diff --git a/.gitignore b/.gitignore index 4476873f71..6032b0d509 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,8 @@ __pycache__/ # Beads / Dolt files (added by bd init) .beads/proxieddb/ .beads.backup-* + +# oh-my-claudecode operational session state (never repo content; +# .omc/skills/ is the sole committable exception per OMC conventions) +.omc/* +!.omc/skills/ diff --git a/.golangci.yml b/.golangci.yml index 5f6486ba8e..0a466a2b24 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,6 +6,7 @@ version: "2" # self-deadlock where the commit that adds this very setting was blocked by it. run: allow-parallel-runners: true + modules-download-mode: readonly severity: default: error diff --git a/.trivyignore.yaml b/.trivyignore.yaml index 6b4f9f49e9..eb6b1f68d3 100644 --- a/.trivyignore.yaml +++ b/.trivyignore.yaml @@ -22,66 +22,66 @@ vulnerabilities: paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: External prebuilt br and kubectl still embed Go 1.26.2 stdlib; remove once each rebuilds against 1.26.3+ (or 1.25.10+). Rebuilt bd/dolt/gh (Go 1.26.5) clear this and are no longer waived. - id: CVE-2026-33814 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: External prebuilt br and kubectl still embed Go 1.26.2 stdlib; remove once each rebuilds against 1.26.3+ (or 1.25.10+). Rebuilt bd/dolt/gh (Go 1.26.5) clear this and are no longer waived. (gc's separate x/net http2 instance is waived below.) - id: CVE-2026-39820 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: External prebuilt br and kubectl still embed Go 1.26.2 stdlib; remove once each rebuilds against 1.26.3+ (or 1.25.10+). Rebuilt bd/dolt/gh (Go 1.26.5) clear this and are no longer waived. - id: CVE-2026-39822 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Go stdlib os.Root symlink CVE (fixed Go 1.26.5 / 1.25.12); external prebuilt br and kubectl still affected pending upstream rebuilds. Rebuilt bd/dolt/gh (Go 1.26.5) clear it and are no longer waived; gc also builds with Go 1.26.5. - id: CVE-2026-39823 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: External prebuilt br and kubectl still embed Go 1.26.2 stdlib; remove once each rebuilds against 1.26.3+ (or 1.25.10+). Rebuilt bd/dolt/gh (Go 1.26.5) clear this and are no longer waived. - id: CVE-2026-39825 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: External prebuilt br and kubectl still embed Go 1.26.2 stdlib; remove once each rebuilds against 1.26.3+ (or 1.25.10+). Rebuilt bd/dolt/gh (Go 1.26.5) clear this and are no longer waived. - id: CVE-2026-39826 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: External prebuilt br and kubectl still embed Go 1.26.2 stdlib; remove once each rebuilds against 1.26.3+ (or 1.25.10+). Rebuilt bd/dolt/gh (Go 1.26.5) clear this and are no longer waived. - id: CVE-2026-39836 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: External prebuilt br and kubectl still embed Go 1.26.2 stdlib; remove once each rebuilds against 1.26.3+ (or 1.25.10+). Rebuilt bd/dolt/gh (Go 1.26.5) clear this and are no longer waived. - id: CVE-2026-42499 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: External prebuilt br and kubectl still embed Go 1.26.2 stdlib; remove once each rebuilds against 1.26.3+ (or 1.25.10+). Rebuilt bd/dolt/gh (Go 1.26.5) clear this and are no longer waived. - id: CVE-2026-42504 paths: - "usr/local/bin/br" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Go stdlib MIME-header DoS (CVE-2026-42504, fixed Go 1.26.4 / 1.25.11); external prebuilt br and kubectl still affected. Rebuilt bd/dolt/gh (Go 1.26.5) clear it and are no longer waived; gc cleared via go.mod toolchain. - id: CVE-2026-27145 paths: - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Go stdlib x509 hostname verification issue (CVE-2026-27145), fixed in Go 1.26.4 / 1.25.11. kubectl in the base image still embeds Go 1.26.2; remove once the bundled CLI rebuilds against 1.26.4+. Rebuilt bd/dolt (Go 1.26.5) cleared and no longer waived. # golang.org/x/text norm.Iter infinite loop, fixed in x/text 0.39.0. Every other # affected binary is fixed in this change: gc via go.mod, and gh/dolt/bd via the @@ -94,92 +94,92 @@ vulnerabilities: - id: CVE-2026-56852 paths: - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/text norm.Iter infinite loop (fixed in 0.39.0). kubectl is external prebuilt; no published kubectl release carries the fix (k8s.io/kubernetes pins x/text v0.33.0 through v1.36.3). Rebuilt gh/dolt/bd and gc are patched and are NOT waived. Remove once Kubernetes releases against x/text >= 0.39.0. - id: CVE-2026-41602 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Latest Dolt 1.88.0 still embeds github.com/apache/thrift v0.13.1; remove after a Dolt release includes thrift 0.23.0 or later. - id: CVE-2026-25680 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles a Go module set with this x/net HTML parsing issue; remove once upstream rebuilds against the fixed x/net release. - id: CVE-2026-25681 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles a Go module set with this x/net HTML rendering issue; remove once upstream rebuilds against the fixed x/net release. - id: CVE-2026-27136 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles a Go module set with this x/net HTML rendering issue; remove once upstream rebuilds against the fixed x/net release. - id: CVE-2026-39821 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles a Go module set with this x/net idna issue; remove once upstream rebuilds against the fixed x/net release. - id: CVE-2026-42502 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles a Go module set with this x/net HTML rendering issue; remove once upstream rebuilds against the fixed x/net release. - id: CVE-2026-42506 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles a Go module set with this x/net HTML rendering issue; remove once upstream rebuilds against the fixed x/net release. - id: CVE-2026-39827 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-39828 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-39829 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-39830 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-39831 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-39832 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-39835 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-42508 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-46595 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. - id: CVE-2026-46597 paths: - "usr/local/bin/dolt" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: Dolt v2.1.7 still bundles golang.org/x/crypto v0.48.0; remove once upstream rebuilds against the fixed release. # The golang.org/x/net (HTML/idna/http2) and golang.org/x/crypto/ssh CVEs in # the same series the dolt entries above waive are also reported against the @@ -193,10 +193,7 @@ vulnerabilities: # golang.org/x/crypto v0.52.0, which clears the gc instance of every # x/crypto/ssh CVE below (fixed in x/crypto 0.52.0) and CVE-2026-33814 # (x/net http2, fixed in 0.53.0); the gc path is therefore dropped from those - # entries so the scan must prove gc is clean rather than mask it. gc is still - # waived for the x/net HTML/idna CVEs fixed only in x/net >= 0.55.0 - # (CVE-2026-25680/25681/27136/39821/42502/42506); drop the gc path from each - # once gc's go.mod bumps golang.org/x/net >= 0.55.0. bd (beads v1.1.0) and + # entries so the scan must prove gc is clean rather than mask it. bd (beads v1.1.0) and # kubectl stay external and base-pre-existing (Container Scan already red on # main, scheduled run 2026-06-24); remove their paths once they rebuild # upstream. TestTrivyIgnoreDropsGCModuleWaiversPastThreshold enforces that no @@ -205,85 +202,85 @@ vulnerabilities: paths: - "usr/local/bin/bd" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/net HTML parsing DoS; base-pre-existing (also red on main 2026-06-24). Present in bd (beads v1.1.0) and kubectl (external, x/net v0.49.0). gc cleared by the golang.org/x/net v0.56.0 bump the x/text 0.39.0 upgrade pulled in. Remove once bd/kubectl rebuild upstream. - id: CVE-2026-25681 paths: - "usr/local/bin/bd" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/net HTML rendering issue; base-pre-existing (also red on main 2026-06-24). Present in bd (beads v1.1.0) and kubectl (external, x/net v0.49.0). gc cleared by the golang.org/x/net v0.56.0 bump the x/text 0.39.0 upgrade pulled in. Remove once bd/kubectl rebuild upstream. - id: CVE-2026-27136 paths: - "usr/local/bin/bd" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/net HTML rendering issue; base-pre-existing (also red on main 2026-06-24). Present in bd (beads v1.1.0) and kubectl (external, x/net v0.49.0). gc cleared by the golang.org/x/net v0.56.0 bump the x/text 0.39.0 upgrade pulled in. Remove once bd/kubectl rebuild upstream. - id: CVE-2026-39821 paths: - "usr/local/bin/bd" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/net/idna issue; base-pre-existing (also red on main 2026-06-24). Present in bd (beads v1.1.0) and kubectl (external, x/net v0.49.0). gc cleared by the golang.org/x/net v0.56.0 bump the x/text 0.39.0 upgrade pulled in. Remove once bd/kubectl rebuild upstream. - id: CVE-2026-42502 paths: - "usr/local/bin/bd" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/net HTML rendering issue; base-pre-existing (also red on main 2026-06-24). Present in bd (beads v1.1.0) and kubectl (external, x/net v0.49.0). gc cleared by the golang.org/x/net v0.56.0 bump the x/text 0.39.0 upgrade pulled in. Remove once bd/kubectl rebuild upstream. - id: CVE-2026-42506 paths: - "usr/local/bin/bd" - "usr/local/bin/kubectl" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/net HTML rendering issue; base-pre-existing (also red on main 2026-06-24). Present in bd (beads v1.1.0) and kubectl (external, x/net v0.49.0). gc cleared by the golang.org/x/net v0.56.0 bump the x/text 0.39.0 upgrade pulled in. Remove once bd/kubectl rebuild upstream. - id: CVE-2026-39827 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-39828 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-39829 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-39830 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-39831 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh CVE; still present in bd (beads v1.1.0). The gc waiver was dropped in the v1.4.0 resync — go.mod now pins golang.org/x/crypto v0.52.0, which fixes it, so gc no longer needs an exception. Remove this entry once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-39832 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh/agent CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-39835 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-42508 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh/knownhosts CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-46595 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. - id: CVE-2026-46597 paths: - "usr/local/bin/bd" - expired_at: 2026-08-07 + expired_at: 2026-09-07 statement: golang.org/x/crypto/ssh CVE; present in bd (beads v1.1.0). gc cleared by the golang.org/x/crypto v0.52.0 bump in this change. Remove once bd rebuilds against x/crypto >= 0.52.0. diff --git a/Makefile b/Makefile index ccffcba76b..dfa00faf59 100644 --- a/Makefile +++ b/Makefile @@ -303,6 +303,7 @@ LINT_BASE ?= origin/main LINT_CHANGED_REF ?= HEAD LINT_CHANGED_SCOPE ?= worktree LINT_FLAGS ?= +QUALITY_GATE_GOFLAGS = $$(go env GOFLAGS | sed -E 's/(^|[[:space:]])-mod=[^[:space:]]+//g') -mod=readonly CI_STATIC_SELECT := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))scripts/ci-static-select CI_STATIC_GO ?= go @@ -311,15 +312,16 @@ lint: lint-full ## lint-full: run golangci-lint across all packages lint-full: $(GOLANGCI_LINT) - $(GOLANGCI_LINT) run $(LINT_FLAGS) ./... + GOFLAGS="$(QUALITY_GATE_GOFLAGS)" $(GOLANGCI_LINT) run $(LINT_FLAGS) ./... ## lint-new: run golangci-lint for issues introduced since LINT_BASE lint-new: $(GOLANGCI_LINT) - $(GOLANGCI_LINT) run $(LINT_FLAGS) --new-from-merge-base=$(LINT_BASE) --whole-files ./... + GOFLAGS="$(QUALITY_GATE_GOFLAGS)" $(GOLANGCI_LINT) run $(LINT_FLAGS) --new-from-merge-base=$(LINT_BASE) --whole-files ./... ## lint-changed: run golangci-lint only for packages touched by changed Go files lint-changed: $(GOLANGCI_LINT) - @case "$(LINT_CHANGED_SCOPE)" in \ + @export GOFLAGS="$(QUALITY_GATE_GOFLAGS)"; \ + case "$(LINT_CHANGED_SCOPE)" in \ staged) \ files="$$(git diff --cached --name-only --diff-filter=ACMRT -- '*.go')"; \ ;; \ @@ -342,10 +344,15 @@ lint-changed: $(GOLANGCI_LINT) echo "lint-changed: no changed Go files"; \ exit 0; \ fi; \ - pkgs="$$(printf '%s\n' "$$files" | sed '/^$$/d' | sort -u | while IFS= read -r file; do dirname "$$file"; done | sort -u | while IFS= read -r dir; do \ + dirs="$$(printf '%s\n' "$$files" | sed '/^$$/d' | sort -u | while IFS= read -r file; do dirname "$$file"; done | sort -u)"; \ + pkgs="$$(for dir in $$dirs; do \ if [ "$$dir" = "." ]; then pkg="."; else pkg="./$$dir"; fi; \ - if go list "$$pkg" >/dev/null 2>&1; then printf '%s\n' "$$pkg"; fi; \ - done | sort -u)"; \ + if ! go list "$$pkg" >/dev/null; then \ + echo "lint-changed: unable to load $$pkg" >&2; \ + exit 1; \ + fi; \ + printf '%s\n' "$$pkg"; \ + done)" || exit $$?; \ if [ -z "$$pkgs" ]; then \ echo "lint-changed: no lintable Go packages"; \ exit 0; \ @@ -355,15 +362,15 @@ lint-changed: $(GOLANGCI_LINT) ## lint-affected: lint packages affected by changed Go build inputs or embedded files lint-affected: $(GOLANGCI_LINT) - @"$(CI_STATIC_SELECT)" lint-affected "$(GOLANGCI_LINT)" "$(CI_STATIC_GO)" $(LINT_FLAGS) + @GOFLAGS="$(QUALITY_GATE_GOFLAGS)" "$(CI_STATIC_SELECT)" lint-affected "$(GOLANGCI_LINT)" "$(CI_STATIC_GO)" $(LINT_FLAGS) ## fmt-check: fail if formatting would change files fmt-check: $(GOLANGCI_LINT) - $(GOLANGCI_LINT) fmt --diff ./... + GOFLAGS="$(QUALITY_GATE_GOFLAGS)" $(GOLANGCI_LINT) fmt --diff ./... ## fmt-check-changed: fail if formatting would change a regular changed Go file fmt-check-changed: $(GOLANGCI_LINT) - @"$(CI_STATIC_SELECT)" fmt-check-changed "$(GOLANGCI_LINT)" + @GOFLAGS="$(QUALITY_GATE_GOFLAGS)" "$(CI_STATIC_SELECT)" fmt-check-changed "$(GOLANGCI_LINT)" ## fmt: auto-fix formatting fmt: $(GOLANGCI_LINT) @@ -371,7 +378,7 @@ fmt: $(GOLANGCI_LINT) ## vet: run go vet vet: - go vet ./... + GOFLAGS="$(QUALITY_GATE_GOFLAGS)" go vet ./... ## TEST_ENV: env -i wrapper for `go test` invocations. Strips host env so ## agent-session vars (GC_CITY, GC_HOME, GC_SESSION_ID, ...) cannot leak into @@ -450,7 +457,7 @@ test-ci-policy: ## cache input hashes over local working files. ## Wrapped in $(TEST_ENV) — see comment above for why. test: test-fsys-darwin-compile - $(TEST_ENV) GC_FAST_UNIT=1 scripts/go-test-observable test -- -p=4 -count=1 -timeout 15m ./... + $(TEST_ENV) GOFLAGS="$(QUALITY_GATE_GOFLAGS)" GC_FAST_UNIT=1 scripts/go-test-observable test -- -p=4 -count=1 -timeout 15m ./... # MAC_UNIT_PKGS excludes cmd/gc from the Mac unit sweep; cmd/gc runs # sharded via the mac-cmd-gc-process CI matrix job instead. @@ -471,7 +478,7 @@ test-fast-parallel: test-fsys-darwin-compile: @tmp=$$(mktemp -d); \ trap 'rm -rf "$$tmp"' EXIT; \ - $(TEST_ENV) GOOS=darwin GOARCH=arm64 go test -c -o "$$tmp/fsys.test" ./internal/fsys + $(TEST_ENV) GOFLAGS="$(QUALITY_GATE_GOFLAGS)" GOOS=darwin GOARCH=arm64 go test -c -o "$$tmp/fsys.test" ./internal/fsys ## test-pack-registry-live: run the opt-in gascity-packs registry canary test-pack-registry-live: diff --git a/TESTING.md b/TESTING.md index 96d2db0f27..967a5c5bda 100644 --- a/TESTING.md +++ b/TESTING.md @@ -451,9 +451,9 @@ all-source audit while staying outside untagged and Small debt. | Ledger kind | Source scope | Resource baseline | Tracking owner | Invariant / resource owner | Migration | Expiry | | --- | --- | --- | --- | --- | --- | --- | -| Audit baseline | all tracked test source | fixed_sleep: 432 calls / 160 files (historical regex census: 447 / 157) | ga-80po0c.2 | tracked test source totals remain visible as audit evidence; ga-80po0c.2 owns this point-in-time source census | P0.4a | 2026-10-01 | +| Audit baseline | all tracked test source | fixed_sleep: 437 calls / 161 files (historical regex census: 447 / 157) | ga-80po0c.2 | tracked test source totals remain visible as audit evidence; ga-80po0c.2 owns this point-in-time source census | P0.4a | 2026-10-01 | | Audit baseline | all tracked test source | listener_helper: 58 calls / 23 files | ga-80po0c.2.2.3 | all-source listener-helper call/file totals cannot drift without an explicit checked policy update; ga-80po0c.2.2.3 owns this all-source audit; tagged calls stay Large and receive no Medium exemption | P0.4c-listener-helper | 2026-10-01 | -| Audit baseline | all tracked test source | subprocess: 552 calls / 168 files (historical regex census: 495 / 135) | ga-80po0c.2 | tracked test source totals remain visible as audit evidence; ga-80po0c.2 owns this point-in-time source census | P0.4a | 2026-10-01 | +| Audit baseline | all tracked test source | subprocess: 555 calls / 168 files (historical regex census: 495 / 135) | ga-80po0c.2 | tracked test source totals remain visible as audit evidence; ga-80po0c.2 owns this point-in-time source census | P0.4a | 2026-10-01 | | Medium owner | `cmd/gc` package `main` | TestMain: environment, tmux | ga-80po0c.2.1 | cmd/gc TestMain is the checked package-level Medium owner for process environment and tmux namespace setup; only declared environment and tmux calls lexically inside TestMain leave Small debt | P0.4b/P0.4c-tmux | 2026-10-01 | | Medium owner | `internal/api` package `api` | TestEveryEmittedErrorCodeIsRegistered: subprocess | ga-80po0c.2.1 | internal/api tracked-source error URN guard is a checked Medium owner; only the git ls-files call lexically inside TestEveryEmittedErrorCodeIsRegistered leaves Small debt | P0.4b | 2026-10-01 | | Medium owner | `internal/doctor` package `doctor` | TestCustomTypesCheck_TableDrift: subprocess | ga-80po0c.2.1 | doctor custom-types config-CSV-vs-table drift detect+heal proof is a checked Medium owner; the bd and dolt subprocesses are confined to TestCustomTypesCheck_TableDrift, which manufactures and heals real table drift against a throwaway store | P0.4b | 2026-10-01 | @@ -472,7 +472,7 @@ all-source audit while staying outside untagged and Small debt. | Small debt ratchet | all untagged test source | net_listen: 93 calls / 35 files (historical regex census: 92 / 34) | ga-80po0c.2.2.2 | untagged Small stream-listener call/file totals cannot grow; reductions must lower this baseline; non-Medium lexical owners move stream-listener tests to exact Medium ownership or replace the listener | P0.4c-listener | 2026-10-01 | | Small debt ratchet | all untagged test source | net_listen_config: 1 calls / 1 files | ga-80po0c.2.2.2 | untagged Small net.ListenConfig listener call/file totals cannot grow; reductions must lower this baseline; non-Medium lexical owners move ListenConfig-backed tests to exact Medium ownership or replace the listener | P0.4c-listener | 2026-10-01 | | Small debt ratchet | all untagged test source | net_listen_packet: 3 calls / 2 files | ga-80po0c.2.2.2 | untagged Small packet-listener call/file totals cannot grow; reductions must lower this baseline; non-Medium lexical owners move packet-listener tests to exact Medium ownership or replace the listener | P0.4c-listener | 2026-10-01 | -| Small debt ratchet | all untagged test source | subprocess: 407 calls / 114 files (historical regex census: 394 / 105) | ga-80po0c.2.1 | untagged Small subprocess call/file totals cannot grow; reductions must lower this baseline; non-Medium lexical owners remove or replace each process call site | D1/D2/D5/D6/E6 | 2026-10-01 | +| Small debt ratchet | all untagged test source | subprocess: 408 calls / 114 files (historical regex census: 394 / 105) | ga-80po0c.2.1 | untagged Small subprocess call/file totals cannot grow; reductions must lower this baseline; non-Medium lexical owners remove or replace each process call site | D1/D2/D5/D6/E6 | 2026-10-01 | | Small debt ratchet | all untagged test source | syscall_listen: 1 calls / 1 files | ga-80po0c.2.2 | untagged Small syscall.Listen call/file totals cannot grow; reductions must lower this baseline; non-Medium lexical owners move syscall-backed listener tests to exact Medium ownership or replace the listener | P0.4c | 2026-10-01 | | Small debt ratchet | all untagged test source | tmux: 0 calls / 0 files | ga-80po0c.2.2.1 | untagged Small tmux dependency call/file totals cannot grow; reductions must lower this baseline; non-Medium lexical owners replace tmux with a fake executor or declare exact isolated ownership | P0.4c-tmux | 2026-10-01 | | Source debt ratchet | `cmd/gc` untagged test source | cwd: 174 calls / 16 files (historical regex census: 98 / 13) | ga-80po0c.2.3 | untagged cmd/gc cwd call/file totals cannot grow; reductions must lower this baseline; cmd/gc callers restore or eliminate every recognized cwd mutation | D5/D6 | 2026-10-01 | @@ -484,7 +484,7 @@ all-source audit while staying outside untagged and Small debt. | Source debt ratchet | all untagged test source | net_listen: 95 calls / 36 files (historical regex census: 92 / 34) | ga-80po0c.2.2.2 | untagged stream-listener call/file totals cannot grow; reductions must lower this baseline; each owning test closes its stream listener and removes duplicate listener-backed coverage | P0.4c-listener | 2026-10-01 | | Source debt ratchet | all untagged test source | net_listen_config: 1 calls / 1 files | ga-80po0c.2.2.2 | untagged net.ListenConfig listener call/file totals cannot grow; reductions must lower this baseline; each owning test closes its configured listener and removes duplicate listener-backed coverage | P0.4c-listener | 2026-10-01 | | Source debt ratchet | all untagged test source | net_listen_packet: 3 calls / 2 files | ga-80po0c.2.2.2 | untagged packet-listener call/file totals cannot grow; reductions must lower this baseline; each owning test closes its packet listener and removes duplicate listener-backed coverage | P0.4c-listener | 2026-10-01 | -| Source debt ratchet | all untagged test source | subprocess: 413 calls / 117 files (historical regex census: 380 / 98) | ga-80po0c.2 | untagged subprocess call/file totals cannot grow; reductions must lower this baseline; each process-owning test removes or replaces its source call site | D1/D2/D5/D6/E6 | 2026-10-01 | +| Source debt ratchet | all untagged test source | subprocess: 414 calls / 117 files (historical regex census: 380 / 98) | ga-80po0c.2 | untagged subprocess call/file totals cannot grow; reductions must lower this baseline; each process-owning test removes or replaces its source call site | D1/D2/D5/D6/E6 | 2026-10-01 | | Source debt ratchet | all untagged test source | syscall_listen: 1 calls / 1 files | ga-80po0c.2.2 | untagged syscall.Listen call/file totals cannot grow; reductions must lower this baseline; each owning test closes its listening file descriptor and removes duplicate listener-backed coverage | P0.4c | 2026-10-01 | | Source debt ratchet | all untagged test source | tmux: 6 calls / 2 files | ga-80po0c.2.2.1 | untagged tmux dependency call/file totals cannot grow; reductions must lower this baseline; each owning test confines tmux processes and sockets to its isolated namespace and cleanup | P0.4c-tmux | 2026-10-01 | diff --git a/cmd/gc/api_state.go b/cmd/gc/api_state.go index d4a9e8160f..ecd78fdf7d 100644 --- a/cmd/gc/api_state.go +++ b/cmd/gc/api_state.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" "reflect" + "sort" "strconv" "strings" "sync" @@ -25,6 +26,7 @@ import ( "github.com/gastownhall/gascity/internal/configedit" "github.com/gastownhall/gascity/internal/emergency" "github.com/gastownhall/gascity/internal/events" + "github.com/gastownhall/gascity/internal/executionevent" "github.com/gastownhall/gascity/internal/extmsg" "github.com/gastownhall/gascity/internal/fsys" "github.com/gastownhall/gascity/internal/git" @@ -448,6 +450,11 @@ func (cs *controllerState) startBeadEventWatcher(ctx context.Context) { if ep == nil { return } + // A controller can crash after the durable bead.closed journal append but + // before its best-effort lifecycle append. The normal watcher intentionally + // begins at the boot-time journal head, so reconcile closed graph.v2 steps + // before tailing to repair that otherwise permanent gap. + cs.reconcileExecutionCompletions() seq := cs.beadEventStartSeq // A captured seq of 0 with OK=true means the log was genuinely empty at // construction — Watch(0) then replays exactly the prime-window events and @@ -499,6 +506,77 @@ func (cs *controllerState) startBeadEventWatcher(ctx context.Context) { }() } +// reconcileExecutionCompletions repairs graph.v2 completion facts from the +// authoritative graph store. It is safe to call at startup and on patrol ticks: +// ReconcileCompleted uses the event journal's exact fact as its idempotency +// record, so repeated passes do not duplicate lifecycle events. +func (cs *controllerState) reconcileExecutionCompletions() { + ep := cs.EventProvider() + if ep == nil { + return + } + + // Graph coordination may be relocated from the city work store, while + // graph.v2 executions normally live in the individual rig work stores. + // Scan both surfaces in stable order, collapsing wrappers first so aliases + // are not scanned more than once. + cs.mu.RLock() + stores := []beads.Store{ + resolveGraphStore(cs.cityBeadStore, cs.cfg, cs.cityPath, cs.eventProv), + cs.cityBeadStore, + } + rigStores := make(map[string]beads.Store, len(cs.beadStores)) + for name, store := range cs.beadStores { + rigStores[name] = store + } + cs.mu.RUnlock() + + rigNames := make([]string, 0, len(rigStores)) + for name := range rigStores { + rigNames = append(rigNames, name) + } + sort.Strings(rigNames) + for _, name := range rigNames { + stores = append(stores, rigStores[name]) + } + + seen := make(map[uintptr]struct{}, len(stores)) + graphStores := make([]beads.GraphStore, 0, len(stores)) + for _, store := range stores { + store = uncachedBeadStore(store) + if store == nil { + continue + } + if key, ok := storePointerKey(store); ok { + if _, duplicate := seen[key]; duplicate { + continue + } + seen[key] = struct{}{} + } + graphStores = append(graphStores, beads.GraphStore{Store: store}) + } + executionevent.ReconcileCompletedStores(ep, graphStores, "execution-reconcile") +} + +// uncachedBeadStore peels the controller's policy/cache read layers so a +// recovery projection can inspect closed authoritative rows. The normal active +// cache prime need not include closed beads, and therefore cannot safely drive +// lifecycle gap repair. +func uncachedBeadStore(store beads.Store) beads.Store { + for range 8 { + if base, _, ok := unwrapBeadPolicyStore(store); ok { + store = base + continue + } + cached, ok := store.(*beads.CachingStore) + if !ok || cached == nil || cached.Backing() == nil { + return store + } + store = cached.Backing() + } + return store +} + // startMaintenanceLoop launches the periodic Dolt store maintenance // loop when [maintenance.dolt] enabled=true in city.toml. When the // section is omitted or enabled=false, this is a no-op — the caller @@ -578,6 +656,13 @@ func (cs *controllerState) applyBeadEventToStores(evt events.Event) { cs.Poke() } if evt.Type == events.BeadClosed && evt.Subject != "" && len(stores) > 0 { + rec := events.Discard + cs.mu.RLock() + if cs.eventProv != nil { + rec = cs.eventProv + } + cs.mu.RUnlock() + executionevent.EmitCompletedFromClosedNotification(rec, cs.GraphBeadStore().Store, evt.Payload, evt.Actor) cs.runBeadCloseAutoclose(evt.Subject, stores[0], storeRef) } } diff --git a/cmd/gc/api_state_test.go b/cmd/gc/api_state_test.go index 387a1353cd..b96a3dfe76 100644 --- a/cmd/gc/api_state_test.go +++ b/cmd/gc/api_state_test.go @@ -2053,6 +2053,147 @@ func TestControllerStateAppliesCacheReconcileBeadEventsToStores(t *testing.T) { } } +func TestControllerStateEmitsCompletedFromAuthoritativeGraphStepClose(t *testing.T) { + store := beads.NewMemStore() + root, err := store.Create(beads.Bead{ID: "gcg-run", Metadata: map[string]string{ + "gc.kind": "workflow", "gc.formula_contract": "graph.v2", + }}) + if err != nil { + t.Fatal(err) + } + step, err := store.Create(beads.Bead{ID: "gcg-retry-attempt", Metadata: map[string]string{ + "gc.root_bead_id": root.ID, "gc.step_id": "build", "gc.session_id": "gcs-session", "gc.native_step_dependencies.v1": `["prepare"]`, + }}) + if err != nil { + t.Fatal(err) + } + if err := store.Close(step.ID); err != nil { + t.Fatal(err) + } + step, err = store.Get(step.ID) + if err != nil { + t.Fatal(err) + } + payload, err := json.Marshal(step) + if err != nil { + t.Fatal(err) + } + rec := events.NewFake() + cs := &controllerState{cityBeadStore: store, eventProv: rec} + cs.applyBeadEventToStores(events.Event{Type: events.BeadClosed, Actor: "bd-close", Subject: step.ID, Payload: payload}) + var completed []events.Event + for _, event := range rec.Events { + if event.Type == events.ExecutionStepCompleted { + completed = append(completed, event) + } + } + if len(completed) != 1 || completed[0].Subject != step.ID || completed[0].RunID != root.ID || completed[0].SessionID != "gcs-session" || completed[0].StepID != "build" { + t.Fatalf("completed lifecycle events = %#v", completed) + } +} + +func TestControllerStateBeadEventWatcherReconcilesCompletedCloseAfterRestart(t *testing.T) { + backing := beads.NewMemStore() + root, err := backing.Create(beads.Bead{ID: "gcg-run", Metadata: map[string]string{ + "gc.kind": "workflow", "gc.formula_contract": "graph.v2", + }}) + if err != nil { + t.Fatal(err) + } + step, err := backing.Create(beads.Bead{ID: "gcg-retry-attempt", Metadata: map[string]string{ + "gc.root_bead_id": root.ID, "gc.step_id": "build", "gc.session_id": "gcs-session", + }}) + if err != nil { + t.Fatal(err) + } + if err := backing.Close(step.ID); err != nil { + t.Fatal(err) + } + step, err = backing.Get(step.ID) + if err != nil { + t.Fatal(err) + } + payload, err := json.Marshal(step) + if err != nil { + t.Fatal(err) + } + + // The close is already in the authoritative journal when this controller + // starts. Its watcher cursor begins at that journal head, reproducing a + // process crash after bead.closed but before step_completed was recorded. + ep := events.NewFake() + ep.Record(events.Event{Type: events.BeadClosed, Actor: "bd-close", Subject: step.ID, Payload: payload}) + prevCityStore := newControllerStateOpenCityStore + newControllerStateOpenCityStore = func(string, gate.Mode) (beads.StoreOpenResult, error) { + return beads.StoreOpenResult{Store: backing}, nil + } + t.Cleanup(func() { newControllerStateOpenCityStore = prevCityStore }) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + cs := newControllerState(ctx, &config.City{Workspace: config.Workspace{Name: "test-city"}}, runtime.NewFake(), ep, "test-city", t.TempDir()) + cs.startBeadEventWatcher(ctx) + + got, listErr := ep.List(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if listErr != nil { + t.Fatal(listErr) + } + if len(got) != 1 { + t.Fatalf("reconciled completed events = %#v, want one", got) + } + if got[0].RunID != root.ID || got[0].SessionID != "gcs-session" || got[0].StepID != "build" { + t.Fatalf("reconciled completed event = %#v", got[0]) + } +} + +func TestControllerStateReconcileExecutionCompletionsScansConfiguredRigStores(t *testing.T) { + cityStore := beads.NewMemStore() + rigStore := beads.NewMemStore() + root, err := rigStore.Create(beads.Bead{ID: "gcg-run", Metadata: map[string]string{ + "gc.kind": "workflow", "gc.formula_contract": "graph.v2", + }}) + if err != nil { + t.Fatal(err) + } + step, err := rigStore.Create(beads.Bead{ID: "gcg-build-attempt", Metadata: map[string]string{ + "gc.root_bead_id": root.ID, "gc.step_id": "build", "gc.session_id": "gcs-session", + }}) + if err != nil { + t.Fatal(err) + } + if err := rigStore.Close(step.ID); err != nil { + t.Fatal(err) + } + + ep := events.NewFake() + cs := &controllerState{ + cfg: &config.City{Rigs: []config.Rig{{Name: "gascity"}}}, + cityBeadStore: cityStore, + beadStores: map[string]beads.Store{"gascity": rigStore}, + eventProv: ep, + } + cs.reconcileExecutionCompletions() + + completed, err := ep.List(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if err != nil { + t.Fatal(err) + } + if len(completed) != 1 { + t.Fatalf("completed events after rig reconciliation = %#v, want one", completed) + } + if got := completed[0]; got.RunID != root.ID || got.SessionID != "gcs-session" || got.StepID != "build" { + t.Fatalf("reconciled completed event = %#v", got) + } + + cs.reconcileExecutionCompletions() + completed, err = ep.List(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if err != nil { + t.Fatal(err) + } + if len(completed) != 1 { + t.Fatalf("completed events after repeated rig reconciliation = %#v, want exact-fact no-op", completed) + } +} + func TestWrapWithCachingStoreCachesNonBdStore(t *testing.T) { backing := beads.NewMemStore() created, err := backing.Create(beads.Bead{Title: "non-bd backing"}) diff --git a/cmd/gc/bd_env.go b/cmd/gc/bd_env.go index 378cd2c9d9..1d1c9dcbbb 100644 --- a/cmd/gc/bd_env.go +++ b/cmd/gc/bd_env.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "os" + "os/exec" "path/filepath" "sort" "strconv" @@ -47,6 +48,13 @@ func postgresCredentialResolvedKey(cityPath string, payload pgauth.PostgresCrede // Env is rebuilt on each call so GC_DOLT_PORT reflects the current managed // dolt port (which can change across city restarts). func bdCommandRunnerForCity(cityPath string) beads.CommandRunner { + completeBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(cityPath)) + if err != nil { + return func(_, _ string, _ ...string) ([]byte, error) { return nil, err } + } + if completeBinding { + return bdContextCommandRunnerForCity(cityPath) + } return bdCommandRunnerWithManagedRetryErr(cityPath, func(dir string) (map[string]string, error) { env, err := bdRuntimeEnvWithError(cityPath) env["BEADS_DIR"] = filepath.Join(dir, ".beads") @@ -54,6 +62,95 @@ func bdCommandRunnerForCity(cityPath string) beads.CommandRunner { }) } +// bdContextCommandRunnerForCity delegates complete external bindings to the +// workspace-pinned bd without projecting or recovering a managed backend. It +// skips managed recovery, not resilience: the scope transport breaker, +// admission semaphore, and outcome recording apply exactly as on the managed +// path — a wedged external endpoint is precisely the outage shape the breaker +// exists to fail fast on (ga-2bo4m), and without admission each controller +// tick would pile another bd subprocess onto a store already known wedged. +func bdContextCommandRunnerForCity(cityPath string) beads.CommandRunner { + return func(dir, name string, args ...string) ([]byte, error) { + env := cityRuntimeEnvMapForCity(cityPath) + bdBin, err := workspacePinnedBdBinary(cityPath) + if err != nil { + return nil, err + } + env["BD_BIN"] = bdBin + env["BEADS_DIR"] = filepath.Join(dir, ".beads") + env["GC_RIG"] = "" + env["GC_RIG_ROOT"] = "" + env["BEADS_DOLT_AUTO_START"] = "0" + env["BD_EXPORT_AUTO"] = "false" + credentialsFile := strings.TrimSpace(env["BEADS_CREDENTIALS_FILE"]) + if credentialsFile == "" { + credentialsFile = strings.TrimSpace(ambientNativeDoltOpenEnv("BEADS_CREDENTIALS_FILE")) + } + setExecProjectedBackendEnvEmpty(env) + if credentialsFile != "" { + env["BEADS_CREDENTIALS_FILE"] = credentialsFile + } + var breaker *resilience.Breaker + if name == "bd" { + breaker = bdScopeBreaker(cityPath, dir) + if !breaker.Allow() { + return nil, fmt.Errorf("bd %s: scope %s: circuit breaker open after consecutive transport failures: %w", + strings.Join(args, " "), dir, beads.ErrStoreUnavailable) + } + release, admitted := bdAdmissionForCity(cityPath).acquire(bdAdmissionScope(cityPath, dir)) + if !admitted { + return nil, fmt.Errorf("bd %s: scope %s: admission saturated, failing fast to protect the controller tick: %w", + strings.Join(args, " "), dir, beads.ErrStoreUnavailable) + } + defer release() + } + execName := name + if execName == "bd" && bdBin != "" { + execName = bdBin + } + out, err := beadsExecCommandRunnerWithEnv(env)(dir, execName, args...) + if breaker != nil { + // No managed retry on this path, so this invocation's outcome is + // the final word: a per-command deadline kill or a transport-class + // error counts one consecutive failure; anything the store + // answered records a healthy transport. + recordBdBreakerOutcome(breaker, + bdInvocationTimedOut(name, err) || bdTransportRetryableError(cityPath, dir, env, err)) + } + return out, err + } +} + +// workspacePinnedBdBinary resolves bd only from an explicitly configured +// workspace PATH. An unconfigured workspace retains the ambient executable +// lookup performed by the caller. +func workspacePinnedBdBinary(cityPath string) (string, error) { + if _, err := os.Stat(filepath.Join(cityPath, "city.toml")); errors.Is(err, os.ErrNotExist) { + return "", nil + } else if err != nil { + return "", err + } + cfg, err := loadCityConfig(cityPath, io.Discard) + if err != nil { + return "", err + } + _, configured := cfg.Workspace.Env["PATH"] + if !configured { + return "", nil + } + for _, dir := range filepath.SplitList(expandEnvMap(cfg.Workspace.Env)["PATH"]) { + dir = strings.TrimSpace(dir) + if !filepath.IsAbs(dir) { + continue + } + candidate, err := exec.LookPath(filepath.Join(dir, "bd")) + if err == nil && filepath.IsAbs(candidate) { + return candidate, nil + } + } + return "", fmt.Errorf("workspace.env PATH is configured but contains no executable bd at an absolute path") +} + func bdStoreForCity(dir, cityPath string) *beads.BdStore { cfg, err := loadCityConfig(cityPath, io.Discard) if err != nil { @@ -351,6 +448,27 @@ func applyCanonicalDoltAuthEnv(env map[string]string, cityPath, scopeRoot string applyResolvedDoltAuthEnv(env, authScopeRoot, strings.TrimSpace(target.User)) } +func applyCompleteNonDoltStorageBindingEnv(env map[string]string, cityPath, scopeRoot string) (bool, error) { + completeBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(scopeRoot)) + if err != nil || !completeBinding { + return completeBinding, err + } + credentialsFile := strings.TrimSpace(env["BEADS_CREDENTIALS_FILE"]) + if credentialsFile == "" { + credentialsFile = strings.TrimSpace(ambientNativeDoltOpenEnv("BEADS_CREDENTIALS_FILE")) + } + setExecProjectedBackendEnvEmpty(env) + if credentialsFile != "" { + env["BEADS_CREDENTIALS_FILE"] = credentialsFile + } + bdBin, err := workspacePinnedBdBinary(cityPath) + if err != nil { + return true, err + } + env["BD_BIN"] = bdBin + return true, nil +} + // applyCanonicalScopeBackendEnv dispatches to the appropriate backend // helper based on the scope's MetadataState.Backend. // @@ -367,6 +485,11 @@ func applyCanonicalScopeBackendEnv(env map[string]string, cityPath, scopeRoot st if resolved.Kind != contract.ScopeConfigAuthoritative { return false, nil } + if completeBinding, err := applyCompleteNonDoltStorageBindingEnv(env, cityPath, scopeRoot); err != nil { + return true, err + } else if completeBinding { + return true, nil + } meta, _, metaErr := contract.LoadMetadataState(fsys.OSFS{}, scopeMetadataJSONPath(scopeRoot)) if metaErr != nil { return true, metaErr @@ -418,6 +541,11 @@ func applyCanonicalScopeBackendEnv(env map[string]string, cityPath, scopeRoot st } func applyCityPostgresBackendEnv(env map[string]string, cityPath string) (bool, error) { + if completeBinding, err := applyCompleteNonDoltStorageBindingEnv(env, cityPath, cityPath); err != nil { + return true, err + } else if completeBinding { + return true, nil + } resolved, err := contract.ResolveScopeConfigState(fsys.OSFS{}, cityPath, cityPath, "") if err != nil { return false, err diff --git a/cmd/gc/bd_env_test.go b/cmd/gc/bd_env_test.go index 032263aa63..1355c405a9 100644 --- a/cmd/gc/bd_env_test.go +++ b/cmd/gc/bd_env_test.go @@ -78,6 +78,116 @@ func requireErrorContains(t *testing.T, err error, want string) { } } +func TestBdCommandRunnerForCityCompleteStorageBindingSkipsManagedRetry(t *testing.T) { + cityPath := t.TempDir() + binDir := t.TempDir() + bdPath := filepath.Join(binDir, "bd") + if err := os.WriteFile(bdPath, []byte("#!/bin/sh\necho clean-runner-sentinel credentials=$BEADS_CREDENTIALS_FILE >&2\nexit 17\n"), 0o755); err != nil { + t.Fatal(err) + } + cityTOML := fmt.Sprintf("[workspace]\nname = \"demo\"\n[workspace.env]\nPATH = %q\n", binDir+string(os.PathListSeparator)+"$PATH") + if err := os.WriteFile(filepath.Join(cityPath, "city.toml"), []byte(cityTOML), 0o600); err != nil { + t.Fatal(err) + } + if err := os.MkdirAll(filepath.Join(cityPath, ".beads"), 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(scopeMetadataJSONPath(cityPath), []byte(`{"backend":"postgres","storage_endpoint":"opaque-remote","storage_database":"work","dolt_mode":"server"}`), 0o600); err != nil { + t.Fatal(err) + } + credentialsPath := filepath.Join(t.TempDir(), "custom-credentials") + t.Setenv("BEADS_CREDENTIALS_FILE", credentialsPath) + + _, err := bdCommandRunnerForCity(cityPath)(cityPath, "bd", "status") + if err == nil { + t.Fatal("runner error = nil, want fake bd failure") + } + if !strings.Contains(err.Error(), "clean-runner-sentinel") { + t.Fatalf("runner error = %q, want fake bd stderr", err) + } + if !strings.Contains(err.Error(), "credentials="+credentialsPath) { + t.Fatalf("runner error = %q, want preserved credential file", err) + } + if strings.Contains(err.Error(), "managed recovery") || strings.Contains(err.Error(), "postgres storage binding") { + t.Fatalf("runner error = %q, managed retry path must not run", err) + } +} + +func TestRuntimeEnvDelegatesCompleteStorageBindingToBd(t *testing.T) { + t.Setenv("GC_BEADS", "bd") + cityPath := t.TempDir() + binDir := t.TempDir() + bdPath := filepath.Join(binDir, "bd") + if err := os.WriteFile(bdPath, []byte("#!/bin/sh\nexit 0\n"), 0o755); err != nil { + t.Fatal(err) + } + cityTOML := fmt.Sprintf("[workspace]\nname = \"demo\"\n[workspace.env]\nPATH = %q\n", binDir+string(os.PathListSeparator)+"$PATH") + if err := os.WriteFile(filepath.Join(cityPath, "city.toml"), []byte(cityTOML), 0o600); err != nil { + t.Fatal(err) + } + if err := os.MkdirAll(filepath.Join(cityPath, ".beads"), 0o700); err != nil { + t.Fatal(err) + } + metadata := []byte(`{"backend":"postgres","storage_endpoint":"postgres://beads@db.example.test:5432","storage_database":"beads_pg","dolt_mode":"server","dolt_database":"legacy_hq","unknown":"preserve-me"}`) + if err := os.WriteFile(scopeMetadataJSONPath(cityPath), metadata, 0o600); err != nil { + t.Fatal(err) + } + + projectedKeys := append([]string{}, projectedDoltEnvKeys...) + projectedKeys = append(projectedKeys, projectedPostgresEnvKeys...) + projectedKeys = append(projectedKeys, projectedBeadsBackendEnvKeys...) + for _, key := range projectedKeys { + t.Setenv(key, "stale-projection") + } + credentialsPath := filepath.Join(t.TempDir(), "custom-credentials") + t.Setenv("BEADS_CREDENTIALS_FILE", credentialsPath) + + assertNoProjection := func(t *testing.T, env map[string]string) { + t.Helper() + for _, key := range projectedKeys { + if key == "BEADS_CREDENTIALS_FILE" { + continue + } + if got := env[key]; got != "" { + t.Errorf("env[%q] = %q, want absent for bd-owned storage binding", key, got) + } + } + if got := env["BEADS_CREDENTIALS_FILE"]; got != credentialsPath { + t.Errorf("BEADS_CREDENTIALS_FILE = %q, want %q", got, credentialsPath) + } + if got := env["BD_BIN"]; got != bdPath { + t.Errorf("BD_BIN = %q, want workspace-pinned %q", got, bdPath) + } + } + + env, err := bdRuntimeEnvWithError(cityPath) + if err != nil { + t.Fatalf("bdRuntimeEnvWithError: %v", err) + } + assertNoProjection(t, env) + + rigPath := filepath.Join(cityPath, "rigs", "remote") + if err := os.MkdirAll(filepath.Join(rigPath, ".beads"), 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(rigPath, ".beads", "config.yaml"), []byte("gc.endpoint_origin: inherited_city\n"), 0o600); err != nil { + t.Fatal(err) + } + rigEnv, err := sessionBackendEnvWithError(cityPath, rigPath, []config.Rig{{Name: "remote", Path: rigPath}}) + if err != nil { + t.Fatalf("sessionBackendEnvWithError(inherited rig): %v", err) + } + assertNoProjection(t, rigEnv) + + gotMetadata, err := os.ReadFile(scopeMetadataJSONPath(cityPath)) + if err != nil { + t.Fatal(err) + } + if string(gotMetadata) != string(metadata) { + t.Fatalf("metadata changed: got %s, want %s", gotMetadata, metadata) + } +} + // ── Dolt config wiring tests (issue 011) ────────────────────────────── func TestCityRuntimeProcessEnvStripsAmbientGCDolt(t *testing.T) { @@ -4085,11 +4195,10 @@ func TestBdRuntimeEnvDoesNotDefaultBeadsActorWhenUnset(t *testing.T) { } } -// TestBdRuntimeEnvPreservesInheritedBeadsActor verifies that session -// contexts (template_resolve.go sets BEADS_ACTOR=) and exec -// orders (orderExecEnv sets BEADS_ACTOR=order:) are not clobbered by -// the neutral bd runtime env. The key is omitted so the inherited value -// passes through mergeEnv unchanged. +// TestBdRuntimeEnvPreservesInheritedBeadsActor verifies that the authoritative +// session runtime context and exec orders can set BEADS_ACTOR without the +// neutral bd runtime env clobbering it. The neutral map omits the key so the +// inherited value passes through mergeEnv unchanged. func TestBdRuntimeEnvPreservesInheritedBeadsActor(t *testing.T) { t.Setenv("GC_BEADS", "bd") t.Setenv("GC_DOLT", "skip") diff --git a/cmd/gc/bd_mistyped_metadata.go b/cmd/gc/bd_mistyped_metadata.go new file mode 100644 index 0000000000..d513f86d41 --- /dev/null +++ b/cmd/gc/bd_mistyped_metadata.go @@ -0,0 +1,16 @@ +package main + +import ( + "github.com/gastownhall/gascity/internal/bdflags" +) + +// mistypedMetadataPairRefusal reports whether a `gc bd` invocation carries +// `--set-metadata` pairs bd would silently drop, and the message to print. +// +// gc bd writes exec raw bd, so nothing upstream of this sees them. It depends +// only on internal/bdflags — the upstream-owned source of truth for bd's flag +// names — so this guard carries no fork-local dependency. +func mistypedMetadataPairRefusal(bdArgs []string) (string, bool) { + verb, verbArgs := bdflags.SplitGlobalFlags(bdArgs) + return bdflags.DroppedMetadataRefusal("gc bd", verb, verbArgs) +} diff --git a/cmd/gc/bd_mistyped_metadata_test.go b/cmd/gc/bd_mistyped_metadata_test.go new file mode 100644 index 0000000000..ea77e6a8c1 --- /dev/null +++ b/cmd/gc/bd_mistyped_metadata_test.go @@ -0,0 +1,129 @@ +package main + +import ( + "bytes" + "strings" + "testing" +) + +// TestGCBdRefusesMistypedMetadataPairs pins that `gc bd update` refuses a bare +// key=value in bd's positional issue-id slot. +// +// `--set-metadata` is a repeatable stringArray taking ONE pair per flag, so in +// `--set-metadata a=1 b=2 c=3` only `a=1` is the flag's value. bd reads `b=2` and +// `c=3` as issue ids, fails to resolve them, prints the failures to stderr — and +// still prints its success line and EXITS 0. Measured on bd 1.1.0 and unchanged +// in 1.1.2: six pairs in, one pair written, exit 0, so no caller can tell. +// +// gc bd writes exec raw bd rather than the routed fastpath, so the classifier's +// guard does not cover this path; it needs its own. The refusal must come before +// any store work, so nothing is written and the exit code is honest. +func TestGCBdRefusesMistypedMetadataPairs(t *testing.T) { + cases := []struct { + name string + args []string + }{ + {"trailing pairs", []string{"update", "bd-1", "--set-metadata", "a=1", "b=2", "c=3"}}, + {"one trailing pair", []string{"update", "bd-1", "--set-metadata", "a=1", "b=2"}}, + {"inline flag form", []string{"update", "bd-1", "--set-metadata=a=1", "b=2"}}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + var stdout, stderr bytes.Buffer + code := doBd(tc.args, &stdout, &stderr) + if code == 0 { + t.Fatalf("doBd(%v) = 0, want non-zero; stderr=%q", tc.args, stderr.String()) + } + msg := stderr.String() + if !strings.Contains(msg, "--set-metadata") { + t.Errorf("stderr %q does not name --set-metadata", msg) + } + // The message must name the offending token, so the caller can see + // which pair bd would have dropped. + if !strings.Contains(msg, "b=2") { + t.Errorf("stderr %q does not name the dropped pair b=2", msg) + } + }) + } +} + +// TestGCBdRefusesMistypedMetadataPairsBehindGlobalFlags pins the exit-code +// contract through the path that used to disarm the guard. +// +// The guard is keyed off the bd subcommand, and bd's global value-flags sit +// BEFORE the subcommand. Locating the verb as the first non-dash token read +// `bob` out of `bd --actor bob update …`, so the verb was not "update", the +// refusal did not fire, and raw bd performed exactly the silent 1-of-N write +// plus exit 0 the guard exists to prevent. +// +// The exit code is the whole contract: this defect survives precisely because +// everything downstream trusts an exit code that lies. So this asserts the code, +// not just the message — and the guard runs before resolveBdCity, so a refusal +// here is also proof that no store was opened and nothing was written. +func TestGCBdRefusesMistypedMetadataPairsBehindGlobalFlags(t *testing.T) { + cases := []struct { + name string + args []string + }{ + {"--actor", []string{"--actor", "bob", "update", "bd-1", "--set-metadata", "a=1", "b=2"}}, + {"-C dir", []string{"-C", "/some/dir", "update", "bd-1", "--set-metadata", "a=1", "b=2"}}, + {"--db path", []string{"--db", "/x/y.db", "update", "bd-1", "--set-metadata", "a=1", "b=2"}}, + {"--directory", []string{"--directory", "/d", "update", "bd-1", "--set-metadata", "a=1", "b=2"}}, + {"--dolt-auto-commit", []string{"--dolt-auto-commit", "off", "update", "bd-1", "--set-metadata", "a=1", "b=2"}}, + {"stacked globals", []string{"--actor", "bob", "--json", "-C", "/d", "update", "bd-1", "--set-metadata", "a=1", "b=2"}}, + {"inline global", []string{"--actor=bob", "update", "bd-1", "--set-metadata", "a=1", "b=2"}}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + var stdout, stderr bytes.Buffer + code := doBd(tc.args, &stdout, &stderr) + if code == 0 { + t.Fatalf("doBd(%v) = 0, want non-zero; stderr=%q", tc.args, stderr.String()) + } + msg := stderr.String() + if !strings.Contains(msg, "would be dropped") { + t.Fatalf("doBd(%v) exited %d but not via the mistyped-pair guard; stderr=%q", tc.args, code, msg) + } + if !strings.Contains(msg, "b=2") { + t.Errorf("stderr %q does not name the dropped pair b=2", msg) + } + }) + } +} + +// TestGCBdAllowsCorrectMetadataForms pins that the guard does not fire on the +// shapes that actually work: one --set-metadata per pair, a plain id, and +// several ids sharing one pair (bd applies the update to every id). These must +// get past the guard and continue into normal resolution — the guard is not +// allowed to become a reason a working invocation stops working. +func TestGCBdAllowsCorrectMetadataForms(t *testing.T) { + // These forms deliberately run PAST the guard, so pin an explicit non-city + // temp dir rather than leaning on ambient state: doBd then fails + // deterministically at resolveBdCity, before any store is opened or bd is + // exec'd. TestMain's env scrub and the test-binary refusal of ambient + // upward discovery cover this today; pinning it here keeps the isolation + // local to the test instead of a property of that scrub list, and matches + // the idiom every sibling test in cmd_bd_test.go uses. + t.Setenv("GC_CITY_PATH", t.TempDir()) + + cases := []struct { + name string + args []string + }{ + {"repeated flag", []string{"update", "bd-1", "--set-metadata", "a=1", "--set-metadata", "b=2"}}, + {"single pair", []string{"update", "bd-1", "--set-metadata", "a=1"}}, + {"multi-id one pair", []string{"update", "bd-1", "bd-2", "--set-metadata", "a=1"}}, + {"flag value before id", []string{"update", "--set-metadata", "a=1", "bd-1"}}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + var stdout, stderr bytes.Buffer + _ = doBd(tc.args, &stdout, &stderr) + // The call fails later for want of a city/store in this environment; + // what matters is that it was NOT stopped by the mistyped-pair guard. + if strings.Contains(stderr.String(), "would be dropped") { + t.Fatalf("guard fired on a valid form %v: %s", tc.args, stderr.String()) + } + }) + } +} diff --git a/cmd/gc/bd_timeout_classification_test.go b/cmd/gc/bd_timeout_classification_test.go index b968f147c9..778388505e 100644 --- a/cmd/gc/bd_timeout_classification_test.go +++ b/cmd/gc/bd_timeout_classification_test.go @@ -3,6 +3,8 @@ package main import ( "errors" "fmt" + "os" + "path/filepath" "testing" "time" @@ -93,6 +95,48 @@ func TestWedgedBackendTripsTheBreakerThroughTheRealRunner(t *testing.T) { } } +// TestCompleteBindingScopesStayBehindTheBreaker pins that a scope with a +// complete external storage binding — which bdCommandRunnerForCity routes to +// the context runner instead of the managed-retry path — still gets the scope +// transport breaker. The external-endpoint direction is exactly what the +// breaker was built for; an early return that skipped it would let a wedged +// endpoint pile up bd subprocesses unbounded. +func TestCompleteBindingScopesStayBehindTheBreaker(t *testing.T) { + t.Setenv("GC_BEADS", "bd") + cityPath := writeBreakerTestCity(t, "") + if err := os.MkdirAll(filepath.Join(cityPath, ".beads"), 0o755); err != nil { + t.Fatal(err) + } + metadata := `{"backend":"dolt","storage_endpoint":"db.example.com:3306","storage_database":"beads_prod"}` + if err := os.WriteFile(scopeMetadataJSONPath(cityPath), []byte(metadata), 0o644); err != nil { + t.Fatal(err) + } + bdResilienceRegistryForCity(cityPath).SetJitterForTest(func(c time.Duration) time.Duration { return c }) + calls := installFakeBdExec(t, func(_, _ string, _ ...string) ([]byte, error) { + return nil, fmt.Errorf("timed out after %s", 2*time.Minute) + }) + + runner := bdCommandRunnerForCity(cityPath) + scope := t.TempDir() + for i := 0; i < 3; i++ { + if _, err := runner(scope, "bd", "list", "--json"); err == nil { + t.Fatalf("call %d: err = nil, want the timeout", i) + } else if errors.Is(err, beads.ErrStoreUnavailable) { + t.Fatalf("call %d: tripped before the threshold", i) + } + } + if *calls != 3 { + t.Fatalf("exec calls = %d after 3 invocations, want 3", *calls) + } + if _, err := runner(scope, "bd", "list", "--json"); !errors.Is(err, beads.ErrStoreUnavailable) { + t.Fatalf("after 3 consecutive wedged-endpoint timeouts err = %v, want ErrStoreUnavailable; "+ + "the context runner bypasses the breaker", err) + } + if *calls != 3 { + t.Fatalf("exec calls = %d after the breaker opened, want still 3 — an open breaker must spawn zero subprocesses", *calls) + } +} + // TestApplicationFailuresDoNotTripTheBreaker is the counterweight: a store that // answers is healthy transport however unhappy the answer. Without this, any // run of ordinary "not found" errors would fail-fast the whole scope. diff --git a/cmd/gc/beads_provider_lifecycle.go b/cmd/gc/beads_provider_lifecycle.go index 2a8e241686..0098062dfc 100644 --- a/cmd/gc/beads_provider_lifecycle.go +++ b/cmd/gc/beads_provider_lifecycle.go @@ -208,7 +208,15 @@ func startBeadsLifecycle(cityPath, _ string, cfg *config.City, stderr io.Writer) clearCityDoltConfig(cityPath) } skipLocalDolt := false + if cityUsesBdStoreContract(cityPath) { + var err error + skipLocalDolt, err = scopeHasCompleteStorageBinding(scopeMetadataJSONPath(cityPath)) + if err != nil { + return err + } + } switch { + case skipLocalDolt: case isExternalDolt(cityPath): // An externally-pinned dolt endpoint (city_canonical / explicit, e.g. a // hosted beads-gateway) is not a gc-managed local lifecycle: connect to @@ -471,9 +479,9 @@ func seedDeferredManagedBeads(cityPath, dir, prefix, doltDatabase string) { } func seedDeferredManagedBeadsErr(cityPath, dir, prefix, doltDatabase string) error { - if usesPostgres, err := scopeUsesPostgresBackendForInit(cityPath, dir); err != nil { + if skipsManagedDolt, err := scopeSkipsManagedDoltForInit(cityPath, dir); err != nil { return err - } else if usesPostgres { + } else if skipsManagedDolt { return nil } if state, ok, err := desiredScopeDoltConfigStateForInit(cityPath, dir, prefix); err != nil { @@ -536,9 +544,9 @@ func normalizeCanonicalBdScopeFilesForInit(cityPath, dir, prefix, doltDatabase s if !cityUsesBdStoreContract(cityPath) { return nil } - if usesPostgres, err := scopeUsesPostgresBackendForInit(cityPath, dir); err != nil { + if skipsManagedDolt, err := scopeSkipsManagedDoltForInit(cityPath, dir); err != nil { return err - } else if usesPostgres { + } else if skipsManagedDolt { return nil } if state, ok, err := desiredScopeDoltConfigStateForInit(cityPath, dir, prefix); err != nil { @@ -566,9 +574,9 @@ func normalizeCanonicalBdScopeFilesForInit(cityPath, dir, prefix, doltDatabase s // wipe existing hooks. installBeadHooks only removes gc-stamped hooks and // is always safe to run regardless of event_hooks config. func initAndHookDir(cityPath, dir, prefix string) error { - if usesPostgres, err := scopeUsesPostgresBackendForInit(cityPath, dir); err != nil { + if skipsManagedDolt, err := scopeSkipsManagedDoltForInit(cityPath, dir); err != nil { return err - } else if usesPostgres { + } else if skipsManagedDolt { if err := installBeadHooks(dir, cityPath); err != nil { return fmt.Errorf("install hooks at %s: %w", dir, err) } @@ -612,11 +620,18 @@ func initAndHookDir(cityPath, dir, prefix string) error { return nil } -func scopeUsesPostgresBackendForInit(cityPath, dir string) (bool, error) { +// scopeSkipsManagedDoltForInit reports whether this scope owns a complete +// external binding or uses Postgres, so callers avoid managed-Dolt setup. +func scopeSkipsManagedDoltForInit(cityPath, dir string) (bool, error) { + path := scopeMetadataJSONPath(dir) + if completeBinding, err := scopeHasCompleteStorageBinding(path); err != nil { + return false, err + } else if completeBinding { + return true, nil + } if !cityUsesBdStoreContract(cityPath) { return false, nil } - path := scopeMetadataJSONPath(dir) state, ok, err := contract.LoadMetadataState(fsys.OSFS{}, path) if err != nil { if allowLegacyDoltMetadataRepair(fsys.OSFS{}, path, err) { @@ -632,10 +647,65 @@ func scopeUsesPostgresBackendForInit(cityPath, dir string) (bool, error) { return false, nil } } + if !samePath(cityPath, dir) { + resolved, err := contract.ResolveScopeConfigState(fsys.OSFS{}, cityPath, dir, "") + if err != nil { + return false, err + } + if resolved.Kind == contract.ScopeConfigAuthoritative && resolved.State.EndpointOrigin == contract.EndpointOriginInheritedCity { + if completeBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(cityPath)); err != nil { + return false, err + } else if completeBinding { + return true, nil + } + } + } _, usesPostgres, err := postgresMetadataForScope(cityPath, dir) return usesPostgres, err } +// scopeHasCompleteStorageBinding recognizes the opaque workspace binding +// before legacy metadata parsing. Only all three non-empty fields authorize +// this dispatch; absent fields remain ordinary legacy metadata and partial +// fields fail closed. +func scopeHasCompleteStorageBinding(path string) (bool, error) { + data, err := fsys.OSFS{}.ReadFile(path) + if errors.Is(err, os.ErrNotExist) { + return false, nil + } + if err != nil { + return false, fmt.Errorf("read beads storage binding %s: %w", path, err) + } + + var presence struct { + StorageEndpoint json.RawMessage `json:"storage_endpoint"` + StorageDatabase json.RawMessage `json:"storage_database"` + } + if err := json.Unmarshal(data, &presence); err != nil { + // This is a dispatch probe, not the metadata parser. Preserve the + // established LoadMetadataState error surface for malformed metadata. + return false, nil + } + if len(presence.StorageEndpoint) == 0 && len(presence.StorageDatabase) == 0 { + return false, nil + } + + var binding struct { + Backend string `json:"backend"` + StorageEndpoint string `json:"storage_endpoint"` + StorageDatabase string `json:"storage_database"` + } + if err := json.Unmarshal(data, &binding); err != nil { + return false, fmt.Errorf("parse beads storage binding %s: %w", path, err) + } + if strings.TrimSpace(binding.Backend) != "" && + strings.TrimSpace(binding.StorageEndpoint) != "" && + strings.TrimSpace(binding.StorageDatabase) != "" { + return true, nil + } + return false, fmt.Errorf("partial beads storage binding %s: backend, storage_endpoint, and storage_database must all be non-empty", path) +} + func allowLegacyDoltMetadataRepair(fs fsys.FS, path string, err error) bool { var parseErr *contract.MetadataParseError if !errors.As(err, &parseErr) { @@ -784,6 +854,13 @@ func ensureBeadsProvider(cityPath string) error { if cityUsesDoltliteBeadsBackend(cityPath) { return nil } + if cityUsesBdStoreContract(cityPath) { + if completeBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(cityPath)); err != nil { + return err + } else if completeBinding { + return nil + } + } provider := beadsProvider(cityPath) if strings.HasPrefix(provider, "exec:") { release, err := acquireProviderSemaphoreForOp(cityPath, "start") @@ -1164,6 +1241,13 @@ func healthBeadsProviderContext(ctx context.Context, cityPath string, waitForSco if cityUsesDoltliteBeadsBackend(cityPath) { return nil } + if cityUsesBdStoreContract(cityPath) { + if completeBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(cityPath)); err != nil { + return err + } else if completeBinding { + return nil + } + } provider := beadsProvider(cityPath) if strings.HasPrefix(provider, "exec:") { release, err := acquireProviderSemaphoreForOpContext(ctx, cityPath, "health") @@ -1697,9 +1781,9 @@ func normalizeCanonicalBdScopeFiles(cityPath string, cfg *config.City, warns ... } resolveRigPaths(cityPath, cfg.Rigs) if scopeUsesManagedBdStoreContract(cityPath, cityPath) { - if usesPostgres, err := scopeUsesPostgresBackendForInit(cityPath, cityPath); err != nil { + if skipsManagedDolt, err := scopeSkipsManagedDoltForInit(cityPath, cityPath); err != nil { return fmt.Errorf("classifying city backend: %w", err) - } else if !usesPostgres { + } else if !skipsManagedDolt { doltDatabase := defaultScopeDoltDatabase(cityPath, cityPath, config.EffectiveHQPrefix(cfg)) if cityUsesDoltliteBeadsBackend(cityPath) { if err := ensureCanonicalDoltliteScopeMetadataForInit(fsys.OSFS{}, cityPath, doltDatabase); err != nil { @@ -1714,9 +1798,9 @@ func normalizeCanonicalBdScopeFiles(cityPath string, cfg *config.City, warns ... if !rigUsesManagedBdStoreContract(cityPath, cfg.Rigs[i]) { continue } - if usesPostgres, err := scopeUsesPostgresBackendForInit(cityPath, cfg.Rigs[i].Path); err != nil { + if skipsManagedDolt, err := scopeSkipsManagedDoltForInit(cityPath, cfg.Rigs[i].Path); err != nil { return fmt.Errorf("classifying rig %q backend: %w", cfg.Rigs[i].Name, err) - } else if !usesPostgres { + } else if !skipsManagedDolt { doltDatabase := defaultScopeDoltDatabase(cityPath, cfg.Rigs[i].Path, cfg.Rigs[i].EffectivePrefix()) if cityUsesDoltliteBeadsBackend(cityPath) { if err := ensureCanonicalDoltliteScopeMetadataForInit(fsys.OSFS{}, cfg.Rigs[i].Path, doltDatabase); err != nil { @@ -1744,13 +1828,20 @@ func syncConfiguredDoltPortFiles(cityPath string, cityDolt config.DoltConfig, ci } resolveRigPaths(cityPath, rigs) cityUsesBd := scopeUsesManagedBdStoreContract(cityPath, cityPath) + cityHasCompleteStorageBinding := false cityUsesPostgres := false if cityUsesBd { - usesPostgres, err := scopeUsesPostgresBackendForInit(cityPath, cityPath) + completeBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(cityPath)) if err != nil { return fmt.Errorf("classifying city backend: %w", err) } - cityUsesPostgres = usesPostgres + cityHasCompleteStorageBinding = completeBinding + if !completeBinding { + _, cityUsesPostgres, err = postgresMetadataForScope(cityPath, cityPath) + if err != nil { + return fmt.Errorf("classifying city backend: %w", err) + } + } } anyRigUsesBd := false for _, rig := range rigs { @@ -1776,7 +1867,7 @@ func syncConfiguredDoltPortFiles(cityPath string, cityDolt config.DoltConfig, ci if cityState.EndpointOrigin == contract.EndpointOriginManagedCity && !cityUsesPostgres { managedPort = currentDoltPort(cityPath) } - if cityUsesBd { + if cityUsesBd && !cityHasCompleteStorageBinding { if err := normalizeScopeDoltConfig(cityPath, cityState); err != nil { return err } @@ -1787,7 +1878,7 @@ func syncConfiguredDoltPortFiles(cityPath string, cityDolt config.DoltConfig, ci removeDoltPortFile(cityPath) } } - } else { + } else if !cityUsesBd { removeDoltPortFile(cityPath) } @@ -1800,10 +1891,20 @@ func syncConfiguredDoltPortFiles(cityPath string, cityDolt config.DoltConfig, ci removeDoltPortFile(rig.Path) continue } + rigHasCompleteStorageBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(rig.Path)) + if err != nil { + return err + } + if rigHasCompleteStorageBinding { + continue + } rigState, err := syncDesiredRigDoltConfigState(cityPath, rig, cityState) if err != nil { return err } + if cityHasCompleteStorageBinding && rigState.EndpointOrigin == contract.EndpointOriginInheritedCity { + continue + } rigManagedPort := "" if cityState.EndpointOrigin == contract.EndpointOriginManagedCity && rigState.EndpointOrigin == contract.EndpointOriginInheritedCity { rigManagedPort = managedPort diff --git a/cmd/gc/beads_provider_lifecycle_test.go b/cmd/gc/beads_provider_lifecycle_test.go index 0b7a200b1a..285512a0b7 100644 --- a/cmd/gc/beads_provider_lifecycle_test.go +++ b/cmd/gc/beads_provider_lifecycle_test.go @@ -49,6 +49,132 @@ func setScopedBeadsProviderForTest(t *testing.T, scopeRoot, provider string) { t.Setenv("GC_BEADS_SCOPE_ROOT", scopeRoot) } +func TestScopeHasCompleteStorageBinding(t *testing.T) { + tests := []struct { + name string + metadata string + want bool + wantErr bool + }{ + {name: "missing metadata"}, + { + name: "legacy metadata has neither storage field", + metadata: `{"backend":"postgres","postgres_host":"db.example.test"}`, + }, + { + name: "complete opaque binding", + metadata: `{"backend":"dolt","storage_endpoint":"opaque-remote","storage_database":"work","dolt_mode":"server","unknown":{"preserve":true}}`, + want: true, + }, + { + name: "one storage field is partial", + metadata: `{"backend":"postgres","storage_endpoint":"remote"}`, + wantErr: true, + }, + { + name: "blank backend is partial", + metadata: `{"backend":" ","storage_endpoint":"remote","storage_database":"work"}`, + wantErr: true, + }, + { + name: "malformed metadata remains unclassified", + metadata: `{"backend":`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + scopeRoot := t.TempDir() + path := scopeMetadataJSONPath(scopeRoot) + if tt.metadata != "" { + if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(path, []byte(tt.metadata), 0o600); err != nil { + t.Fatal(err) + } + } + + got, err := scopeHasCompleteStorageBinding(path) + if (err != nil) != tt.wantErr { + t.Fatalf("scopeHasCompleteStorageBinding() error = %v, wantErr %v", err, tt.wantErr) + } + if got != tt.want { + t.Fatalf("scopeHasCompleteStorageBinding() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestScopeSkipsManagedDoltForInitChecksCompleteBindingFirst(t *testing.T) { + t.Setenv("GC_BEADS", "file") + scopeRoot := t.TempDir() + if err := os.MkdirAll(filepath.Join(scopeRoot, ".beads"), 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(scopeMetadataJSONPath(scopeRoot), []byte(`{"backend":"postgres","storage_endpoint":"opaque-remote","storage_database":"work","dolt_mode":"server"}`), 0o600); err != nil { + t.Fatal(err) + } + + got, err := scopeSkipsManagedDoltForInit(scopeRoot, scopeRoot) + if err != nil { + t.Fatalf("scopeSkipsManagedDoltForInit: %v", err) + } + if !got { + t.Fatal("scopeSkipsManagedDoltForInit = false, want true for complete storage binding") + } +} + +func TestScopeBackendIsPostgresRejectsCompleteDoltBinding(t *testing.T) { + scopeRoot := t.TempDir() + if err := os.MkdirAll(filepath.Join(scopeRoot, ".beads"), 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(scopeMetadataJSONPath(scopeRoot), []byte(`{"backend":"dolt","storage_endpoint":"opaque-remote","storage_database":"work"}`), 0o600); err != nil { + t.Fatal(err) + } + if scopeBackendIsPostgres(scopeRoot, scopeRoot) { + t.Fatal("scopeBackendIsPostgres = true, want false for a Dolt storage binding") + } +} + +func TestStartBeadsLifecycleDelegatesCompleteStorageBindingWithoutMutation(t *testing.T) { + cityPath := t.TempDir() + callLog := filepath.Join(cityPath, "provider-calls.log") + script := writeManagedBdTestScript(t, "#!/bin/sh\necho \"$1\" >> "+callLog+"\nexit 99\n") + if err := os.MkdirAll(filepath.Join(cityPath, ".beads"), 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(cityPath, "city.toml"), []byte("[workspace]\nname = \"test-city\"\n"), 0o600); err != nil { + t.Fatal(err) + } + metadataPath := scopeMetadataJSONPath(cityPath) + metadata := []byte(`{"backend":"postgres","storage_endpoint":"opaque-remote","storage_database":"work","dolt_mode":"server","dolt_database":"legacy_hq","unknown":{"preserve":true}}`) + if err := os.WriteFile(metadataPath, metadata, 0o600); err != nil { + t.Fatal(err) + } + t.Setenv("GC_BEADS", "exec:"+script) + t.Setenv("GC_BEADS_SCOPE_ROOT", cityPath) + cfg := &config.City{Workspace: config.Workspace{Name: "test-city"}} + + if err := healthBeadsProviderContext(context.Background(), cityPath, false); err != nil { + t.Fatalf("healthBeadsProviderContext: %v", err) + } + if err := startBeadsLifecycle(cityPath, "test-city", cfg, io.Discard); err != nil { + t.Fatalf("startBeadsLifecycle: %v", err) + } + if _, err := os.Stat(callLog); !os.IsNotExist(err) { + t.Fatalf("managed provider should not run for complete storage binding, stat err = %v", err) + } + got, err := os.ReadFile(metadataPath) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(got, metadata) { + t.Fatalf("metadata changed: got %s, want %s", got, metadata) + } +} + func mustProviderLifecycleProcessEnv(t *testing.T, cityPath, provider string) []string { t.Helper() env, err := providerLifecycleProcessEnvWithError(cityPath, provider) @@ -2798,6 +2924,41 @@ dolt.auto-start: true } } +func TestSyncConfiguredDoltPortFilesSkipsInheritedRigForCompleteCityStorageBinding(t *testing.T) { + cityDir := t.TempDir() + rigDir := filepath.Join(t.TempDir(), "frontend") + for _, dir := range []string{cityDir, rigDir} { + if err := os.MkdirAll(filepath.Join(dir, ".beads"), 0o700); err != nil { + t.Fatal(err) + } + } + cityMetadata := []byte(`{"backend":"dolt","storage_endpoint":"opaque-remote","storage_database":"work"}`) + if err := os.WriteFile(scopeMetadataJSONPath(cityDir), cityMetadata, 0o600); err != nil { + t.Fatal(err) + } + rigConfig := []byte(`issue_prefix: frontend +gc.endpoint_origin: inherited_city +gc.endpoint_status: verified +dolt.auto-start: false +`) + if err := os.WriteFile(filepath.Join(rigDir, ".beads", "config.yaml"), rigConfig, 0o644); err != nil { + t.Fatal(err) + } + + if err := syncConfiguredDoltPortFiles(cityDir, config.DoltConfig{}, "gc", []config.Rig{{Name: "frontend", Path: rigDir}}, io.Discard); err != nil { + t.Fatalf("syncConfiguredDoltPortFiles: %v", err) + } + if got := mustReadFile(t, scopeMetadataJSONPath(cityDir)); string(got) != string(cityMetadata) { + t.Fatalf("city metadata changed:\n got %s\nwant %s", got, cityMetadata) + } + if got := mustReadFile(t, filepath.Join(rigDir, ".beads", "config.yaml")); string(got) != string(rigConfig) { + t.Fatalf("inherited rig config changed:\n got %s\nwant %s", got, rigConfig) + } + if _, err := os.Stat(filepath.Join(rigDir, ".beads", "dolt-server.port")); !os.IsNotExist(err) { + t.Fatalf("inherited rig port file should remain absent, stat err = %v", err) + } +} + func TestSyncConfiguredDoltPortFilesReconcilesMirroredPrefixesFromCityConfig(t *testing.T) { cityDir := t.TempDir() rigDir := filepath.Join(t.TempDir(), "frontend") diff --git a/cmd/gc/build_desired_state.go b/cmd/gc/build_desired_state.go index bd56929bcc..706c059d0f 100644 --- a/cmd/gc/build_desired_state.go +++ b/cmd/gc/build_desired_state.go @@ -4223,7 +4223,8 @@ func stampRunSessionIdentity(workBeads []beads.Bead, workStores []beads.Store, s if sessionName != "" && strings.TrimSpace(wb.Metadata[beadmeta.SessionNameMetadataKey]) != sessionName { patch[beadmeta.SessionNameMetadataKey] = sessionName } - if workDir != "" && strings.TrimSpace(wb.Metadata[beadmeta.WorkDirMetadataKey]) != workDir { + if workDir != "" && strings.TrimSpace(wb.Metadata[beadmeta.WorkDirMetadataKey]) != workDir && + (!sbInfo.PoolManaged || workDirStampHasOwnershipEvidence(wb.Metadata, workDir)) { patch[beadmeta.WorkDirMetadataKey] = workDir } if len(patch) > 0 { @@ -4236,16 +4237,29 @@ func stampRunSessionIdentity(workBeads []beads.Bead, workStores []beads.Store, s // workBeads and route-time stamping skips it for pool agents. The // dashboard's root-only snapshot reads the root's own metadata, so a // worked step back-fills its root via gc.root_bead_id. (#2843) - stampRunRootFromStep(store, wb, sessionName, workDir, stampedRoots, stderr) + stampRunRootFromStep(store, wb, sessionName, workDir, !sbInfo.PoolManaged, stampedRoots, stderr) } } +// workDirStampHasOwnershipEvidence reports whether existing bead metadata +// already identifies workDir as the work artifact directory. Session +// reconciliation of a pool session observes a slot cwd; it does not create or +// own a managed worktree, so it must not manufacture gc.work_dir on an +// arbitrary routed bead. Doing so turns a pool slot label into incomplete +// worktree ownership evidence and makes demand fail closed. The worktree +// creator writes the legacy artifact path first; reconciliation may only mirror +// that value. Non-pool sessions retain the historical observability stamp. +func workDirStampHasOwnershipEvidence(metadata map[string]string, workDir string) bool { + legacy := strings.TrimSpace(metadata[beadmeta.LegacyWorkDirMetadataKey]) + return legacy != "" && legacy == workDir +} + // stampRunRootFromStep copies a step's resolved session_name/work_dir onto its // workflow root (gc.root_bead_id), once per root per pass. Idempotent: it reads // the root and writes only the keys that differ. Best-effort — a root that is // in another store, already gone, or already stamped is silently skipped (a // cross-store root gets stamped on its own store's reconcile pass). -func stampRunRootFromStep(store beads.Store, step beads.Bead, sessionName, workDir string, stampedRoots map[string]struct{}, stderr io.Writer) { +func stampRunRootFromStep(store beads.Store, step beads.Bead, sessionName, workDir string, allowUnownedWorkDir bool, stampedRoots map[string]struct{}, stderr io.Writer) { rootID := strings.TrimSpace(step.Metadata[beadmeta.RootBeadIDMetadataKey]) if rootID == "" || rootID == step.ID { return @@ -4264,7 +4278,8 @@ func stampRunRootFromStep(store beads.Store, step beads.Bead, sessionName, workD if sessionName != "" && strings.TrimSpace(root.Metadata[beadmeta.SessionNameMetadataKey]) != sessionName { patch[beadmeta.SessionNameMetadataKey] = sessionName } - if workDir != "" && strings.TrimSpace(root.Metadata[beadmeta.WorkDirMetadataKey]) != workDir { + if workDir != "" && strings.TrimSpace(root.Metadata[beadmeta.WorkDirMetadataKey]) != workDir && + (allowUnownedWorkDir || workDirStampHasOwnershipEvidence(root.Metadata, workDir)) { patch[beadmeta.WorkDirMetadataKey] = workDir } if len(patch) == 0 { @@ -5146,13 +5161,30 @@ func materializeProviderOverlaysBeforeFingerprint( PackOverlayDirs: packDirs, OverlayDir: overlayDir, }) + // Skip reconciler-owned mergeable hook/settings files here: hooks.Install + // runs immediately after this staging on the SAME workDir (see + // prepareTemplateResolution), so it must be the sole writer of those files + // ON THE RECONCILE TICK. Staging them too leaves two writers with + // disagreeing hook-entry matchers and a permanent codex-hooks-drift hybrid. + // The runtime task-worktree staging path keeps staging them — it is their + // sole writer. + // + // "Sole writer" is scoped to the tick on purpose. For a persistent + // (non-task) agent the home dir is also the session workDir, and + // session-start staging writes these same files through the NON-skipping + // path — internal/runtime/tmux.stageStartFiles and + // runtime.StageSessionWorkDir (subprocess/acp) both call + // StageProviderOverlayDir with a nil skip. So a hybrid document can + // reappear at session start; the next tick converges it. That turns the + // permanent drift this fix targets into a transient one, which is the + // actual invariant — not that nothing else ever writes these paths. for _, od := range packDirs { - if err := runtime.StageProviderOverlayDir(od, workDir, overlayProviders, stderr); err != nil { + if err := runtime.StageProviderOverlayDirSkippingMergeable(od, workDir, overlayProviders, stderr); err != nil { fmt.Fprintf(stderr, "agent %q: pack overlay %q: %v\n", qualifiedName, od, err) //nolint:errcheck } } if overlayDir != "" { - if err := runtime.StageProviderOverlayDir(overlayDir, workDir, overlayProviders, stderr); err != nil { + if err := runtime.StageProviderOverlayDirSkippingMergeable(overlayDir, workDir, overlayProviders, stderr); err != nil { fmt.Fprintf(stderr, "agent %q: overlay %q: %v\n", qualifiedName, overlayDir, err) //nolint:errcheck } } diff --git a/cmd/gc/build_desired_state_pool_info.go b/cmd/gc/build_desired_state_pool_info.go index 5a3ec623f9..fd02bc75a2 100644 --- a/cmd/gc/build_desired_state_pool_info.go +++ b/cmd/gc/build_desired_state_pool_info.go @@ -402,7 +402,7 @@ func normalizeNonExpandingPoolSessionInfo( } if aliasNeedsUpdate { if err := session.WithCitySessionAliasLock(bp.cityPath, canonical, func() error { - if err := session.EnsureAliasAvailableWithConfig(bp.beadStore, bp.city, canonical, info.ID); err != nil { + if err := session.EnsureAliasAvailableWithConfigForOwner(bp.beadStore, bp.city, canonical, info.ID, canonical); err != nil { return err } return apply() diff --git a/cmd/gc/build_desired_state_session_stamp_test.go b/cmd/gc/build_desired_state_session_stamp_test.go index 86fdade1a4..d919995822 100644 --- a/cmd/gc/build_desired_state_session_stamp_test.go +++ b/cmd/gc/build_desired_state_session_stamp_test.go @@ -63,6 +63,32 @@ func TestStampRunSessionIdentityStampsInProgressAssignedBead(t *testing.T) { } } +func TestStampRunSessionIdentityDoesNotManufactureWorktreeEvidence(t *testing.T) { + const ( + sessionName = "polecat-gc-734732" + slotDir = "/home/ds/gascity-worktrees/polecat-slots/polecat-2" + ) + run := beads.Bead{ID: "gc-demand", Type: "task", Status: "in_progress", Assignee: sessionName} + mem := beads.NewMemStoreFrom(0, []beads.Bead{run}, nil) + store := &countingStore{Store: mem} + poolSession := stampTestSession(sessionName, slotDir) + poolSession.Metadata["pool_managed"] = "true" + sessions := newSessionBeadSnapshot([]beads.Bead{poolSession}) + + stampRunSessionIdentity([]beads.Bead{run}, []beads.Store{store}, sessions, io.Discard) + + got, err := mem.Get(run.ID) + if err != nil { + t.Fatalf("Get(%s): %v", run.ID, err) + } + if got.Metadata["gc.session_name"] != sessionName { + t.Fatalf("gc.session_name = %q, want %q", got.Metadata["gc.session_name"], sessionName) + } + if value, exists := got.Metadata["gc.work_dir"]; exists { + t.Fatalf("gc.work_dir was manufactured as %q from a pool slot; worktree ownership evidence must come from the worktree creator", value) + } +} + func TestStampRunSessionIdentityPropagatesToRunRoot(t *testing.T) { // #2843: a worked in-progress STEP back-fills its workflow ROOT (which the // dashboard's root-only snapshot reads). The root is a control-lane bead, diff --git a/cmd/gc/city_runtime.go b/cmd/gc/city_runtime.go index 4ba751ecb1..f22ec5c3b1 100644 --- a/cmd/gc/city_runtime.go +++ b/cmd/gc/city_runtime.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "hash/fnv" "io" "log" "net" @@ -20,9 +21,11 @@ import ( "sync/atomic" "time" + "github.com/gastownhall/gascity/internal/beadmeta" "github.com/gastownhall/gascity/internal/beads" "github.com/gastownhall/gascity/internal/clock" "github.com/gastownhall/gascity/internal/config" + "github.com/gastownhall/gascity/internal/doctor" "github.com/gastownhall/gascity/internal/events" "github.com/gastownhall/gascity/internal/fsys" "github.com/gastownhall/gascity/internal/nudgequeue" @@ -116,6 +119,12 @@ type CityRuntime struct { modelProxyAddr string providerHealthReg *providerHealthRegistry modelProxyServer *http.Server + // liveSweepMemos carries the live model-usage sweep's per-session memo: the + // resolved transcript path, whether discovery definitively found nothing, and + // the sweep-interval floor. The worker factory is rebuilt per tick, so this + // process-lifetime cache is what keeps a per-tick live lane from repeating + // bounded discovery and transcript reads for every awake session. + liveSweepMemos sync.Map // session bead id -> liveSweepMemo fsPressureConsecutiveSkips int fsPressureEpisodeLogged bool @@ -158,9 +167,10 @@ const runtimeDemandSnapshotMaxAge = 30 * time.Second const scaleCheckDemandMinInterval = 1 * time.Second type runtimeDemandSnapshot struct { - createdAt time.Time - sessionFingerprint string - result DesiredStateResult + createdAt time.Time + sessionFingerprint string + readyDemandFingerprint string + result DesiredStateResult } // CityRuntimeParams holds the caller-provided parameters for creating a @@ -1387,6 +1397,14 @@ func (cr *CityRuntime) tick( cr.beadReconcileTick(ctx, result, sessionBeads, trace, false) recordPhase(TraceSiteControllerTickPhase, "bead_reconcile_tick", phaseStart, traceDesiredStateFields(result)) } + // Graph stores intentionally do not emit bead.closed. Reconcile their + // closed graph.v2 steps only at the authoritative patrol cadence, not on + // event-driven ticks, so lifecycle recovery remains bounded and idempotent. + if trigger == "patrol" && cr.cs != nil { + phaseStart = time.Now() + cr.cs.reconcileExecutionCompletions() + recordPhase(TraceSiteControllerTickPhase, "reconcile_execution_completions", phaseStart, nil) + } // Wisp GC: purge expired closed molecules. The molecule/wisp/workflow purge // arm routes through the typed graph-class store; the read-message retention @@ -1593,6 +1611,19 @@ func (cr *CityRuntime) runOrderTrackingSweepWatchdog(now time.Time) { } } +// bulkDeleteMaxAge returns the maximum backup age allowed for bulk bead +// deletions. Configurable via GC_BACKUP_MAX_AGE_FOR_BULK_DELETE (integer +// seconds); defaults to 86400 s (24 h). +func bulkDeleteMaxAge(_ *config.City) time.Duration { + if s := os.Getenv("GC_BACKUP_MAX_AGE_FOR_BULK_DELETE"); s != "" { + var secs int + if _, err := fmt.Sscanf(s, "%d", &secs); err == nil && secs > 0 { + return time.Duration(secs) * time.Second + } + } + return 24 * time.Hour +} + // runOrderTrackingRetentionWatchdog deletes closed order-tracking beads that // are past their TTL (defaulting to 7d) and beyond the retain-10 floor, at // most once every orderTrackingRetentionWatchdogInterval. It deletes at most @@ -1604,6 +1635,17 @@ func (cr *CityRuntime) runOrderTrackingRetentionWatchdog(now time.Time) { } cr.orderTrackingRetentionWatchdogLast = now + // The cityPath guard is a test affordance: real controllers always set it, + // so the backup-age check below always runs in production. + if cr.cityPath != "" { + if safe, reason := doctor.BulkDeleteSafe(cr.cityPath, cr.cfg, bulkDeleteMaxAge(cr.cfg), now); !safe { + if cr.stderr != nil { + fmt.Fprintf(cr.stderr, "%s: order-tracking retention watchdog: skipping bulk delete — %s\n", cr.logPrefix, reason) //nolint:errcheck // best-effort stderr + } + return + } + } + stores, _, closeOpened, storeErr := cr.orderTrackingSweepStores() defer closeOpened() if len(stores) == 0 { @@ -2291,7 +2333,9 @@ func (cr *CityRuntime) stopConfigWatcher() { // readiness quickly, so it skips the undesired-pool-session sweep (a heavy // candidate × store × status × identifier bd-read fan-out that, serialized on // the readiness path, can exceed the startup watchdog on a heavy-session city — -// gastownhall/gascity#3288). The first steady-state tick performs the sweep. +// gastownhall/gascity#3288) and the usage lane's live transcript sweep (bounded +// per-session file discovery and reads across every awake session at once). The +// first steady-state tick performs both. func (cr *CityRuntime) beadReconcileTick(ctx context.Context, result DesiredStateResult, sessionBeads *sessionBeadSnapshot, trace *sessionReconcilerTraceCycle, bootReconcile bool) { desiredState := result.State store := cr.cityBeadStore() @@ -2317,8 +2361,11 @@ func (cr *CityRuntime) beadReconcileTick(ctx context.Context, result DesiredStat result.SessionQueryPartial = result.SessionQueryPartial || sessionQueryPartial } // Emit any due compute usage facts by reusing the open-session snapshot this - // tick already loaded, rather than issuing a second redundant store scan. - cr.emitDueComputeFacts(ctx, sessionBeads.OpenInfos()) + // tick already loaded, rather than issuing a second redundant store scan. The + // boot pass covers the whole fleet at once on the readiness path, so it takes + // only the marker-gated terminal lane and leaves the fleet-proportional live + // lane to the first steady-state tick. + cr.emitDueComputeFacts(ctx, sessionBeads.OpenInfos(), bootReconcile) rigStores := cr.rigBeadStores() assignedWorkBeads := result.AssignedWorkBeads assignedWorkStoreRefs := result.AssignedWorkStoreRefs @@ -3401,7 +3448,18 @@ func (cr *CityRuntime) loadDemandSnapshot( configChanged bool, ) runtimeDemandSnapshot { sessionFingerprint := sessionBeadSnapshotFingerprint(sessionBeads) - if cr.shouldRefreshDemandSnapshot(trigger, configChanged, sessionFingerprint) { + readyDemandFingerprint := "" + refresh := cr.shouldRefreshDemandSnapshot(trigger, configChanged, sessionFingerprint) + if !refresh && trigger == "patrol" && cr.demandSnapshotsEnabled() { + readyDemandFingerprint = cr.readyDemandSnapshotFingerprint() + refresh = cr.demandSnapshot.readyDemandFingerprint != readyDemandFingerprint + } + if refresh { + if trigger == "patrol" && cr.demandSnapshotsEnabled() && readyDemandFingerprint == "" { + readyDemandFingerprint = cr.readyDemandSnapshotFingerprint() + } else if cr.demandSnapshot != nil { + readyDemandFingerprint = cr.demandSnapshot.readyDemandFingerprint + } result := cr.buildDesiredState(sessionBeads, trace) var openSessionInfos []sessionpkg.Info if sessionBeads != nil { @@ -3421,9 +3479,10 @@ func (cr *CityRuntime) loadDemandSnapshot( mergeNamedSessionDemand(result.PoolDesiredCounts, result.NamedSessionDemand, cr.cfg) result.WorkSet = make(map[string]bool) cr.demandSnapshot = &runtimeDemandSnapshot{ - createdAt: time.Now(), - sessionFingerprint: sessionFingerprint, - result: result, + createdAt: time.Now(), + sessionFingerprint: sessionFingerprint, + readyDemandFingerprint: readyDemandFingerprint, + result: result, } } if cr.demandSnapshot == nil { @@ -3483,6 +3542,75 @@ func (cr *CityRuntime) demandSnapshotPatrolMaxAge() time.Duration { return scaleCheckDemandMinInterval } +func (cr *CityRuntime) readyDemandSnapshotFingerprint() string { + stores := []struct { + ref string + store beads.Store + }{{ref: cr.cityName, store: cr.cityBeadStore()}} + rigStores := cr.rigBeadStores() + refs := make([]string, 0, len(rigStores)) + for ref := range rigStores { + refs = append(refs, ref) + } + sort.Strings(refs) + for _, ref := range refs { + stores = append(stores, struct { + ref string + store beads.Store + }{ref: ref, store: rigStores[ref]}) + } + + h := fnv.New64a() + for _, entry := range stores { + _, _ = io.WriteString(h, entry.ref) + _, _ = io.WriteString(h, "\x00") + if entry.store == nil { + _, _ = io.WriteString(h, "") + _, _ = io.WriteString(h, "\x00") + continue + } + ready, err := beads.ReadyLive(entry.store, beads.ReadyQuery{TierMode: beads.TierBoth}) + if err != nil { + log.Printf("readyDemandSnapshotFingerprint: store %s: %v", entry.ref, err) + _, _ = io.WriteString(h, "error:") + _, _ = io.WriteString(h, err.Error()) + _, _ = io.WriteString(h, "\x00") + continue + } + sort.Slice(ready, func(i, j int) bool { + return ready[i].ID < ready[j].ID + }) + for _, bead := range ready { + writeReadyDemandFingerprintBead(h, bead) + } + } + return fmt.Sprintf("%x", h.Sum64()) +} + +func writeReadyDemandFingerprintBead(w io.Writer, bead beads.Bead) { + _, _ = io.WriteString(w, bead.ID) + _, _ = io.WriteString(w, "\x00") + _, _ = io.WriteString(w, bead.Status) + _, _ = io.WriteString(w, "\x00") + _, _ = io.WriteString(w, bead.Type) + _, _ = io.WriteString(w, "\x00") + _, _ = io.WriteString(w, bead.Assignee) + _, _ = io.WriteString(w, "\x00") + _, _ = io.WriteString(w, bead.UpdatedAt.Format(time.RFC3339Nano)) + _, _ = io.WriteString(w, "\x00") + for _, key := range []string{ + beadmeta.RoutedToMetadataKey, + beadmeta.RunTargetMetadataKey, + beadmeta.KindMetadataKey, + beadmeta.FormulaContractMetadataKey, + } { + _, _ = io.WriteString(w, key) + _, _ = io.WriteString(w, "\x00") + _, _ = io.WriteString(w, bead.Metadata[key]) + _, _ = io.WriteString(w, "\x00") + } +} + func (cr *CityRuntime) demandSnapshotsEnabled() bool { return cr.cs != nil && cr.cs.EventProvider() != nil && demandSnapshotDemandSourcesEventBacked(cr.cfg) } diff --git a/cmd/gc/city_runtime_test.go b/cmd/gc/city_runtime_test.go index 07a5258cf9..4c6b63bb58 100644 --- a/cmd/gc/city_runtime_test.go +++ b/cmd/gc/city_runtime_test.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "log" "os" "path/filepath" "strings" @@ -843,6 +844,65 @@ func TestCityRuntimeDemandSnapshotReusesStablePatrolDemand(t *testing.T) { } } +func TestCityRuntimeDemandSnapshotRefreshesForNewRoutedReadyWork(t *testing.T) { + const template = "gascity/gc.gap-analyst" + cityPath := t.TempDir() + store := beads.NewMemStore() + cfg := &config.City{ + Workspace: config.Workspace{Name: "test-city"}, + Agents: []config.Agent{{ + Name: "gap-analyst", + BindingName: "gc", + Dir: "gascity", + StartCommand: "true", + MinActiveSessions: intPtr(0), + MaxActiveSessions: intPtr(3), + }}, + } + cr := &CityRuntime{ + cityName: "test-city", + cityPath: cityPath, + cfg: cfg, + sp: runtime.NewFake(), + cs: &controllerState{ + cityName: "test-city", + cityPath: cityPath, + cityBeadStore: store, + eventProv: events.NewFake(), + }, + stderr: io.Discard, + } + buildCalls := 0 + cr.buildFnWithSessionBeads = func(cfg *config.City, sp runtime.Provider, store beads.Store, rigStores map[string]beads.Store, sessionBeads *sessionBeadSnapshot, trace *sessionReconcilerTraceCycle) DesiredStateResult { + buildCalls++ + return buildDesiredStateWithSessionBeads("test-city", cityPath, time.Now(), cfg, sp, store, rigStores, sessionBeads, trace, io.Discard) + } + sessionBeads := newSessionBeadSnapshot(nil) + + first := cr.loadDemandSnapshot(sessionBeads, nil, "patrol", false) + if got := first.result.PoolDesiredCounts[template]; got != 0 { + t.Fatalf("initial PoolDesiredCounts[%s] = %d, want 0", template, got) + } + if _, err := store.Create(beads.Bead{ + Title: "gap analysis", + Type: "task", + Status: "open", + Metadata: map[string]string{ + "gc.routed_to": template, + }, + }); err != nil { + t.Fatalf("Create routed work: %v", err) + } + + second := cr.loadDemandSnapshot(sessionBeads, nil, "patrol", false) + if buildCalls != 2 { + t.Fatalf("buildDesiredState call count = %d, want 2 after ready-demand change", buildCalls) + } + if got := second.result.PoolDesiredCounts[template]; got != 1 { + t.Fatalf("PoolDesiredCounts[%s] = %d, want 1 for newly-ready routed work", template, got) + } +} + func TestCityRuntimeEnsureManagedDoltPublishedForTickCallsHealthWhenManagedPortMissing(t *testing.T) { t.Setenv("GC_BEADS", "bd") @@ -1504,6 +1564,92 @@ func TestCityRuntimeTickDispatchesOrdersBeforeDemandSnapshot(t *testing.T) { } } +func TestCityRuntimePatrolReconcilesGraphStepClosedAfterWatcherStartup(t *testing.T) { + backing := beads.NewMemStore() + root, err := backing.Create(beads.Bead{ID: "gcg-run", Metadata: map[string]string{ + beadmeta.KindMetadataKey: beadmeta.KindWorkflow, + beadmeta.FormulaContractMetadataKey: beadmeta.FormulaContractGraphV2, + }}) + if err != nil { + t.Fatal(err) + } + step, err := backing.Create(beads.Bead{ID: "gcg-build-attempt", Metadata: map[string]string{ + beadmeta.RootBeadIDMetadataKey: root.ID, + beadmeta.StepIDMetadataKey: "build", + beadmeta.SessionIDMetadataKey: "gcs-session", + }}) + if err != nil { + t.Fatal(err) + } + + ep := events.NewFake() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + cs := &controllerState{ + cfg: &config.City{Workspace: config.Workspace{Name: "test-city"}}, + cityBeadStore: backing, + eventProv: ep, + } + cs.startBeadEventWatcher(ctx) + + if err := backing.Close(step.ID); err != nil { + t.Fatal(err) + } + completed, err := ep.List(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if err != nil { + t.Fatal(err) + } + if len(completed) != 0 { + t.Fatalf("completed events before patrol = %#v, want none without bead.closed", completed) + } + + cr := &CityRuntime{ + cityName: "test-city", + cityPath: t.TempDir(), + cfg: cs.cfg, + sp: runtime.NewFake(), + cs: cs, + buildFnWithSessionBeads: func(*config.City, runtime.Provider, beads.Store, map[string]beads.Store, *sessionBeadSnapshot, *sessionReconcilerTraceCycle) DesiredStateResult { + return DesiredStateResult{State: map[string]TemplateParams{}} + }, + stdout: io.Discard, + stderr: io.Discard, + } + var dirty atomic.Bool + var lastProviderName string + var prevPoolRunning map[string]bool + cr.tick(ctx, &dirty, &lastProviderName, cr.cityPath, &prevPoolRunning, "poke") + completed, err = ep.List(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if err != nil { + t.Fatal(err) + } + if len(completed) != 0 { + t.Fatalf("completed events after poke = %#v, want no global reconciliation outside patrol", completed) + } + + cr.tick(ctx, &dirty, &lastProviderName, cr.cityPath, &prevPoolRunning, "patrol") + + completed, err = ep.List(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if err != nil { + t.Fatal(err) + } + if len(completed) != 1 { + t.Fatalf("completed events after patrol = %#v, want one", completed) + } + if got := completed[0]; got.RunID != root.ID || got.SessionID != "gcs-session" || got.StepID != "build" { + t.Fatalf("completed event = %#v", got) + } + + cr.tick(ctx, &dirty, &lastProviderName, cr.cityPath, &prevPoolRunning, "patrol") + completed, err = ep.List(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if err != nil { + t.Fatal(err) + } + if len(completed) != 1 { + t.Fatalf("completed events after second patrol = %#v, want exact-fact no-op", completed) + } +} + func TestCityRuntimeTickReturnsBeforeDemandWhenCanceled(t *testing.T) { store := beads.NewMemStore() od := &recordingOrderDispatcher{} @@ -2153,18 +2299,19 @@ func TestCityRuntimeDemandSnapshotReplaysACPRoutesOnCacheHit(t *testing.T) { cs: &controllerState{ eventProv: events.NewFake(), }, - demandSnapshot: &runtimeDemandSnapshot{ - createdAt: time.Now(), - sessionFingerprint: "", - result: DesiredStateResult{State: map[string]TemplateParams{ - "headless-agent": { - SessionName: "headless-agent", - IsACP: true, - }, - }}, - }, stderr: io.Discard, } + cr.demandSnapshot = &runtimeDemandSnapshot{ + createdAt: time.Now(), + sessionFingerprint: sessionBeadSnapshotFingerprint(nil), + readyDemandFingerprint: cr.readyDemandSnapshotFingerprint(), + result: DesiredStateResult{State: map[string]TemplateParams{ + "headless-agent": { + SessionName: "headless-agent", + IsACP: true, + }, + }}, + } _ = cr.loadDemandSnapshot(nil, nil, "patrol", false) @@ -2173,6 +2320,71 @@ func TestCityRuntimeDemandSnapshotReplaysACPRoutesOnCacheHit(t *testing.T) { } } +func TestCityRuntimeReadyDemandFingerprintLogsStableStoreError(t *testing.T) { + var logBuf bytes.Buffer + oldLogOutput := log.Writer() + log.SetOutput(&logBuf) + t.Cleanup(func() { log.SetOutput(oldLogOutput) }) + + store := &readyFailStore{Store: beads.NewMemStore()} + cr := &CityRuntime{ + cityName: "test-city", + cfg: &config.City{ + Workspace: config.Workspace{Name: "test-city"}, + }, + cs: &controllerState{ + cityName: "test-city", + cityBeadStore: store, + eventProv: events.NewFake(), + }, + stderr: io.Discard, + } + + first := cr.readyDemandSnapshotFingerprint() + second := cr.readyDemandSnapshotFingerprint() + + if first != second { + t.Fatalf("readyDemandSnapshotFingerprint changed across stable store errors: %q != %q", first, second) + } + if store.readyCalls != 2 { + t.Fatalf("Ready calls = %d, want 2", store.readyCalls) + } + if got := logBuf.String(); !strings.Contains(got, "readyDemandSnapshotFingerprint: store test-city: backing ready should not be used") { + t.Fatalf("log output = %q, want readyDemandSnapshotFingerprint store error", got) + } +} + +func TestCityRuntimeDemandSnapshotPokeDoesNotScanReadyFingerprint(t *testing.T) { + store := &readyFailStore{Store: beads.NewMemStore()} + buildCalls := 0 + cr := &CityRuntime{ + cityName: "test-city", + cityPath: t.TempDir(), + cfg: &config.City{ + Workspace: config.Workspace{Name: "test-city"}, + }, + cs: &controllerState{ + cityName: "test-city", + cityBeadStore: store, + eventProv: events.NewFake(), + }, + stderr: io.Discard, + } + cr.buildFnWithSessionBeads = func(*config.City, runtime.Provider, beads.Store, map[string]beads.Store, *sessionBeadSnapshot, *sessionReconcilerTraceCycle) DesiredStateResult { + buildCalls++ + return DesiredStateResult{State: map[string]TemplateParams{}} + } + + _ = cr.loadDemandSnapshot(newSessionBeadSnapshot(nil), nil, "poke", false) + + if buildCalls != 1 { + t.Fatalf("buildDesiredState calls = %d, want 1", buildCalls) + } + if store.readyCalls != 0 { + t.Fatalf("Ready calls = %d, want 0 for forced non-patrol rebuild", store.readyCalls) + } +} + // Pool session beads in the "creating" window (tmux not yet up, work not yet // assigned) must not be swept. Otherwise the sweep runs on the same tick the // pool creates the bead, observes zero assigned work, and closes it — the @@ -7000,6 +7212,97 @@ func TestOrderTrackingRetentionWatchdog_StampsLastAfterFiring(t *testing.T) { } } +// seedRetentionWatchdogCity builds a CityRuntime whose cityPath points at a +// scratch city carrying one legacy backup_state.json stamped at backupAge, plus +// a store holding minClosedOrderTrackingRetained+2 prunable beads. Every other +// TestOrderTrackingRetentionWatchdog_* case leaves cityPath empty, which skips +// the doctor.BulkDeleteSafe guard entirely; these two exercise it. +func seedRetentionWatchdogCity(t *testing.T, now time.Time, backupAge time.Duration) (*CityRuntime, beads.Store, *bytes.Buffer) { + t.Helper() + cityDir := t.TempDir() + backupDir := filepath.Join(cityDir, ".beads", "backup") + if err := os.MkdirAll(backupDir, 0o755); err != nil { + t.Fatalf("MkdirAll(%s): %v", backupDir, err) + } + stateJSON := fmt.Sprintf(`{"timestamp":%q}`, now.Add(-backupAge).Format(time.RFC3339)) + if err := os.WriteFile(filepath.Join(backupDir, "backup_state.json"), []byte(stateJSON), 0o644); err != nil { + t.Fatalf("write backup_state.json: %v", err) + } + + // Beads are 8 days old (> 7d default TTL); the 2 oldest exceed the retain-10 floor. + seed := make([]beads.Bead, 0, minClosedOrderTrackingRetained+2) + for i := range minClosedOrderTrackingRetained + 2 { + seed = append(seed, beads.Bead{ + ID: fmt.Sprintf("guard-%02d", i), + Title: "order:guard", + Status: "closed", + Type: "task", + CreatedAt: now.Add(-8*24*time.Hour + time.Duration(i)*time.Minute), + Labels: []string{"order-run:guard", labelOrderTracking}, + Ephemeral: true, + }) + } + store := beads.NewMemStoreFrom(100, seed, nil) + var stderrBuf bytes.Buffer + cr := &CityRuntime{ + cityName: "test-city", + cityPath: cityDir, + cfg: &config.City{Workspace: config.Workspace{Name: "test-city"}}, + standaloneCityStore: store, + stdout: io.Discard, + stderr: &stderrBuf, + logPrefix: "gc test", + } + return cr, store, &stderrBuf +} + +func TestOrderTrackingRetentionWatchdog_SkipsBulkDeleteWhenBackupStale(t *testing.T) { + now := time.Date(2026, 6, 7, 12, 0, 0, 0, time.UTC) + // 48h since the last backup, past the 24h bulkDeleteMaxAge default. + cr, store, stderrBuf := seedRetentionWatchdogCity(t, now, 48*time.Hour) + + cr.runOrderTrackingRetentionWatchdog(now) + + // Nothing may be deleted while the recovery point is stale. + for i := range minClosedOrderTrackingRetained + 2 { + id := fmt.Sprintf("guard-%02d", i) + if _, err := store.Get(id); err != nil { + t.Fatalf("%s should be preserved when the backup is stale: %v", id, err) + } + } + if got := stderrBuf.String(); !strings.Contains(got, "skipping bulk delete") { + t.Fatalf("stderr = %q, want 'skipping bulk delete' in output", got) + } + // The interval stamp is consumed even on the skip path, so a blocked + // watchdog does not re-scan on every tick. + if !cr.orderTrackingRetentionWatchdogLast.Equal(now) { + t.Fatalf("orderTrackingRetentionWatchdogLast = %v, want %v", cr.orderTrackingRetentionWatchdogLast, now) + } +} + +func TestOrderTrackingRetentionWatchdog_PrunesWhenBackupFresh(t *testing.T) { + now := time.Date(2026, 6, 7, 12, 0, 0, 0, time.UTC) + // 1h since the last backup, well inside the 24h bulkDeleteMaxAge default. + cr, store, stderrBuf := seedRetentionWatchdogCity(t, now, time.Hour) + + cr.runOrderTrackingRetentionWatchdog(now) + + if got := stderrBuf.String(); strings.Contains(got, "skipping bulk delete") { + t.Fatalf("stderr = %q, want no skip with a fresh backup", got) + } + for _, id := range []string{"guard-00", "guard-01"} { + if _, err := store.Get(id); !errors.Is(err, beads.ErrNotFound) { + t.Fatalf("Get(%s) err = %v, want ErrNotFound (should be pruned)", id, err) + } + } + for i := 2; i < minClosedOrderTrackingRetained+2; i++ { + id := fmt.Sprintf("guard-%02d", i) + if _, err := store.Get(id); err != nil { + t.Fatalf("%s should be preserved at the retain floor: %v", id, err) + } + } +} + func TestWarnIfClosedOrderTrackingBacklogLarge_SilentAtThreshold(t *testing.T) { // 100 closed beads: at the threshold, no warning (fires only when > 100). seed := make([]beads.Bead, 100) diff --git a/cmd/gc/cmd_agent_script.go b/cmd/gc/cmd_agent_script.go index 9a37cfc909..88d0e8db1c 100644 --- a/cmd/gc/cmd_agent_script.go +++ b/cmd/gc/cmd_agent_script.go @@ -816,7 +816,7 @@ func agentScriptHookExitIsNoWork(output, stderr string) bool { } func agentScriptClaimActor() string { - for _, key := range []string{"GC_SESSION_NAME", "GC_AGENT", "GC_ALIAS", "BEADS_ACTOR"} { + for _, key := range []string{"GC_ALIAS", "BEADS_ACTOR", "GC_AGENT", "GC_SESSION_NAME"} { if value := strings.TrimSpace(os.Getenv(key)); value != "" { return value } @@ -838,7 +838,7 @@ func agentScriptRig() string { } func agentScriptAlias() string { - for _, key := range []string{"GC_ALIAS", "GC_SESSION_NAME", "GC_AGENT"} { + for _, key := range []string{"GC_ALIAS", "BEADS_ACTOR", "GC_AGENT", "GC_SESSION_NAME"} { if value := strings.TrimSpace(os.Getenv(key)); value != "" { return value } diff --git a/cmd/gc/cmd_agent_script_test.go b/cmd/gc/cmd_agent_script_test.go index 82ed662c3e..9613c68654 100644 --- a/cmd/gc/cmd_agent_script_test.go +++ b/cmd/gc/cmd_agent_script_test.go @@ -14,8 +14,9 @@ import ( "time" ) -func TestAgentScriptBDClaimUsesSessionActor(t *testing.T) { - t.Setenv("GC_SESSION_NAME", "demo/worker-1") +func TestAgentScriptBDClaimUsesCanonicalActor(t *testing.T) { + t.Setenv("GC_ALIAS", "demo/worker") + t.Setenv("GC_SESSION_NAME", "demo--worker") var calls [][]string exec := agentScriptExecutor{ @@ -37,12 +38,45 @@ func TestAgentScriptBDClaimUsesSessionActor(t *testing.T) { if exitCode != nil { t.Fatalf("exitCode = %v, want nil", *exitCode) } - want := []string{"bd", "update", "ga-123", "--claim", "--actor", "demo/worker-1"} + want := []string{"bd", "update", "ga-123", "--claim", "--actor", "demo/worker"} if len(calls) != 1 || !slices.Equal(calls[0], want) { t.Fatalf("calls = %#v, want %#v", calls, [][]string{want}) } } +func TestAgentScriptClaimActorFallsBackToSessionName(t *testing.T) { + t.Setenv("GC_ALIAS", "") + t.Setenv("GC_AGENT", "") + t.Setenv("GC_SESSION_NAME", "demo--worker") + t.Setenv("BEADS_ACTOR", "") + + if got := agentScriptClaimActor(); got != "demo--worker" { + t.Fatalf("agentScriptClaimActor() = %q, want session name fallback", got) + } +} + +func TestAgentScriptClaimActorPrefersProjectedActor(t *testing.T) { + t.Setenv("GC_ALIAS", "") + t.Setenv("BEADS_ACTOR", "repair-id") + t.Setenv("GC_AGENT", "stale") + t.Setenv("GC_SESSION_NAME", "s-repair-id") + + if got := agentScriptClaimActor(); got != "repair-id" { + t.Fatalf("agentScriptClaimActor() = %q, want projected actor", got) + } +} + +func TestAgentScriptAliasPrefersDurableOwner(t *testing.T) { + t.Setenv("GC_ALIAS", "") + t.Setenv("BEADS_ACTOR", "repair-id") + t.Setenv("GC_AGENT", "stale") + t.Setenv("GC_SESSION_NAME", "s-repair-id") + + if got := agentScriptAlias(); got != "repair-id" { + t.Fatalf("agentScriptAlias() = %q, want durable owner", got) + } +} + func TestAgentScriptShellEnvIncludesBeadMetadata(t *testing.T) { ctx := agentScriptContext{ bead: agentScriptBead{ diff --git a/cmd/gc/cmd_bd.go b/cmd/gc/cmd_bd.go index 0a1a0ef926..3906460d4f 100644 --- a/cmd/gc/cmd_bd.go +++ b/cmd/gc/cmd_bd.go @@ -206,6 +206,13 @@ func doBd(args []string, stdout, stderr io.Writer) int { return 1 } + // Refuse a dropped --set-metadata pair before any store work, so nothing is + // written and the exit code is honest. bd applies the subset and exits 0. + if msg, mistyped := mistypedMetadataPairRefusal(bdArgs); mistyped { + fmt.Fprint(stderr, msg) //nolint:errcheck // best-effort stderr + return 1 + } + cityPath, err := resolveBdCity(cityName) if err != nil { fmt.Fprintf(stderr, "gc bd: %v\n", err) //nolint:errcheck // best-effort stderr diff --git a/cmd/gc/cmd_hook.go b/cmd/gc/cmd_hook.go index 0564ef1444..0c9e704407 100644 --- a/cmd/gc/cmd_hook.go +++ b/cmd/gc/cmd_hook.go @@ -365,13 +365,7 @@ func cmdHookWithOptions(args []string, opts hookCommandOptions, stdout, stderr i agentForQuery := resolvedAgentName sessionForQuery := "" if sessionTemplateContext { - agentForQuery = os.Getenv("GC_ALIAS") - if agentForQuery == "" { - agentForQuery = os.Getenv("GC_SESSION_NAME") - } - if agentForQuery == "" { - agentForQuery = os.Getenv("GC_AGENT") - } + agentForQuery = hookSessionAgentForQuery() sessionForQuery = os.Getenv("GC_SESSION_NAME") } else { sessionForQuery = cliSessionName(cityPath, cityName, resolvedAgentName, cfg.Workspace.SessionTemplate) @@ -405,7 +399,7 @@ func cmdHookWithOptions(args []string, opts hookCommandOptions, stdout, stderr i // returns empty and the spawned session exits with nothing to do. The rig // store goes first (as the primary entry, not a best-effort federated // extra) so a rig-store work-query timeout still surfaces to the reconciler - // via firstStoreWithWork's emit-on-timeout contract — the agent's + // via bestStoreWithWork's emit-on-timeout contract — the agent's // (work-less) city-scoped env stays as a best-effort secondary. This // extends the #2877 city-scoped cross-store delivery to rig-scoped agents. stores := []hookStore{{dir: workDir, env: queryEnv}} @@ -434,7 +428,7 @@ func cmdHookWithOptions(args []string, opts hookCommandOptions, stdout, stderr i os.Getenv("GC_SESSION_ID"), failureTemplate, command, err) } runner := func(command, _ string) (string, error) { - out, _, err := firstStoreWithWork(command, stores, stores[0], shellWorkQueryWithEnv) + out, _, err := bestStoreWithWork(command, stores, stores[0], shellWorkQueryWithEnv) emitQueryFailure(command, err) return out, err } @@ -444,7 +438,9 @@ func cmdHookWithOptions(args []string, opts hookCommandOptions, stdout, stderr i sessionID := strings.TrimSpace(overrides["GC_SESSION_ID"]) sessionName := strings.TrimSpace(sessionForQuery) alias := strings.TrimSpace(overrides["GC_ALIAS"]) - assignee := firstNonEmptyHookValue(sessionName, sessionID, alias, agentForQuery, resolvedAgentName) + // Write the alias/agent form that read paths query through GC_AGENT. + // Session forms remain fallbacks for unaliased workers. + assignee := firstNonEmptyHookValue(alias, agentForQuery, resolvedAgentName, sessionName, sessionID) claimOpts := hookClaimOptions{ Assignee: assignee, // IdentityCandidates governs ADOPTION of already-owned in_progress/open @@ -605,10 +601,11 @@ func claimHookWork(workQuery, workDir string, queryEnv []string, stores []hookSt } // claimHookWorkWithRunner is claimHookWork with the work-query runner and claim -// ops injected for tests. It selects the first store reporting ready work, -// re-validates it for claim-time freshness and falls back to a later store if it -// emptied since discovery (claimStoreWithFallback), then attempts the claim -// against that store's captured rows, against that store's dir/env. +// ops injected for tests. It selects the best-ranked store reporting ready work +// (see bestStoreWithWork), re-validates it for claim-time freshness and falls +// back to a later store if it emptied since discovery (claimStoreWithFallback), +// then attempts the claim against that store's captured rows, against that +// store's dir/env. // // When a selected store still reports ready work but every claimable row is lost // to another claimant before the mutation, the single-store claim drains without @@ -635,7 +632,7 @@ func claimHookWorkWithRunner(workQuery, workDir string, queryEnv []string, store // report claims_errored instead of laundering a write failure into no_work. claimsErrored := false for len(remaining) > 0 { - _, selected, err := firstStoreWithWork(workQuery, remaining, primary, run) + _, selected, err := bestStoreWithWork(workQuery, remaining, primary, run) if err != nil { emitFailure(workQuery, err) fmt.Fprintf(stderr, "gc hook --claim: %v\n", err) //nolint:errcheck // best-effort stderr @@ -686,6 +683,15 @@ func hookClaimPrimaryRouteTarget(a *config.Agent) string { return agentutil.RoutedToIdentity(a) } +func hookSessionAgentForQuery() string { + return firstNonEmptyHookValue( + os.Getenv("GC_ALIAS"), + os.Getenv("BEADS_ACTOR"), + os.Getenv("GC_AGENT"), + os.Getenv("GC_SESSION_NAME"), + ) +} + func firstNonEmptyHookValue(values ...string) string { for _, value := range values { value = strings.TrimSpace(value) diff --git a/cmd/gc/cmd_hook_claim.go b/cmd/gc/cmd_hook_claim.go index 78b3ccdf78..3377349164 100644 --- a/cmd/gc/cmd_hook_claim.go +++ b/cmd/gc/cmd_hook_claim.go @@ -16,6 +16,7 @@ import ( "github.com/gastownhall/gascity/internal/beadmeta" "github.com/gastownhall/gascity/internal/beads" "github.com/gastownhall/gascity/internal/events" + "github.com/gastownhall/gascity/internal/executionevent" ) const hookClaimCommandName = "hook" @@ -61,6 +62,10 @@ type hookClaimOps struct { // (gc.work_branch and/or the durable session back-reference gc.session_id / // gc.session_name) onto the claimed bead in ONE update. Best-effort. StampWorkMeta hookStampWorkMetaFunc + // ReadWorkMeta is the post-stamp authoritative readback used only to + // establish the durable lifecycle-start emission point. + ReadWorkMeta func(context.Context, string, []string, string, string) (beads.Bead, error) + EmitExecutionStepStarted func(beads.Bead, string, []string, string) // PublishRunMap writes best-effort session-to-run correlation without // mutating the session bead after a successful work claim. PublishRunMap hookPublishRunMapFunc @@ -205,6 +210,12 @@ func (ops *hookClaimOps) applyDefaults() { if ops.PublishRunMap == nil { ops.PublishRunMap = writeRunMap } + if ops.ReadWorkMeta == nil { + ops.ReadWorkMeta = hookReadClaimedBeadWithBdStore + } + if ops.EmitExecutionStepStarted == nil { + ops.EmitExecutionStepStarted = hookEmitExecutionStepStarted + } } // claimFirstReadyHookAssignment atomically promotes the first open candidate @@ -426,7 +437,10 @@ func hookClaimCandidateIsMessage(candidate beads.Bead) bool { func writeHookClaimWorkResultForBead(result hookClaimJSONResult, bead beads.Bead, opts hookClaimOptions, ops hookClaimOps, dir string, stdout, stderr io.Writer) int { result.RootBeadID = strings.TrimSpace(bead.Metadata[beadmeta.RootBeadIDMetadataKey]) result.ContinuationGroup = strings.TrimSpace(bead.Metadata[beadmeta.ContinuationGroupMetadataKey]) - stampHookClaimIdentity(bead, opts, ops, dir, stderr) + durable, stamped := stampHookClaimIdentity(bead, opts, ops, dir, stderr) + if stamped && hookClaimLifecycleCandidate(durable, opts) { + ops.EmitExecutionStepStarted(durable, dir, opts.Env, opts.Assignee) + } publishHookClaimRunMap(bead, opts, ops, stderr) assigned, err := preassignHookContinuationGroup(bead, opts, ops, dir) if err != nil { @@ -578,16 +592,54 @@ func hookClaimWithBdStore(ctx context.Context, dir string, env []string, beadID, // an unconditional write would emit a bead.updated per tick per in-progress bead // (the cache-reconcile flood class). Best-effort: a missing repo, detached HEAD, // absent session, or write error never blocks the claim. -func stampHookClaimIdentity(bead beads.Bead, opts hookClaimOptions, ops hookClaimOps, dir string, stderr io.Writer) { +func stampHookClaimIdentity(bead beads.Bead, opts hookClaimOptions, ops hookClaimOps, dir string, stderr io.Writer) (beads.Bead, bool) { patch := hookClaimIdentityPatch(bead, opts, ops, dir) + sessionID := hookClaimSessionID(opts.Env) + needsLifecycleIdentity := sessionID != "" && !beadmeta.IsControlKind(strings.TrimSpace(bead.Metadata[beadmeta.KindMetadataKey])) if len(patch) == 0 { - return + return bead, needsLifecycleIdentity && strings.EqualFold(strings.TrimSpace(bead.Status), "in_progress") && + strings.TrimSpace(bead.Metadata[beadmeta.SessionIDMetadataKey]) == sessionID } ctx, cancel := context.WithTimeout(context.Background(), hookClaimMutationTimeout) defer cancel() if err := ops.StampWorkMeta(ctx, dir, opts.Env, bead.ID, opts.Assignee, patch); err != nil { fmt.Fprintf(stderr, "gc hook --claim: stamping execution identity on %s: %v\n", bead.ID, err) //nolint:errcheck + return beads.Bead{}, false + } + if !needsLifecycleIdentity { + return beads.Bead{}, false } + readback, err := ops.ReadWorkMeta(ctx, dir, opts.Env, bead.ID, opts.Assignee) + if err != nil { + fmt.Fprintf(stderr, "gc hook --claim: reading stamped execution identity on %s: %v\n", bead.ID, err) //nolint:errcheck + return beads.Bead{}, false + } + if !strings.EqualFold(strings.TrimSpace(readback.Status), "in_progress") || + strings.TrimSpace(readback.Metadata[beadmeta.SessionIDMetadataKey]) != sessionID { + return beads.Bead{}, false + } + return readback, true +} + +// hookClaimLifecycleCandidate reports whether a bead can be a session-owned +// graph step whose started fact is safe to reconcile. EmitLifecycle performs the +// authoritative graph-root validation; this cheaper gate avoids opening the +// graph-store path for ordinary hook work. +func hookClaimLifecycleCandidate(bead beads.Bead, opts hookClaimOptions) bool { + sessionID := hookClaimSessionID(opts.Env) + if sessionID == "" || + !strings.EqualFold(strings.TrimSpace(bead.Status), "in_progress") || + beadmeta.IsControlKind(strings.TrimSpace(bead.Metadata[beadmeta.KindMetadataKey])) || + strings.TrimSpace(bead.Metadata[beadmeta.RootBeadIDMetadataKey]) == "" || + strings.TrimSpace(bead.Metadata[beadmeta.StepIDMetadataKey]) == "" || + strings.TrimSpace(bead.Metadata[beadmeta.SessionIDMetadataKey]) != sessionID { + return false + } + if sessionName := hookClaimSessionName(opts.Env); sessionName != "" && + strings.TrimSpace(bead.Metadata[beadmeta.SessionNameMetadataKey]) != sessionName { + return false + } + return true } // hookClaimIdentityPatch builds the compare-and-skipped claim-time metadata patch. @@ -624,6 +676,20 @@ func hookStampWorkMetaWithBdStore(_ context.Context, dir string, env []string, b return store.Update(beadID, beads.UpdateOpts{Metadata: patch}) } +func hookReadClaimedBeadWithBdStore(_ context.Context, dir string, env []string, beadID, assignee string) (beads.Bead, error) { + return hookClaimBdStore(dir, env, assignee).Get(beadID) +} + +func hookEmitExecutionStepStarted(step beads.Bead, dir string, env []string, assignee string) { + rec := openCityRecorder(io.Discard) + if closer, ok := rec.(io.Closer); ok { + defer closer.Close() //nolint:errcheck // lifecycle events are best-effort + } + // The hook's bd context owns both the claimed graph step and its workflow + // root; EmitLifecycle verifies the root is graph.v2 before recording. + _ = executionevent.EmitLifecycle(rec, hookClaimBdStore(dir, env, assignee), events.ExecutionStepStarted, step, eventActor()) +} + // publishHookClaimRunMap publishes the claimed bead's resolved run ID for the // external proxy correlation path. It deliberately does not decorate the // session bead: bd's fuzzy ID resolver can redirect a post-claim update to a diff --git a/cmd/gc/cmd_hook_claim_runid_test.go b/cmd/gc/cmd_hook_claim_runid_test.go index 2eefc85ca0..9d99a72d99 100644 --- a/cmd/gc/cmd_hook_claim_runid_test.go +++ b/cmd/gc/cmd_hook_claim_runid_test.go @@ -38,7 +38,15 @@ func claimOpsForRunMap(beadID string, claimedMeta map[string]string, spy *publis }, ResolveWorkBranch: func(string) string { return "" }, StampWorkMeta: noopStampWorkMeta, - PublishRunMap: spy.fn, + ReadWorkMeta: func(_ context.Context, _ string, _ []string, id, assignee string) (beads.Bead, error) { + meta := map[string]string{} + for k, v := range claimedMeta { + meta[k] = v + } + meta["gc.session_id"] = "session-1" + return beads.Bead{ID: id, Status: "in_progress", Assignee: assignee, Metadata: meta}, nil + }, + PublishRunMap: spy.fn, } opts := hookClaimOptions{ Assignee: "worker-1", diff --git a/cmd/gc/cmd_hook_claim_stamp_test.go b/cmd/gc/cmd_hook_claim_stamp_test.go index c79032edbb..d8758e214c 100644 --- a/cmd/gc/cmd_hook_claim_stamp_test.go +++ b/cmd/gc/cmd_hook_claim_stamp_test.go @@ -57,7 +57,16 @@ func poolClaimOps(runner string, claimedMeta map[string]string, branch string, s }, ResolveWorkBranch: func(string) string { return branch }, StampWorkMeta: spy.fn, - PublishRunMap: noopPublishRunMap, + ReadWorkMeta: func(_ context.Context, _ string, _ []string, id, assignee string) (beads.Bead, error) { + meta := map[string]string{} + for k, v := range claimedMeta { + meta[k] = v + } + meta[beadmeta.SessionIDMetadataKey] = "mc-sess1" + meta[beadmeta.SessionNameMetadataKey] = "gc__role-mc-sess1" + return beads.Bead{ID: id, Status: "in_progress", Assignee: assignee, Metadata: meta}, nil + }, + PublishRunMap: noopPublishRunMap, } } @@ -293,3 +302,68 @@ func TestDoHookClaimIdentityStampFailureDoesNotFailClaim(t *testing.T) { t.Fatalf("claim result = %+v, want bead hw-err reason claimed", result) } } + +func TestDoHookClaimEmitsStartedOnlyAfterDurableSessionReadback(t *testing.T) { + spy := &stampMetaSpy{} + meta := map[string]string{ + "gc.routed_to": "worker", beadmeta.RootBeadIDMetadataKey: "gcg-run", + beadmeta.StepIDMetadataKey: "build", beadmeta.NativeStepDependenciesMetadataKey: `["prepare"]`, + } + ops := poolClaimOps(`[{"id":"gcg-attempt","status":"open","metadata":{"gc.routed_to":"worker"}}]`, meta, "", spy) + var emitted []beads.Bead + ops.EmitExecutionStepStarted = func(b beads.Bead, _ string, _ []string, _ string) { emitted = append(emitted, b) } + var stdout, stderr bytes.Buffer + if code := doHookClaim("bd ready --json", "/tmp/work", poolClaimOpts(), ops, &stdout, &stderr); code != 0 { + t.Fatalf("doHookClaim = %d; stderr=%s", code, stderr.String()) + } + if len(emitted) != 1 || emitted[0].ID != "gcg-attempt" || emitted[0].Metadata[beadmeta.SessionIDMetadataKey] != "mc-sess1" || emitted[0].Status != "in_progress" { + t.Fatalf("started emission = %#v, want one durable in-progress session-stamped step", emitted) + } + + spy.err = errors.New("stamp failed") + emitted = nil + if code := doHookClaim("bd ready --json", "/tmp/work", poolClaimOpts(), ops, &stdout, &stderr); code != 0 { + t.Fatalf("failed-stamp claim = %d; stderr=%s", code, stderr.String()) + } + if len(emitted) != 0 { + t.Fatalf("failed stamp emitted started event: %#v", emitted) + } +} + +// TestDoHookClaimAdoptionReconcilesDurableStartedFact covers the crash window +// between a durable claim-time identity stamp and event recording. A later hook +// tick adopts the same in-progress assignment, verifies its durable identity, +// and must re-emit the idempotent started fact rather than leave a permanent +// lifecycle gap. +func TestDoHookClaimAdoptionReconcilesDurableStartedFact(t *testing.T) { + spy := &stampMetaSpy{} + meta := map[string]string{ + "gc.routed_to": "worker", beadmeta.RootBeadIDMetadataKey: "gcg-run", + beadmeta.StepIDMetadataKey: "build", beadmeta.SessionIDMetadataKey: "mc-sess1", + beadmeta.SessionNameMetadataKey: "gc__role-mc-sess1", + } + ops := hookClaimOps{ + Runner: func(string, string) (string, error) { + return `[{"id":"gcg-attempt","status":"in_progress","assignee":"gc__role-mc-sess1","metadata":{"gc.routed_to":"worker","gc.root_bead_id":"gcg-run","gc.step_id":"build","gc.session_id":"mc-sess1","gc.session_name":"gc__role-mc-sess1"}}]`, nil + }, + ResolveWorkBranch: func(string) string { return "" }, + StampWorkMeta: spy.fn, + ReadWorkMeta: func(_ context.Context, _ string, _ []string, id, assignee string) (beads.Bead, error) { + return beads.Bead{ID: id, Status: "in_progress", Assignee: assignee, Metadata: meta}, nil + }, + PublishRunMap: noopPublishRunMap, + } + var emitted []beads.Bead + ops.EmitExecutionStepStarted = func(b beads.Bead, _ string, _ []string, _ string) { emitted = append(emitted, b) } + + var stdout, stderr bytes.Buffer + if code := doHookClaim("bd ready --json", "/tmp/work", poolClaimOpts(), ops, &stdout, &stderr); code != 0 { + t.Fatalf("doHookClaim = %d; stderr=%s", code, stderr.String()) + } + if spy.calls != 0 { + t.Fatalf("StampWorkMeta calls = %d, want 0 for an already durable identity", spy.calls) + } + if len(emitted) != 1 || emitted[0].ID != "gcg-attempt" || emitted[0].Metadata[beadmeta.SessionIDMetadataKey] != "mc-sess1" { + t.Fatalf("started emission = %#v, want durable adopted step", emitted) + } +} diff --git a/cmd/gc/cmd_hook_test.go b/cmd/gc/cmd_hook_test.go index c391ea2deb..a92e708153 100644 --- a/cmd/gc/cmd_hook_test.go +++ b/cmd/gc/cmd_hook_test.go @@ -1011,7 +1011,7 @@ func TestClaimHookWorkRetriesLaterStoreWhenSelectedStoreLosesClaimRace(t *testin // own (primary) store loses its claim race and is dropped from the working set, // a later federated store that errors must stay a best-effort skip. The claim // must drain as "no work" rather than surface that federated store's error as a -// fatal claim failure (the bug: firstStoreWithWork keyed "own store" on slice +// fatal claim failure (the bug: bestStoreWithWork keyed "own store" on slice // position, so the federated store became index 0 after the primary was removed // and wedged the hook). func TestClaimHookWorkDrainsWhenPrimaryLosesRaceThenFederatedStoreErrors(t *testing.T) { @@ -1548,7 +1548,7 @@ work_query = "printf '[{\"id\":\"hw-1\",\"title\":\"Fix the bug\"}]'" } } -func TestHookCommandClaimUsesSessionActorAndPreassignsContinuation(t *testing.T) { +func TestHookCommandClaimUsesCanonicalActorAndPreassignsContinuation(t *testing.T) { clearGCEnv(t) disableManagedDoltRecoveryForTest(t) cityDir := t.TempDir() @@ -1602,7 +1602,7 @@ esac t.Setenv("GC_TEMPLATE", "worker") t.Setenv("GC_ALIAS", "worker-1") t.Setenv("GC_SESSION_ID", "session-id-1") - t.Setenv("GC_SESSION_NAME", "worker-1") + t.Setenv("GC_SESSION_NAME", "test-city--worker-1") t.Setenv("GC_SESSION_ORIGIN", "ephemeral") var stdout, stderr bytes.Buffer @@ -1630,10 +1630,10 @@ esac } logText := string(logData) if !strings.Contains(logText, "actor=worker-1 args=update hw-claim --claim --json") { - t.Fatalf("bd claim did not use session BEADS_ACTOR=worker-1; log:\n%s", logText) + t.Fatalf("bd claim did not use canonical BEADS_ACTOR=worker-1; log:\n%s", logText) } if !strings.Contains(logText, "actor=worker-1 args=show --json hw-claim") { - t.Fatalf("bd canonical read did not use session BEADS_ACTOR=worker-1; log:\n%s", logText) + t.Fatalf("bd canonical read did not use BEADS_ACTOR=worker-1; log:\n%s", logText) } if !strings.Contains(logText, "args=update --json hw-next --assignee worker-1") { t.Fatalf("continuation sibling was not preassigned through bd; log:\n%s", logText) @@ -1643,6 +1643,33 @@ esac } } +func TestHookSessionAgentForQueryPrefersOwnershipIdentity(t *testing.T) { + for _, tc := range []struct { + name string + alias string + actor string + agent string + sessionName string + want string + }{ + {name: "alias", alias: "rig/worker", actor: "session-id", agent: "stale", sessionName: "rig--worker", want: "rig/worker"}, + {name: "durable actor fallback", actor: "session-id", agent: "stale", sessionName: "s-session-id", want: "session-id"}, + {name: "compatibility fallback", agent: "session-id", sessionName: "s-session-id", want: "session-id"}, + {name: "runtime fallback", sessionName: "rig--worker", want: "rig--worker"}, + } { + t.Run(tc.name, func(t *testing.T) { + clearGCEnv(t) + t.Setenv("GC_ALIAS", tc.alias) + t.Setenv("BEADS_ACTOR", tc.actor) + t.Setenv("GC_AGENT", tc.agent) + t.Setenv("GC_SESSION_NAME", tc.sessionName) + if got := hookSessionAgentForQuery(); got != tc.want { + t.Fatalf("hookSessionAgentForQuery() = %q, want %q", got, tc.want) + } + }) + } +} + func TestCmdHookSessionTemplateContextDoesNotScanSessionsForName(t *testing.T) { clearGCEnv(t) disableManagedDoltRecoveryForTest(t) diff --git a/cmd/gc/cmd_mail.go b/cmd/gc/cmd_mail.go index 46ebf2b02e..4dcfc94dd8 100644 --- a/cmd/gc/cmd_mail.go +++ b/cmd/gc/cmd_mail.go @@ -1011,6 +1011,15 @@ func resolveMailRecipientIdentityCached(cityPath string, cfg *config.City, store if normalized := normalizeNamedSessionTarget(identifier); normalized == "" || normalized == "human" { return "human", nil } + if store != nil { + sessionID, err := session.ResolveSessionIDByExactID(store, identifier) + if err == nil { + return sessionID, nil + } + if !errors.Is(err, session.ErrSessionNotFound) { + return "", err + } + } if target, matched, targetErr := resolveLiveConfiguredNamedMailTargetCached(store, identifier, cache); targetErr != nil { return "", targetErr } else if matched { diff --git a/cmd/gc/cmd_mail_test.go b/cmd/gc/cmd_mail_test.go index 40fdb3cfb9..fb1035e464 100644 --- a/cmd/gc/cmd_mail_test.go +++ b/cmd/gc/cmd_mail_test.go @@ -1259,6 +1259,47 @@ func TestResolveMailRecipientIdentity_RejectsTemplatePrefixOnSessionSurface(t *t } } +func TestCmdMailSendExactSessionIDStaysPinned(t *testing.T) { + t.Setenv("GC_BEADS", "file") + t.Setenv("GC_MAIL", "") + t.Setenv("GC_ALIAS", "") + t.Setenv("GC_SESSION_ID", "") + t.Setenv("GC_AGENT", "") + + cityPath := t.TempDir() + if err := os.WriteFile(filepath.Join(cityPath, "city.toml"), []byte("[workspace]\nname = \"test-city\"\n"), 0o644); err != nil { + t.Fatalf("WriteFile(city.toml): %v", err) + } + t.Setenv("GC_CITY", cityPath) + + store, err := openCityStoreAt(cityPath) + if err != nil { + t.Fatalf("openCityStoreAt: %v", err) + } + sessionBead, err := store.Create(beads.Bead{ + Type: session.BeadType, + Labels: []string{session.LabelSession}, + Metadata: map[string]string{ + "alias": "worker", + "session_name": "worker-session", + }, + }) + if err != nil { + t.Fatalf("Create(session): %v", err) + } + + var stdout, stderr bytes.Buffer + code := cmdMailSend([]string{sessionBead.ID, "body"}, false, false, "human", "", "", "", &stdout, &stderr) + if code != 0 { + t.Fatalf("cmdMailSend() = %d, want 0; stdout=%s stderr=%s", code, stdout.String(), stderr.String()) + } + + stored := mailSendTestFindMessage(t, cityPath) + if stored.Assignee != sessionBead.ID { + t.Fatalf("stored assignee = %q, want typed session ID %q", stored.Assignee, sessionBead.ID) + } +} + func TestResolveMailRecipientIdentity_BareNamedSessionUsesConfiguredMailboxWithoutMaterializing(t *testing.T) { t.Setenv("GC_SESSION", "fake") diff --git a/cmd/gc/cmd_order.go b/cmd/gc/cmd_order.go index 23861d94ec..424af7d1e6 100644 --- a/cmd/gc/cmd_order.go +++ b/cmd/gc/cmd_order.go @@ -188,20 +188,35 @@ exit code 0 if any order is due, 1 if none are due.`, func newOrderHistoryCmd(stdout, stderr io.Writer) *cobra.Command { var rig string var jsonOutput bool + var limit int + var since string cmd := &cobra.Command{ Use: "history [name]", Short: "Show order execution history", Long: `Show execution history for orders. Queries bead history for past order runs. Optionally filter by order -name. Use --rig to filter by rig.`, +name. Use --rig to filter by rig. + +The read is bounded by default: only the most recent runs are fetched. +Widen it with --limit (0 fetches every retained run) or bound it by time +with --since. On a city with a long order-run history an unbounded read +costs tens of seconds, so prefer keeping a bound when triaging.`, Args: cobra.MaximumNArgs(1), RunE: func(_ *cobra.Command, args []string) error { name := "" if len(args) > 0 { name = args[0] } - if cmdOrderHistoryJSON(name, rig, jsonOutput, stdout, stderr) != 0 { + bounds, err := parseOrderHistoryBounds(limit, since) + if err != nil { + // Report it here rather than returning the error: the root + // command silences cobra's own error printing, so returning + // would exit 1 with no message at all. + fmt.Fprintf(stderr, "gc order history: %v\n", err) //nolint:errcheck // best-effort stderr + return errExit + } + if cmdOrderHistoryJSON(name, rig, bounds, jsonOutput, stdout, stderr) != 0 { return errExit } return nil @@ -210,15 +225,67 @@ name. Use --rig to filter by rig.`, } cmd.Flags().StringVar(&rig, "rig", "", "rig name to filter order history") cmd.Flags().BoolVar(&jsonOutput, "json", false, "output JSONL summary") + cmd.Flags().IntVar(&limit, "limit", defaultOrderHistoryLimit, "maximum runs to show (0 = every retained run)") + cmd.Flags().StringVar(&since, "since", "", "only show runs from within this duration ago (e.g. 1h, 24h)") _ = cmd.RegisterFlagCompletionFunc("rig", completeRigFlagNames) return cmd } +// defaultOrderHistoryLimit bounds `gc order history` when the operator gives no +// --limit. The command previously fetched every retained order-run bead, which +// measured 22s on a city with 11k+ rows and left the command unusable for +// interactive triage — the very moment an operator reaches for it (ga-klv). +// Recent runs are what triage needs; --limit 0 restores the full read. +const defaultOrderHistoryLimit = 50 + +// orderHistoryBounds bounds an order-history read. +type orderHistoryBounds struct { + // Limit caps how many runs are returned, newest first. Zero or less + // fetches every retained run. + Limit int + // Since drops runs older than this much time ago. Zero applies no time + // bound. + Since time.Duration +} + +// parseOrderHistoryBounds validates the CLI bound flags. A malformed --since is +// rejected at the edge so a typo fails loudly instead of silently widening the +// read to everything. +func parseOrderHistoryBounds(limit int, since string) (orderHistoryBounds, error) { + if limit < 0 { + return orderHistoryBounds{}, fmt.Errorf("--limit %d: want a non-negative count (0 fetches every retained run)", limit) + } + bounds := orderHistoryBounds{Limit: limit} + trimmed := strings.TrimSpace(since) + if trimmed == "" { + return bounds, nil + } + parsed, err := time.ParseDuration(trimmed) + if err != nil { + return orderHistoryBounds{}, fmt.Errorf("parsing --since %q: %w (want a duration such as 1h or 24h)", since, err) + } + if parsed <= 0 { + return orderHistoryBounds{}, fmt.Errorf("parsing --since %q: want a positive duration such as 1h or 24h", since) + } + bounds.Since = parsed + return bounds, nil +} + +// cutoff reports the oldest run time the bounds admit, and whether a time bound +// applies at all. +func (b orderHistoryBounds) cutoff(now time.Time) (time.Time, bool) { + if b.Since <= 0 { + return time.Time{}, false + } + return now.Add(-b.Since), true +} + func newOrderSweepTrackingCmd(stdout, stderr io.Writer) *cobra.Command { staleAfter := defaultOrderTrackingSweepStaleAfter includeWisps := false dryRun := false quiet := false + confirm := false cmd := &cobra.Command{ Use: "sweep-tracking [order ...]", Short: "Close stale and prune closed order-tracking beads", @@ -235,10 +302,15 @@ use bounded cleanup to avoid spending an unbounded tick on stale work. Use --include-wisps for operator recovery of abandoned order-run wisp subtrees whose open descendants are also older than --stale-after. Pass one or more scoped order names when --include-wisps is set; wisp recovery is -order-scoped to avoid scanning unrelated beads.`, +order-scoped to avoid scanning unrelated beads. + +When the number of eligible closed-bead deletions exceeds +GC_BULK_DELETE_CONFIRM_THRESHOLD (default 20), --confirm is required to +proceed. This guard prevents accidental mass-deletes without an explicit +operator acknowledgement.`, Args: cobra.ArbitraryArgs, RunE: func(_ *cobra.Command, args []string) error { - if cmdOrderSweepTrackingWithOptions(staleAfter, includeWisps, dryRun, quiet, args, stdout, stderr) != 0 { + if cmdOrderSweepTrackingWithOptions(staleAfter, includeWisps, dryRun, quiet, confirm, args, stdout, stderr) != 0 { return errExit } return nil @@ -249,6 +321,11 @@ order-scoped to avoid scanning unrelated beads.`, cmd.Flags().BoolVar(&includeWisps, "include-wisps", false, "also close stale order-run wisp subtrees with open descendants") cmd.Flags().BoolVar(&dryRun, "dry-run", false, "report stale order-tracking and order wisp beads without closing them") cmd.Flags().BoolVar(&quiet, "quiet", false, "suppress success output") + // The help text hardcodes the default threshold rather than calling + // bulkDeleteConfirmThreshold(): that reads the environment at command + // construction time, which would make docs/reference/cli.md regenerate + // differently depending on the generator's environment. + cmd.Flags().BoolVar(&confirm, "confirm", false, fmt.Sprintf("confirm bulk deletion when eligible count > GC_BULK_DELETE_CONFIRM_THRESHOLD (default %d)", defaultBulkDeleteConfirmThreshold)) return cmd } @@ -1275,16 +1352,16 @@ func validateOrderCheckPreflight(a orders.Order) error { // --- gc order history --- func cmdOrderHistory(name, rig string, stdout, stderr io.Writer) int { - return cmdOrderHistoryJSON(name, rig, false, stdout, stderr) + return cmdOrderHistoryJSON(name, rig, orderHistoryBounds{}, false, stdout, stderr) } -func cmdOrderHistoryJSON(name, rig string, jsonOutput bool, stdout, stderr io.Writer) int { +func cmdOrderHistoryJSON(name, rig string, bounds orderHistoryBounds, jsonOutput bool, stdout, stderr io.Writer) int { cityPath, cfg, aa, code := loadAllOrdersWithCity(stderr, "gc order history") if code != 0 { return code } c, reason := orderHistoryAPIClient(cityPath) - return routeOrderHistory(cityPath, cfg, name, rig, aa, c, reason, jsonOutput, stdout, stderr) + return routeOrderHistory(cityPath, cfg, name, rig, aa, c, reason, bounds, jsonOutput, stdout, stderr) } // orderHistoryAPIClient returns (client, "") when the API path is available, @@ -1302,7 +1379,7 @@ var orderHistoryAPIClient = func(cityPath string) (*api.Client, string) { // a single order is being queried and the controller is up; otherwise falls // back to the local iterator. Emits exactly one route=... log line per exit // path (gated on GC_DEBUG). -func routeOrderHistory(cityPath string, cfg *config.City, name, rig string, aa []orders.Order, c *api.Client, nilReason string, jsonOutput bool, stdout, stderr io.Writer) int { +func routeOrderHistory(cityPath string, cfg *config.City, name, rig string, aa []orders.Order, c *api.Client, nilReason string, bounds orderHistoryBounds, jsonOutput bool, stdout, stderr io.Writer) int { // Multi-order mode (no name provided) has no single scoped_name to // request against /orders/history; stay on the local iterator so we // produce the same aggregated output. The log line documents the @@ -1310,19 +1387,30 @@ func routeOrderHistory(cityPath string, cfg *config.City, name, rig string, aa [ // missing route=api. if name == "" { logRoute(stderr, "order history", "fallback", "multi-order") - return doOrderHistoryWithStoresResolverJSON(name, rig, aa, cachedOrderHistoryStoresResolver(cityPath, cfg, stderr), jsonOutput, stdout, stderr) + return doOrderHistoryBounded(name, rig, aa, cachedOrderHistoryStoresResolver(cityPath, cfg, stderr), bounds, jsonOutput, stdout, stderr) + } + + // The API has no wire representation for an unlimited read: omitting + // `limit` selects the server's own default (20), not "everything". Stay + // on the local iterator so `--limit 0` keeps meaning every retained run. + if bounds.Limit <= 0 { + logRoute(stderr, "order history", "fallback", "unlimited") + return doOrderHistoryBounded(name, rig, aa, cachedOrderHistoryStoresResolver(cityPath, cfg, stderr), bounds, jsonOutput, stdout, stderr) } var cr api.CachedRead[[]api.OrderHistoryView] return routeRead(c, "order history", nilReason, stderr, func() error { var err error - cr, err = c.GetOrderHistory(orderScopedName(name, rig, aa), 0, "") + // The server already accepts the row bound; --since has no wire + // equivalent (the API's `before` is an upper bound), so the time + // window is applied to the response below. + cr, err = c.GetOrderHistory(orderScopedName(name, rig, aa), bounds.Limit, "") return err }, - func() int { return renderOrderHistoryFromAPI(cr, name, rig, jsonOutput, stdout, stderr) }, + func() int { return renderOrderHistoryFromAPI(cr, name, rig, bounds, jsonOutput, stdout, stderr) }, func() int { - return doOrderHistoryWithStoresResolverJSON(name, rig, aa, cachedOrderHistoryStoresResolver(cityPath, cfg, stderr), jsonOutput, stdout, stderr) + return doOrderHistoryBounded(name, rig, aa, cachedOrderHistoryStoresResolver(cityPath, cfg, stderr), bounds, jsonOutput, stdout, stderr) }, ) } @@ -1341,12 +1429,39 @@ func orderScopedName(name, rig string, aa []orders.Order) string { return name + ":rig:" + rig } +// boundOrderHistoryViews applies the --since window to an API response. The +// server honors the row bound itself; the time window has no wire equivalent, +// so it is applied here rather than silently dropped. A row whose created_at +// the server cannot be parsed is an error, not a silently skipped row. +func boundOrderHistoryViews(views []api.OrderHistoryView, bounds orderHistoryBounds) ([]api.OrderHistoryView, error) { + cutoff, hasCutoff := bounds.cutoff(time.Now()) + if !hasCutoff { + return views, nil + } + kept := make([]api.OrderHistoryView, 0, len(views)) + for _, v := range views { + createdAt, err := time.Parse(time.RFC3339Nano, v.CreatedAt) + if err != nil { + return nil, fmt.Errorf("parsing API created_at %q: %w", v.CreatedAt, err) + } + if createdAt.Before(cutoff) { + continue + } + kept = append(kept, v) + } + return kept, nil +} + // renderOrderHistoryFromAPI prints the API-sourced order history to match // doOrderHistoryWithStoresResolver's human output. Empty results and // rig-column presence are preserved; a staleness banner appends when the // supervisor cache age exceeds the shared threshold. -func renderOrderHistoryFromAPI(cr api.CachedRead[[]api.OrderHistoryView], name, rig string, jsonOutput bool, stdout, stderr io.Writer) int { - entries := cr.Body +func renderOrderHistoryFromAPI(cr api.CachedRead[[]api.OrderHistoryView], name, rig string, bounds orderHistoryBounds, jsonOutput bool, stdout, stderr io.Writer) int { + entries, err := boundOrderHistoryViews(cr.Body, bounds) + if err != nil { + fmt.Fprintf(stderr, "gc order history: %v\n", err) //nolint:errcheck // best-effort stderr + return 1 + } if len(entries) == 0 { if jsonOutput { return writeCLIJSONLineOrExit(stdout, stderr, "gc order history", orderHistoryJSONResult{ @@ -1446,6 +1561,14 @@ func doOrderHistoryWithStoresResolver(name, rig string, aa []orders.Order, resol } func doOrderHistoryWithStoresResolverJSON(name, rig string, aa []orders.Order, resolveStores orderStoresResolver, jsonOutput bool, stdout, stderr io.Writer) int { + return doOrderHistoryBounded(name, rig, aa, resolveStores, orderHistoryBounds{}, jsonOutput, stdout, stderr) +} + +// doOrderHistoryBounded is doOrderHistoryWithStoresResolverJSON with an explicit +// read bound. The per-order fetch is capped at bounds.Limit: after the merge the +// output keeps only the newest Limit runs overall, so no single order can +// contribute more than that, and fetching more would be pure waste. +func doOrderHistoryBounded(name, rig string, aa []orders.Order, resolveStores orderStoresResolver, bounds orderHistoryBounds, jsonOutput bool, stdout, stderr io.Writer) int { // Filter orders if name or rig specified. targets := aa if name != "" || rig != "" { @@ -1469,6 +1592,7 @@ func doOrderHistoryWithStoresResolverJSON(name, rig string, aa []orders.Order, r } var entries []historyEntry seenEntries := make(map[string]bool) + cutoff, hasCutoff := bounds.cutoff(time.Now()) for _, a := range targets { stores, err := resolveStores(a) @@ -1480,7 +1604,7 @@ func doOrderHistoryWithStoresResolverJSON(name, rig string, aa []orders.Order, r if store.Store == nil { continue } - results, err := orders.NewStore(store).RecentRuns(a.ScopedName(), 0) + results, err := orders.NewStore(store).RecentRuns(a.ScopedName(), bounds.Limit) if err != nil { fmt.Fprintf(stderr, "gc order history: %v\n", err) //nolint:errcheck // best-effort stderr if i == 0 && len(results) == 0 { @@ -1491,6 +1615,9 @@ func doOrderHistoryWithStoresResolverJSON(name, rig string, aa []orders.Order, r } } for _, r := range results { + if hasCutoff && r.CreatedAt.Before(cutoff) { + continue + } key := a.ScopedName() + "\x00" + r.ID + "\x00" + r.CreatedAt.Format(time.RFC3339Nano) if seenEntries[key] { continue @@ -1528,6 +1655,13 @@ func doOrderHistoryWithStoresResolverJSON(name, rig string, aa []orders.Order, r sort.SliceStable(entries, func(i, j int) bool { return entries[i].createdAt.After(entries[j].createdAt) }) + // Multi-order mode merges one bounded fetch per order, so the union can + // still exceed the requested bound; cut it here, after the newest-first + // sort, so the rows kept are the newest overall rather than the newest of + // whichever order happened to be iterated first. + if bounds.Limit > 0 && len(entries) > bounds.Limit { + entries = entries[:bounds.Limit] + } if jsonOutput { payload := orderHistoryJSONResult{ @@ -1599,7 +1733,24 @@ type orderHistoryJSONSummary struct { // --- gc order sweep-tracking --- -func cmdOrderSweepTrackingWithOptions(staleAfter time.Duration, includeWisps, dryRun, quiet bool, orderNames []string, stdout, stderr io.Writer) int { +// defaultBulkDeleteConfirmThreshold is the built-in value of +// bulkDeleteConfirmThreshold when GC_BULK_DELETE_CONFIRM_THRESHOLD is unset. +const defaultBulkDeleteConfirmThreshold = 20 + +// bulkDeleteConfirmThreshold returns the maximum number of eligible retention +// deletions allowed without an explicit --confirm flag. Configurable via +// GC_BULK_DELETE_CONFIRM_THRESHOLD (positive integer); default 20. +func bulkDeleteConfirmThreshold() int { + if s := os.Getenv("GC_BULK_DELETE_CONFIRM_THRESHOLD"); s != "" { + var n int + if _, err := fmt.Sscanf(s, "%d", &n); err == nil && n > 0 { + return n + } + } + return defaultBulkDeleteConfirmThreshold +} + +func cmdOrderSweepTrackingWithOptions(staleAfter time.Duration, includeWisps, dryRun, quiet, confirm bool, orderNames []string, stdout, stderr io.Writer) int { if staleAfter <= 0 { fmt.Fprintln(stderr, "gc order sweep-tracking: --stale-after must be positive") //nolint:errcheck // best-effort stderr return 1 @@ -1638,12 +1789,41 @@ func cmdOrderSweepTrackingWithOptions(staleAfter time.Duration, includeWisps, dr var sweepErr error var retentionResult orderTrackingRetentionSweepResult var retentionErr error + // Set when the bulk-delete confirm gate blocks the retention sweep. By that + // point stale-close has already run, so normal reporting still happens and + // the non-zero exit is deferred to the end of the function. + confirmGateBlocked := false if dryRun { result, sweepErr = sweepStaleOrderTrackingAcrossStoresDryRun(stores, now, staleAfter, onlyOrders, includeWisps) } else { result, sweepErr = sweepStaleOrderTrackingAcrossStores(stores, now, staleAfter, onlyOrders, includeWisps) - retentionResult, retentionErr = sweepClosedOrderTrackingRetentionAcrossStores(stores, now, orderTrackingRetentionPolicyForConfig(cfg), onlyOrders) - result.trackingDeleted = retentionResult.deleted + + // Bulk-delete confirm gate: before any retention deletions, count + // eligible beads and require --confirm when above + // GC_BULK_DELETE_CONFIRM_THRESHOLD. The gate covers only the retention + // sweep — stale-close runs first and unconditionally, so a tripped gate + // can never wedge the stale-close every caller depends on. + // Fail-closed: a store read error blocks deletion rather than proceeding + // unguarded — a degraded store is exactly when accidental mass deletion + // is most dangerous. + retentionPolicy := orderTrackingRetentionPolicyForConfig(cfg) + eligible, countErr := countClosedOrderTrackingRetentionEligible(stores, now, retentionPolicy, onlyOrders) + threshold := bulkDeleteConfirmThreshold() + switch { + case countErr != nil: + fmt.Fprintf(stderr, //nolint:errcheck // best-effort stderr + "gc order sweep-tracking: cannot count eligible beads for confirm gate: %v — aborting to avoid unguarded bulk delete\n", + countErr) + confirmGateBlocked = true + case eligible > threshold && !confirm: + fmt.Fprintf(stderr, //nolint:errcheck // best-effort stderr + "gc order sweep-tracking: %d beads would be deleted — rerun with --confirm to proceed (GC_BULK_DELETE_CONFIRM_THRESHOLD=%d)\n", + eligible, threshold) + confirmGateBlocked = true + default: + retentionResult, retentionErr = sweepClosedOrderTrackingRetentionAcrossStores(stores, now, retentionPolicy, onlyOrders) + result.trackingDeleted = retentionResult.deleted + } } if err := errors.Join(openErr, sweepErr, retentionErr); err != nil { fmt.Fprintf(stderr, "gc order sweep-tracking: %v\n", err) //nolint:errcheck // best-effort stderr @@ -1668,6 +1848,9 @@ func cmdOrderSweepTrackingWithOptions(staleAfter time.Duration, includeWisps, dr fmt.Fprintf(stdout, "%s %d stale order-tracking bead(s)%s\n", verb, result.trackingClosed, deletedClause) //nolint:errcheck // best-effort stdout } } + if confirmGateBlocked { + return 1 + } return 0 } diff --git a/cmd/gc/cmd_order_history_bounds_test.go b/cmd/gc/cmd_order_history_bounds_test.go new file mode 100644 index 0000000000..12ff030190 --- /dev/null +++ b/cmd/gc/cmd_order_history_bounds_test.go @@ -0,0 +1,286 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + "time" + + "github.com/gastownhall/gascity/internal/api" + "github.com/gastownhall/gascity/internal/beads" + "github.com/gastownhall/gascity/internal/orders" +) + +const ( + // orderHistoryTestOrder is the single order these bound tests exercise. + orderHistoryTestOrder = "digest" + // orderHistoryTestRunCount is how many runs the fixture seeds — comfortably + // more than any bound under test, so a bound that silently fails to apply + // shows up as a count mismatch. + orderHistoryTestRunCount = 25 +) + +// orderHistoryRunsStore builds a store holding orderHistoryTestRunCount +// order-run beads for orderHistoryTestOrder, one per hour going back from now, +// newest first. It goes through the bd-backed store rather than the in-memory +// one because MemStore.Create stamps its own CreatedAt, and these tests are +// entirely about created_at ordering and windows. +func orderHistoryRunsStore(t *testing.T, now time.Time) beads.Store { + t.Helper() + rows := make([]string, 0, orderHistoryTestRunCount) + for i := 0; i < orderHistoryTestRunCount; i++ { + rows = append(rows, fmt.Sprintf( + `{"id":"WP-%d","title":"run %d","status":"closed","issue_type":"task","created_at":%q,"labels":["order-run:%s"]}`, + i, i, now.Add(-time.Duration(i)*time.Hour).Format(time.RFC3339Nano), orderHistoryTestOrder, + )) + } + payload := []byte("[" + strings.Join(rows, ",") + "]") + return beads.NewBdStore(t.TempDir(), func(_, _ string, args ...string) ([]byte, error) { + if strings.Contains(strings.Join(args, " "), "--label=order-run:"+orderHistoryTestOrder) { + return payload, nil + } + return []byte(`[]`), nil + }) +} + +func orderHistoryEntries(t *testing.T, stdout *bytes.Buffer) orderHistoryJSONResult { + t.Helper() + var payload orderHistoryJSONResult + if err := json.Unmarshal(stdout.Bytes(), &payload); err != nil { + t.Fatalf("stdout is not JSON: %v\n%s", err, stdout.String()) + } + return payload +} + +// TestOrderHistoryLimitCapsEntries pins the `--limit` contract: an operator who +// bounds the read gets at most that many runs back. Without a bound the command +// pulls every retained run, which measured 22s on a city with 11k+ order-run +// rows and made the command unusable interactively (ga-klv). +func TestOrderHistoryLimitCapsEntries(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + store := orderHistoryRunsStore(t, now) + aa := []orders.Order{{Name: "digest", Formula: "mol-digest"}} + resolver := func(orders.Order) ([]beads.OrdersStore, error) { + return []beads.OrdersStore{{Store: store}}, nil + } + + var stdout, stderr bytes.Buffer + code := doOrderHistoryBounded("digest", "", aa, resolver, orderHistoryBounds{Limit: 5}, true, &stdout, &stderr) + if code != 0 { + t.Fatalf("doOrderHistoryBounded = %d, want 0; stderr: %s", code, stderr.String()) + } + + payload := orderHistoryEntries(t, &stdout) + if len(payload.Entries) != 5 { + t.Fatalf("entries = %d, want 5 (the requested limit)", len(payload.Entries)) + } + if payload.Summary.Total != 5 { + t.Fatalf("summary.total = %d, want 5", payload.Summary.Total) + } + // Newest-first: the limit must keep the most recent runs, not an arbitrary + // slice — a history listing that drops the newest rows is useless. + if !payload.Entries[0].CreatedAt.Equal(now) { + t.Fatalf("first entry created_at = %s, want the newest run %s", payload.Entries[0].CreatedAt, now) + } +} + +// TestOrderHistoryLimitZeroStaysUnlimited keeps the escape hatch honest: an +// operator who explicitly asks for everything still gets everything. +func TestOrderHistoryLimitZeroStaysUnlimited(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + store := orderHistoryRunsStore(t, now) + aa := []orders.Order{{Name: "digest", Formula: "mol-digest"}} + resolver := func(orders.Order) ([]beads.OrdersStore, error) { + return []beads.OrdersStore{{Store: store}}, nil + } + + var stdout, stderr bytes.Buffer + code := doOrderHistoryBounded("digest", "", aa, resolver, orderHistoryBounds{Limit: 0}, true, &stdout, &stderr) + if code != 0 { + t.Fatalf("doOrderHistoryBounded = %d, want 0; stderr: %s", code, stderr.String()) + } + if payload := orderHistoryEntries(t, &stdout); len(payload.Entries) != orderHistoryTestRunCount { + t.Fatalf("entries = %d, want all %d", len(payload.Entries), orderHistoryTestRunCount) + } +} + +// TestOrderHistorySinceDropsOlderRuns pins the `--since` contract. +func TestOrderHistorySinceDropsOlderRuns(t *testing.T) { + now := time.Now().UTC().Truncate(time.Second) + store := orderHistoryRunsStore(t, now) + aa := []orders.Order{{Name: "digest", Formula: "mol-digest"}} + resolver := func(orders.Order) ([]beads.OrdersStore, error) { + return []beads.OrdersStore{{Store: store}}, nil + } + + var stdout, stderr bytes.Buffer + // Runs are one hour apart. The window deliberately lands between two of + // them (5h30m) rather than exactly on one: the cutoff is computed at call + // time, a hair after the fixture's `now`, so a window landing exactly on a + // run would flip that run in or out on timing alone. + window := 5*time.Hour + 30*time.Minute + code := doOrderHistoryBounded("digest", "", aa, resolver, orderHistoryBounds{Since: window}, true, &stdout, &stderr) + if code != 0 { + t.Fatalf("doOrderHistoryBounded = %d, want 0; stderr: %s", code, stderr.String()) + } + + payload := orderHistoryEntries(t, &stdout) + if len(payload.Entries) != 6 { + t.Fatalf("entries = %d, want the 6 runs (0h..5h old) inside the %s window", len(payload.Entries), window) + } + cutoff := now.Add(-window) + for i, e := range payload.Entries { + if e.CreatedAt.Before(cutoff) { + t.Fatalf("entry %d created_at = %s, older than the --since cutoff %s", i, e.CreatedAt, cutoff) + } + } +} + +// TestOrderHistoryLimitAndSinceCompose checks the combined semantic: at most +// Limit runs, none older than Since. +func TestOrderHistoryLimitAndSinceCompose(t *testing.T) { + now := time.Now().UTC().Truncate(time.Second) + store := orderHistoryRunsStore(t, now) + aa := []orders.Order{{Name: "digest", Formula: "mol-digest"}} + resolver := func(orders.Order) ([]beads.OrdersStore, error) { + return []beads.OrdersStore{{Store: store}}, nil + } + + var stdout, stderr bytes.Buffer + code := doOrderHistoryBounded("digest", "", aa, resolver, orderHistoryBounds{Limit: 3, Since: 10 * time.Hour}, true, &stdout, &stderr) + if code != 0 { + t.Fatalf("doOrderHistoryBounded = %d, want 0; stderr: %s", code, stderr.String()) + } + if payload := orderHistoryEntries(t, &stdout); len(payload.Entries) != 3 { + t.Fatalf("entries = %d, want 3 (limit wins inside a wider since window)", len(payload.Entries)) + } +} + +// TestOrderHistoryDefaultLimitIsBounded is the regression guard for the +// interactive-cost half of ga-klv: the command must ship a positive default +// bound. An unbounded default is what made a plain `gc order history` take 22s. +func TestOrderHistoryDefaultLimitIsBounded(t *testing.T) { + if defaultOrderHistoryLimit <= 0 { + t.Fatalf("defaultOrderHistoryLimit = %d, want positive; an unbounded default restores the 22s interactive read", defaultOrderHistoryLimit) + } + + var stdout, stderr bytes.Buffer + cmd := newOrderHistoryCmd(&stdout, &stderr) + for _, name := range []string{"limit", "since"} { + if cmd.Flags().Lookup(name) == nil { + t.Fatalf("gc order history is missing the --%s flag", name) + } + } + limitFlag := cmd.Flags().Lookup("limit") + if limitFlag.DefValue != fmt.Sprint(defaultOrderHistoryLimit) { + t.Fatalf("--limit default = %q, want %d", limitFlag.DefValue, defaultOrderHistoryLimit) + } +} + +// TestOrderHistoryRejectsBadSince keeps the duration parse at the CLI edge, so a +// typo fails fast with a usable message instead of being silently ignored. +func TestOrderHistoryRejectsBadSince(t *testing.T) { + var stdout, stderr bytes.Buffer + cmd := newOrderHistoryCmd(&stdout, &stderr) + cmd.SetOut(&stdout) + cmd.SetErr(&stderr) + cmd.SetArgs([]string{"--since", "yesterday"}) + + if err := cmd.Execute(); err == nil { + t.Fatal("gc order history --since yesterday returned nil error, want a parse failure") + } + if combined := stdout.String() + stderr.String(); !strings.Contains(combined, "since") { + t.Fatalf("output = %q, want it to name the bad --since value", combined) + } +} + +// TestOrderHistoryLimitReachesStoreQuery proves the bound is pushed into the +// read rather than applied only after fetching everything. Trimming client-side +// still pays the full fetch and serialization cost this bead is about. +func TestOrderHistoryLimitReachesStoreQuery(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + spy := &orderHistoryListSpy{Store: orderHistoryRunsStore(t, now)} + aa := []orders.Order{{Name: "digest", Formula: "mol-digest"}} + resolver := func(orders.Order) ([]beads.OrdersStore, error) { + return []beads.OrdersStore{{Store: spy}}, nil + } + + var stdout, stderr bytes.Buffer + if code := doOrderHistoryBounded("digest", "", aa, resolver, orderHistoryBounds{Limit: 5}, true, &stdout, &stderr); code != 0 { + t.Fatalf("doOrderHistoryBounded = %d, want 0; stderr: %s", code, stderr.String()) + } + if len(spy.queries) == 0 { + t.Fatal("no list query reached the store") + } + for i, q := range spy.queries { + if q.Limit != 5 { + t.Fatalf("query %d: Limit = %d, want 5 pushed into the read", i, q.Limit) + } + } +} + +// TestOrderHistoryUnlimitedAvoidsAPIRoute pins the routing half of the +// `--limit 0` contract. The API has no wire representation for an unlimited +// read: GetOrderHistory omits `limit` when it is non-positive, and the server +// then applies its own default of 20 rows. An API-routed `--limit 0` would +// therefore silently return 20 runs while the flag help promises every +// retained one, so an unbounded read must stay on the local iterator. +func TestOrderHistoryUnlimitedAvoidsAPIRoute(t *testing.T) { + t.Setenv("GC_DEBUG", "1") // force route=... lines into the stderr buffer + + cityPath := writeOrderHistoryTestCity(t) + cfg, err := loadCityConfig(cityPath, &bytes.Buffer{}) + if err != nil { + t.Fatalf("loadCityConfig: %v", err) + } + aa, code := loadAllOrders(cityPath, cfg, &bytes.Buffer{}, "test") + if code != 0 { + t.Fatalf("loadAllOrders = %d", code) + } + + // A non-nil client pointed at a port that always refuses. The only reason + // to skip the API here is the unlimited bound itself: if the routing + // regresses and consults the API, routeRead logs route=api or a fallback + // whose reason comes from api.FallbackReason (route_read.go:44-77) — never + // "unlimited" — so the assertion below still catches it without a server. + c := api.NewCityScopedClient("http://127.0.0.1:1", "test-city") + + var stdout, stderr bytes.Buffer + if got := routeOrderHistory(cityPath, cfg, "digest", "", aa, c, "", orderHistoryBounds{}, false, &stdout, &stderr); got != 0 { + t.Fatalf("exit = %d, want 0; stderr=%q", got, stderr.String()) + } + if !strings.Contains(stderr.String(), "route=fallback reason=unlimited") { + t.Fatalf("stderr missing %q:\n%s", "route=fallback reason=unlimited", stderr.String()) + } +} + +// TestOrderHistoryRejectsNegativeLimit keeps 0 as the only spelling of +// "unlimited". A negative limit was previously accepted and read two different +// ways — unlimited locally, the server's 20-row default over the API — so it +// is rejected at the CLI edge instead. +func TestOrderHistoryRejectsNegativeLimit(t *testing.T) { + var stdout, stderr bytes.Buffer + cmd := newOrderHistoryCmd(&stdout, &stderr) + cmd.SetOut(&stdout) + cmd.SetErr(&stderr) + cmd.SetArgs([]string{"--limit", "-1"}) + + if err := cmd.Execute(); err == nil { + t.Fatal("gc order history --limit -1 returned nil error, want a validation failure") + } + if combined := stdout.String() + stderr.String(); !strings.Contains(combined, "--limit") { + t.Fatalf("output = %q, want it to name --limit", combined) + } +} + +type orderHistoryListSpy struct { + beads.Store + queries []beads.ListQuery +} + +func (s *orderHistoryListSpy) List(q beads.ListQuery) ([]beads.Bead, error) { + s.queries = append(s.queries, q) + return s.Store.List(q) +} diff --git a/cmd/gc/cmd_order_test.go b/cmd/gc/cmd_order_test.go index 54a19a2b1b..c2ce3aeaa8 100644 --- a/cmd/gc/cmd_order_test.go +++ b/cmd/gc/cmd_order_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "log" @@ -16,6 +17,7 @@ import ( "testing" "time" + "github.com/BurntSushi/toml" "github.com/gastownhall/gascity/internal/api" "github.com/gastownhall/gascity/internal/beadmeta" "github.com/gastownhall/gascity/internal/beads" @@ -1319,7 +1321,7 @@ prefix = "fe" } var stdout, stderr bytes.Buffer - code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, []string{"rig-digest:rig:frontend"}, &stdout, &stderr) + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, false, []string{"rig-digest:rig:frontend"}, &stdout, &stderr) if code != 0 { t.Fatalf("cmdOrderSweepTracking = %d, want 0; stderr: %s", code, stderr.String()) } @@ -1385,7 +1387,7 @@ prefix = "fe" } var stdout, stderr bytes.Buffer - code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, nil, &stdout, &stderr) + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, false, nil, &stdout, &stderr) if code != 0 { t.Fatalf("cmdOrderSweepTracking = %d, want 0; stderr: %s", code, stderr.String()) } @@ -1449,7 +1451,7 @@ prefix = "ct" } var stdout, stderr bytes.Buffer - code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, nil, &stdout, &stderr) + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, false, nil, &stdout, &stderr) if code != 0 { t.Fatalf("cmdOrderSweepTracking = %d, want 0; stderr: %s", code, stderr.String()) } @@ -1523,7 +1525,7 @@ delete_after_close = "1ns" } var stdout, stderr bytes.Buffer - code := cmdOrderSweepTrackingWithOptions(time.Hour, false, false, false, nil, &stdout, &stderr) + code := cmdOrderSweepTrackingWithOptions(time.Hour, false, false, false, false, nil, &stdout, &stderr) if code != 0 { t.Fatalf("cmdOrderSweepTracking = %d, want 0; stderr: %s", code, stderr.String()) } @@ -1606,7 +1608,7 @@ delete_after_close = "1ns" } var stdout, stderr bytes.Buffer - code := cmdOrderSweepTrackingWithOptions(time.Hour, true, false, false, nil, &stdout, &stderr) + code := cmdOrderSweepTrackingWithOptions(time.Hour, true, false, false, false, nil, &stdout, &stderr) if code == 0 { t.Fatalf("cmdOrderSweepTracking = 0, want failure") } @@ -1670,7 +1672,7 @@ prefix = "fe" } var stdout, stderr bytes.Buffer - code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, []string{"cleanup"}, &stdout, &stderr) + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, false, []string{"cleanup"}, &stdout, &stderr) if code != 0 { t.Fatalf("cmdOrderSweepTracking = %d, want 0; stderr: %s", code, stderr.String()) } @@ -1730,7 +1732,7 @@ prefix = "ct" } var stdout, stderr bytes.Buffer - code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, true, false, []string{"cleanup"}, &stdout, &stderr) + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, true, false, false, []string{"cleanup"}, &stdout, &stderr) if code != 0 { t.Fatalf("cmdOrderSweepTrackingWithOptions = %d, want 0; stderr: %s", code, stderr.String()) } @@ -1784,7 +1786,7 @@ prefix = "fe" } var stdout, stderr bytes.Buffer - code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, []string{"rig-digest:rig:frontend"}, &stdout, &stderr) + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, false, []string{"rig-digest:rig:frontend"}, &stdout, &stderr) if code == 0 { t.Fatalf("cmdOrderSweepTracking = 0, want failure; stdout: %s stderr: %s", stdout.String(), stderr.String()) } @@ -3821,7 +3823,7 @@ func TestRouteOrderHistory_SixRowMatrix(t *testing.T) { } var stdout, stderr bytes.Buffer - got := routeOrderHistory(cityPath, cfg, "digest", "", aa, c, tc.nilReason, false, &stdout, &stderr) + got := routeOrderHistory(cityPath, cfg, "digest", "", aa, c, tc.nilReason, orderHistoryBounds{Limit: defaultOrderHistoryLimit}, false, &stdout, &stderr) if got != tc.wantExit { t.Fatalf("exit = %d, want %d; stderr=%q stdout=%q", got, tc.wantExit, stderr.String(), stdout.String()) @@ -3877,7 +3879,7 @@ func TestRouteOrderHistory_MultiOrderFallback(t *testing.T) { var stdout, stderr bytes.Buffer // Name empty → should not hit the API. - if got := routeOrderHistory(cityPath, cfg, "", "", aa, c, "", false, &stdout, &stderr); got != 0 { + if got := routeOrderHistory(cityPath, cfg, "", "", aa, c, "", orderHistoryBounds{}, false, &stdout, &stderr); got != 0 { t.Fatalf("exit = %d, stderr=%q", got, stderr.String()) } if !strings.Contains(stderr.String(), "route=fallback reason=multi-order") { @@ -3919,7 +3921,7 @@ func TestRouteOrderHistory_StaleBannerOver30s(t *testing.T) { c := api.NewCityScopedClient(srv.URL, "test-city") var stdout, stderr bytes.Buffer - if code := routeOrderHistory(cityPath, cfg, "digest", "", aa, c, "", false, &stdout, &stderr); code != 0 { + if code := routeOrderHistory(cityPath, cfg, "digest", "", aa, c, "", orderHistoryBounds{Limit: defaultOrderHistoryLimit}, false, &stdout, &stderr); code != 0 { t.Fatalf("exit = %d, stderr=%q", code, stderr.String()) } if !strings.Contains(stdout.String(), "cache age: 45s") { @@ -4024,3 +4026,270 @@ func TestOrderCheckCooldownStaleEventFallsThroughToLastRunStore(t *testing.T) { t.Fatalf("stale event did not fall through to last-run store; expected last-run error in stderr:\n%s", stderr.String()) } } + +// TestOrderSweepTrackingRequiresConfirm verifies that cmdOrderSweepTrackingWithOptions +// returns exit 1 with a descriptive message when the number of eligible deletions +// exceeds GC_BULK_DELETE_CONFIRM_THRESHOLD and confirm=false. +func TestOrderSweepTrackingRequiresConfirm(t *testing.T) { + t.Setenv("GC_BEADS", "file") + t.Setenv("GC_BEADS_SCOPE_ROOT", "") + // Set threshold low (1) so a single eligible retention bead triggers the guard. + t.Setenv("GC_BULK_DELETE_CONFIRM_THRESHOLD", "1") + + cityDir := t.TempDir() + t.Setenv("GC_CITY", cityDir) + t.Setenv("GC_CITY_PATH", cityDir) + t.Setenv("GC_CITY_ROOT", cityDir) + t.Setenv("GC_RIG", "") + t.Setenv("GC_RIG_ROOT", "") + t.Chdir(cityDir) + + writeFile(t, filepath.Join(cityDir, "city.toml"), `[workspace] +name = "test-city" +prefix = "ct" +`) + if err := ensureScopedFileStoreLayout(cityDir); err != nil { + t.Fatal(err) + } + + // Seed 12 closed order-tracking beads (10d old > 7d TTL, exceeds retain-10 floor → 2 eligible). + // Write JSON directly: store.Create always forces Status="open" and CreatedAt=time.Now(), + // which would make the count gate see 0 eligible closed beads. + now := time.Now() + type fileStoreJSON struct { + Seq int `json:"seq"` + Beads []beads.Bead `json:"beads"` + } + n := minClosedOrderTrackingRetained + 2 + seedBeads := make([]beads.Bead, 0, n+1) + for i := range n { + seedBeads = append(seedBeads, beads.Bead{ + ID: fmt.Sprintf("sg-%02d", i), + Title: "order:sweep-guard", + Status: "closed", + Type: "task", + CreatedAt: now.Add(-10*24*time.Hour + time.Duration(i)*time.Minute), + Labels: []string{"order-run:sweep-guard", labelOrderTracking}, + Ephemeral: true, + }) + } + // One open stale bead in its own order-run group: stale-close is sequenced + // before the gate, so a tripped gate must not suppress it. + const openID = "sg-open" + seedBeads = append(seedBeads, beads.Bead{ + ID: openID, + Title: "order:sweep-guard-open", + Status: "open", + Type: "task", + CreatedAt: now.Add(-10 * 24 * time.Hour), + Labels: []string{"order-run:sweep-guard-open", labelOrderTracking}, + Ephemeral: true, + }) + seedData, err := json.Marshal(fileStoreJSON{Seq: len(seedBeads), Beads: seedBeads}) + if err != nil { + t.Fatalf("marshal seed beads: %v", err) + } + beadsPath := filepath.Join(cityDir, ".gc", "beads.json") + if err := os.WriteFile(beadsPath, seedData, 0o644); err != nil { + t.Fatalf("write seed beads.json: %v", err) + } + + var stdout, stderr bytes.Buffer + // confirm=false: should return 1 and print descriptive message. + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, false, nil, &stdout, &stderr) + if code != 1 { + t.Fatalf("cmdOrderSweepTrackingWithOptions (no confirm) = %d, want 1; stderr: %s stdout: %s", code, stderr.String(), stdout.String()) + } + got := stderr.String() + if !strings.Contains(got, "confirm") { + t.Fatalf("stderr = %q, want '--confirm' hint in message", got) + } + if !strings.Contains(got, "GC_BULK_DELETE_CONFIRM_THRESHOLD") { + t.Fatalf("stderr = %q, want GC_BULK_DELETE_CONFIRM_THRESHOLD in message", got) + } + // The gate blocks the retention deletions only. Stale-close ran first and + // its work is durable even though the command exits 1. + reopened, err := openStoreAtForCity(cityDir, cityDir) + if err != nil { + t.Fatalf("openStoreAtForCity: %v", err) + } + openBead, err := reopened.Get(openID) + if err != nil { + t.Fatalf("Get(%s): %v", openID, err) + } + if openBead.Status != "closed" { + t.Fatalf("%s status = %q, want closed — a tripped confirm gate must not suppress stale-close", openID, openBead.Status) + } + // ...and nothing was deleted. + for i := range n { + id := fmt.Sprintf("sg-%02d", i) + if _, err := reopened.Get(id); err != nil { + t.Fatalf("%s should survive a tripped confirm gate: %v", id, err) + } + } +} + +// TestOrderSweepTrackingConfirmGateFailsClosedOnCountError verifies that when +// countClosedOrderTrackingRetentionEligible fails (store read error), the confirm +// gate returns exit 1 with a descriptive message rather than proceeding unguarded. +func TestOrderSweepTrackingConfirmGateFailsClosedOnCountError(t *testing.T) { + // A failing exec script makes store.List() return an error, exercising the + // countErr != nil fail-closed path without requiring a real beads provider. + failScript := filepath.Join(t.TempDir(), "gc-beads-fail") + if err := os.WriteFile(failScript, []byte("#!/bin/sh\nexit 1\n"), 0o755); err != nil { + t.Fatalf("write fail script: %v", err) + } + t.Setenv("GC_BEADS", "exec:"+failScript) + t.Setenv("GC_BEADS_SCOPE_ROOT", "") + + cityDir := t.TempDir() + t.Setenv("GC_CITY", cityDir) + t.Setenv("GC_CITY_PATH", cityDir) + t.Setenv("GC_CITY_ROOT", cityDir) + t.Setenv("GC_RIG", "") + t.Setenv("GC_RIG_ROOT", "") + t.Chdir(cityDir) + + writeFile(t, filepath.Join(cityDir, "city.toml"), `[workspace] +name = "test-city" +prefix = "ct" +`) + if err := ensureScopedFileStoreLayout(cityDir); err != nil { + t.Fatal(err) + } + + var stdout, stderr bytes.Buffer + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, false, nil, &stdout, &stderr) + if code != 1 { + t.Fatalf("cmdOrderSweepTrackingWithOptions (count error) = %d, want 1; stderr: %s stdout: %s", code, stderr.String(), stdout.String()) + } + got := stderr.String() + if !strings.Contains(got, "cannot count eligible beads for confirm gate") { + t.Fatalf("stderr = %q, want 'cannot count eligible beads for confirm gate' in message", got) + } +} + +// TestPackagedOrderTrackingSweepPassesConfirm pins the packaged core sweep +// order to --confirm. The order runs unattended every minute, so without the +// flag the bulk-delete gate fails it on every tick once the backlog passes the +// threshold — and takes stale-close down with it. Nothing else would catch a +// regression here until a city's tracking backlog stopped draining. +func TestPackagedOrderTrackingSweepPassesConfirm(t *testing.T) { + const packOrderPath = "../../internal/bootstrap/packs/core/orders/order-tracking-sweep.toml" + var packed struct { + Order struct { + Exec string `toml:"exec"` + } `toml:"order"` + } + if _, err := toml.DecodeFile(packOrderPath, &packed); err != nil { + t.Fatalf("decode %s: %v", packOrderPath, err) + } + if !strings.Contains(packed.Order.Exec, "gc order sweep-tracking") { + t.Fatalf("exec = %q, want a gc order sweep-tracking invocation", packed.Order.Exec) + } + if !strings.Contains(packed.Order.Exec, "--confirm") { + t.Fatalf("exec = %q, want --confirm so the unattended sweep clears the bulk-delete gate", packed.Order.Exec) + } + // The flag the exec line passes must still exist on the command. + if flag := newOrderSweepTrackingCmd(io.Discard, io.Discard).Flags().Lookup("confirm"); flag == nil { + t.Fatal("gc order sweep-tracking has no --confirm flag, but the packaged order passes one") + } +} + +// TestOrderSweepTrackingConfirmAboveThresholdSweepsAndPrunes verifies the +// confirmed path above the threshold: exit 0, retention deletions happen, and +// stale-close still runs. Stale-close is sequenced before the gate precisely so +// it can never be suppressed by it. +func TestOrderSweepTrackingConfirmAboveThresholdSweepsAndPrunes(t *testing.T) { + t.Setenv("GC_BEADS", "file") + t.Setenv("GC_BEADS_SCOPE_ROOT", "") + // Threshold 1 puts the 2 eligible retention beads above the gate. + t.Setenv("GC_BULK_DELETE_CONFIRM_THRESHOLD", "1") + + cityDir := t.TempDir() + t.Setenv("GC_CITY", cityDir) + t.Setenv("GC_CITY_PATH", cityDir) + t.Setenv("GC_CITY_ROOT", cityDir) + t.Setenv("GC_RIG", "") + t.Setenv("GC_RIG_ROOT", "") + t.Chdir(cityDir) + + writeFile(t, filepath.Join(cityDir, "city.toml"), `[workspace] +name = "test-city" +prefix = "ct" +`) + if err := ensureScopedFileStoreLayout(cityDir); err != nil { + t.Fatal(err) + } + + // Seed directly as JSON: store.Create forces Status="open" and + // CreatedAt=time.Now(), which would leave 0 eligible closed beads. + now := time.Now() + type fileStoreJSON struct { + Seq int `json:"seq"` + Beads []beads.Bead `json:"beads"` + } + n := minClosedOrderTrackingRetained + 2 + seedBeads := make([]beads.Bead, 0, n+1) + for i := range n { + seedBeads = append(seedBeads, beads.Bead{ + ID: fmt.Sprintf("sc-%02d", i), + Title: "order:sweep-confirm", + Status: "closed", + Type: "task", + CreatedAt: now.Add(-10*24*time.Hour + time.Duration(i)*time.Minute), + Labels: []string{"order-run:sweep-confirm", labelOrderTracking}, + Ephemeral: true, + }) + } + // One open stale bead in its own order-run group, so stale-close has work + // to do without perturbing the retention group's retain-floor arithmetic. + const openID = "sc-open" + seedBeads = append(seedBeads, beads.Bead{ + ID: openID, + Title: "order:sweep-open", + Status: "open", + Type: "task", + CreatedAt: now.Add(-10 * 24 * time.Hour), + Labels: []string{"order-run:sweep-open", labelOrderTracking}, + Ephemeral: true, + }) + seedData, err := json.Marshal(fileStoreJSON{Seq: len(seedBeads), Beads: seedBeads}) + if err != nil { + t.Fatalf("marshal seed beads: %v", err) + } + if err := os.WriteFile(filepath.Join(cityDir, ".gc", "beads.json"), seedData, 0o644); err != nil { + t.Fatalf("write seed beads.json: %v", err) + } + + var stdout, stderr bytes.Buffer + code := cmdOrderSweepTrackingWithOptions(time.Nanosecond, false, false, false, true, nil, &stdout, &stderr) + if code != 0 { + t.Fatalf("cmdOrderSweepTrackingWithOptions (confirm) = %d, want 0; stderr: %s stdout: %s", code, stderr.String(), stdout.String()) + } + + reopened, err := openStoreAtForCity(cityDir, cityDir) + if err != nil { + t.Fatalf("openStoreAtForCity: %v", err) + } + // Retention deleted the 2 beads past the retain-10 floor. + for _, id := range []string{"sc-00", "sc-01"} { + if _, err := reopened.Get(id); !errors.Is(err, beads.ErrNotFound) { + t.Fatalf("Get(%s) err = %v, want ErrNotFound (should be pruned under --confirm)", id, err) + } + } + for i := 2; i < n; i++ { + id := fmt.Sprintf("sc-%02d", i) + if _, err := reopened.Get(id); err != nil { + t.Fatalf("%s should be preserved at the retain floor: %v", id, err) + } + } + // Stale-close ran too. + got, err := reopened.Get(openID) + if err != nil { + t.Fatalf("Get(%s): %v", openID, err) + } + if got.Status != "closed" { + t.Fatalf("%s status = %q, want closed — stale-close must run alongside retention", openID, got.Status) + } +} diff --git a/cmd/gc/cmd_prime.go b/cmd/gc/cmd_prime.go index ed3e50162f..10c06b1c8f 100644 --- a/cmd/gc/cmd_prime.go +++ b/cmd/gc/cmd_prime.go @@ -695,8 +695,8 @@ func persistPrimeHookProviderSessionKey(hookProviderSessionID string, stderr io. warn("%v", err) return } - if fromHookStdin && sessionProviderFamily(info) != "codex" { - warn("hook stdin provider session id is only accepted for codex session %q", gcSessionID) + if fromHookStdin && !providerAcceptsHookStdinSessionID(sessionProviderFamily(info)) { + warn("hook stdin provider session id is only accepted for codex/claude session %q", gcSessionID) return } if existing := strings.TrimSpace(info.SessionKey); existing != "" { @@ -704,6 +704,30 @@ func persistPrimeHookProviderSessionKey(hookProviderSessionID string, stderr io. } if err := sessFront.SetMarker(gcSessionID, "session_key", providerSessionID); err != nil { warn("writing session_key for session %q: %v", gcSessionID, err) + return + } + // Runs once per session (the empty-key check above guards re-entry). + if stderr != nil { + fmt.Fprintf(stderr, "gc prime --hook: persisted resume session_key for %s session %q\n", sessionProviderFamily(info), gcSessionID) //nolint:errcheck // hook diagnostics are best effort. + } +} + +// providerAcceptsHookStdinSessionID reports whether a provider family delivers +// its authoritative resume id on the SessionStart hook's stdin JSON. codex and +// claude both run through the settings.json `gc prime --hook` path and emit +// their own session id there, so it is the authoritative resume key. Other CLI +// providers surface it via env instead (GC_PROVIDER_SESSION_ID for the +// JS-plugin providers, GEMINI_SESSION_ID for gemini) and are handled above, +// before this stdin gate. Claude cannot be handed an id up front +// (`--session-id` is unsupported, so the builtin profile sets no +// session_id_flag); capturing the hook-delivered id is the only way its +// wake_mode=resume ever has a conversation to resume. +func providerAcceptsHookStdinSessionID(family string) bool { + switch family { + case "codex", "claude": + return true + default: + return false } } diff --git a/cmd/gc/cmd_sling.go b/cmd/gc/cmd_sling.go index e4a1f9dc42..cd1b8f5798 100644 --- a/cmd/gc/cmd_sling.go +++ b/cmd/gc/cmd_sling.go @@ -22,6 +22,7 @@ import ( "github.com/gastownhall/gascity/internal/events" "github.com/gastownhall/gascity/internal/formula" "github.com/gastownhall/gascity/internal/graphroute" + "github.com/gastownhall/gascity/internal/graphv2" "github.com/gastownhall/gascity/internal/runtime" "github.com/gastownhall/gascity/internal/session" "github.com/gastownhall/gascity/internal/shellquote" @@ -1797,6 +1798,17 @@ func dryRunSingle(opts slingOpts, deps slingDeps, querier BeadQuerier, stdout, s } else { w(" This assigns the bead to \"" + a.QualifiedName() + "\".") } + // A graph.v2 formula attach routes more than the work bead: the + // cooked workflow root is also routed to the same agent. Without + // this line the preview shows only the plain-routing effect, so a + // reader cannot anticipate the second routed bead. Legacy (non- + // graph.v2) attach deliberately leaves the wisp root unrouted -- + // see the design-intent comment on the finalize() call in + // slingFormula (internal/sling/sling_core.go, citing #2848 and + // TestOnFormulaAttachesAndRoutes) -- so this must not fire there. + if dryRunFormulaAttachIsGraphV2(opts, deps, a) { + w(" A wisp/workflow root is also cooked and routed to the agent.") + } } w("") } @@ -1810,6 +1822,28 @@ func dryRunSingle(opts slingOpts, deps slingDeps, querier BeadQuerier, stdout, s return 0 } +// dryRunFormulaAttachIsGraphV2 reports whether the formula this sling would +// attach (an explicit --on, or the target's default_sling_formula) is a +// graph.v2 formula. Resolution failures (unknown formula, parse error) report +// false rather than surfacing an error here -- a dry-run preview must not +// fail on a formula-name typo the live attach path will report clearly on +// its own, and understating the preview is the safe direction: it never +// claims a second routed bead that legacy attach will not create. +func dryRunFormulaAttachIsGraphV2(opts slingOpts, deps slingDeps, a config.Agent) bool { + formulaName := opts.OnFormula + if formulaName == "" { + if opts.NoFormula { + return false + } + formulaName = a.EffectiveDefaultSlingFormula() + } + if formulaName == "" { + return false + } + isGraph, _, err := graphv2.IsGraphV2Formula(formulaName, sling.SlingFormulaSearchPaths(deps, a)) + return err == nil && isGraph +} + // dryRunBatch prints a step-by-step preview of what gc sling would do for a // convoy without executing any side effects. func dryRunBatch(opts slingOpts, deps slingDeps, stdout, _ io.Writer, diff --git a/cmd/gc/cmd_sling_test.go b/cmd/gc/cmd_sling_test.go index 6f47884c46..f4879fbdd9 100644 --- a/cmd/gc/cmd_sling_test.go +++ b/cmd/gc/cmd_sling_test.go @@ -6384,6 +6384,73 @@ func TestDryRunOnFormula(t *testing.T) { if !strings.Contains(out, "bd update 'BL-42' --set-metadata gc.routed_to=mayor") { t.Errorf("stdout missing route command: %s", out) } + // code-review (sharedTestFormulaDir) is version=1, not graph.v2: legacy + // attach deliberately leaves the wisp root unrouted (see the + // design-intent comment on the finalize() call in slingFormula, + // internal/sling/sling_core.go, citing #2848 and + // TestOnFormulaAttachesAndRoutes), so the preview must not claim a + // second routed bead here. See TestDryRunOnFormulaGraphV2 for the + // graph.v2 case where the line is expected. + if strings.Contains(out, "A wisp/workflow root is also cooked and routed to the agent.") { + t.Errorf("stdout has wisp-root disclosure for a legacy (non-graph.v2) formula attach: %s", out) + } + if len(runner.calls) != 0 { + t.Errorf("got %d runner calls, want 0: %v", len(runner.calls), runner.calls) + } +} + +// writeGraphV2FormulaForDryRunTest writes a minimal graph.v2-contract +// formula file, mirroring internal/sling's writeNamedGraphV2ConvoyFormula +// (unexported there, so duplicated here rather than reused across packages). +func writeGraphV2FormulaForDryRunTest(t *testing.T, dir, name string) { + t.Helper() + content := fmt.Sprintf(` +formula = %q +version = 2 +contract = "graph.v2" + +[[steps]] +id = "step" +title = "Do work" +`, name) + if err := os.WriteFile(filepath.Join(dir, name+".formula.toml"), []byte(content), 0o644); err != nil { + t.Fatal(err) + } +} + +func TestDryRunOnFormulaGraphV2(t *testing.T) { + formulaDir := t.TempDir() + writeGraphV2FormulaForDryRunTest(t, formulaDir, "graph-work") + + runner := newFakeRunner() + sp := runtime.NewFake() + cfg := &config.City{ + Workspace: config.Workspace{Name: "test-city"}, + Daemon: config.DaemonConfig{FormulaV2: boolPtr(true)}, + FormulaLayers: config.FormulaLayers{City: []string{formulaDir}}, + } + a := config.Agent{Name: "mayor", MaxActiveSessions: intPtr(1)} + q := newFakeChildQuerier() + q.beadsByID["BL-42"] = beads.Bead{ID: "BL-42", Type: "task", Status: "open"} + q.childrenOf["BL-42"] = []beads.Bead{} // no molecule children + + deps, stdout, stderr := testDeps(cfg, sp, runner.run) + deps.Store = seededStore("BL-42") + opts := testOpts(a, "BL-42") + opts.OnFormula = "graph-work" + opts.DryRun = true + code := doSling(opts, deps, q, stdout, stderr) + + if code != 0 { + t.Fatalf("dry-run returned %d, want 0; stderr: %s", code, stderr.String()) + } + out := stdout.String() + if !strings.Contains(out, "Attach formula:") { + t.Errorf("stdout missing attach section: %s", out) + } + if !strings.Contains(out, "A wisp/workflow root is also cooked and routed to the agent.") { + t.Errorf("stdout missing wisp-root disclosure for a graph.v2 formula attach: %s", out) + } if len(runner.calls) != 0 { t.Errorf("got %d runner calls, want 0: %v", len(runner.calls), runner.calls) } diff --git a/cmd/gc/cmd_start.go b/cmd/gc/cmd_start.go index e3af84b97a..88fe657c94 100644 --- a/cmd/gc/cmd_start.go +++ b/cmd/gc/cmd_start.go @@ -1238,7 +1238,7 @@ func stageHookFiles(copyFiles []runtime.CopyEntry, cityPath, workDir string, hoo if _, err := os.Stat(abs); err == nil { copyFiles = append(copyFiles, runtime.CopyEntry{ Src: abs, RelDst: path.Join(relWorkDir, rel), - Probed: true, ContentHash: runtime.HashPathContent(abs), + Probed: true, ContentHash: runtime.HashHookSettingsContent(abs, rel), }) } } diff --git a/cmd/gc/cmd_supervisor.go b/cmd/gc/cmd_supervisor.go index fffe23a5f2..8f6ecf635a 100644 --- a/cmd/gc/cmd_supervisor.go +++ b/cmd/gc/cmd_supervisor.go @@ -1647,6 +1647,44 @@ type initFailRecord struct { const staleCityDirAbsentThreshold = 3 +// structuralInitFailureBackoff is the retry interval for init failures +// classified as structural (see isStructuralInitFailureMessage) -- far +// longer than the transient-failure ceiling, since retrying sooner cannot +// help: the failure requires an out-of-band fix no in-city action can +// trigger (#4484). +const structuralInitFailureBackoff = time.Hour + +// isStructuralInitFailureMessage reports whether msg indicates an init +// failure that no amount of retrying -- or editing city.toml -- can ever +// resolve, e.g. a bd schema-version gate ("database is at vN, binary +// knows up to vM"), which requires an out-of-band bd binary upgrade. +// Mirrors runtime.IsSessionGone's message-substring classification style +// for external-subprocess errors with no typed sentinel available. +func isStructuralInitFailureMessage(msg string) bool { + return strings.Contains(msg, "schema version mismatch") +} + +// initFailureBackoffDelay computes the retry backoff for the count-th +// consecutive init failure. Transient failures use capped exponential +// backoff (10s doubling to a 5-minute ceiling, unchanged from before +// #4484); structural failures (see isStructuralInitFailureMessage) back +// off to structuralInitFailureBackoff immediately, since the standard +// escalation cannot help a failure retrying will never resolve. +func initFailureBackoffDelay(count int, msg string) time.Duration { + if isStructuralInitFailureMessage(msg) { + return structuralInitFailureBackoff + } + exp := count - 1 + if exp > 5 { + exp = 5 + } + delay := time.Duration(10< 5*time.Minute { + delay = 5 * time.Minute + } + return delay +} + // reconcileCities compares the registry against running cities and // starts/stops as needed. All state access goes through the cityRegistry. func reconcileCities( @@ -1913,18 +1951,15 @@ func reconcileCities( } ifrec.count++ ifrec.dirAbsent = 0 - exp := ifrec.count - 1 - if exp > 5 { - exp = 5 - } - delay := time.Duration(10< 5*time.Minute { - delay = 5 * time.Minute - } + delay := initFailureBackoffDelay(ifrec.count, msg) ifrec.backoff = time.Now().Add(delay) ifrec.configMod = configMod ifrec.lastError = msg - fmt.Fprintf(stderr, "gc supervisor: city '%s': init failure #%d, next retry in %s\n", cityName, ifrec.count, delay) //nolint:errcheck + if isStructuralInitFailureMessage(msg) { + fmt.Fprintf(stderr, "gc supervisor: city '%s': STRUCTURAL init failure (retrying cannot resolve this — needs an out-of-band fix), next check in %s\n", cityName, delay) //nolint:errcheck + } else { + fmt.Fprintf(stderr, "gc supervisor: city '%s': init failure #%d, next retry in %s\n", cityName, ifrec.count, delay) //nolint:errcheck + } }) } diff --git a/cmd/gc/cmd_supervisor_city_test.go b/cmd/gc/cmd_supervisor_city_test.go index c3d0f97452..a75a7f3f83 100644 --- a/cmd/gc/cmd_supervisor_city_test.go +++ b/cmd/gc/cmd_supervisor_city_test.go @@ -2911,3 +2911,50 @@ func TestNormalizeRegisteredCityPathResolvesSymlinks(t *testing.T) { t.Fatalf("normalizeRegisteredCityPath(%q) = %q, want %q", link, got, want) } } + +// TestIsStructuralInitFailureMessageDetectsSchemaVersionGate pins #4484: +// a bd schema-version gate ("database is at vN, binary knows up to vM") +// is a structural failure -- no retry, and no city.toml edit, can ever +// resolve it, since the fix is an out-of-band bd binary upgrade. Ordinary +// transient failures (a lock held, a socket busy) must not match. +func TestIsStructuralInitFailureMessageDetectsSchemaVersionGate(t *testing.T) { + structural := `init: beads lifecycle: init city beads: bd list: exit status 1: { "error": "schema version mismatch: database is at v53, binary knows up to v49 (4 migrations ahead)", "schema_skew": {"current_version":53,"delta":4,"required_version":49}, "schema_version": 1 }` + if !isStructuralInitFailureMessage(structural) { + t.Errorf("isStructuralInitFailureMessage(%q) = false, want true", structural) + } + + transient := "controller lock: lock held by another process" + if isStructuralInitFailureMessage(transient) { + t.Errorf("isStructuralInitFailureMessage(%q) = true, want false", transient) + } +} + +// TestInitFailureBackoffDelayEscalatesStructuralFailuresBeyondTransientCeiling +// pins #4484: gc supervisor previously applied the same capped exponential +// backoff (10s doubling to a 5-minute ceiling) to every init failure, +// including a structural schema-version gate that retrying can never +// resolve -- observed live retrying at the 5-minute ceiling for ~6 days +// straight. A structural failure must back off to a far longer interval +// immediately (not escalate gradually like a transient one), while +// ordinary transient failures keep their existing behavior unchanged. +func TestInitFailureBackoffDelayEscalatesStructuralFailuresBeyondTransientCeiling(t *testing.T) { + structuralMsg := `init: bd list: exit status 1: schema version mismatch: database is at v53, binary knows up to v49 (4 migrations ahead)` + + if got := initFailureBackoffDelay(1, structuralMsg); got != structuralInitFailureBackoff { + t.Errorf("initFailureBackoffDelay(1, structural) = %s, want %s (should not use the transient ceiling even on the first failure)", got, structuralInitFailureBackoff) + } + if got := initFailureBackoffDelay(27, structuralMsg); got != structuralInitFailureBackoff { + t.Errorf("initFailureBackoffDelay(27, structural) = %s, want %s", got, structuralInitFailureBackoff) + } + + transientMsg := "controller lock: lock held by another process" + if got, want := initFailureBackoffDelay(1, transientMsg), 10*time.Second; got != want { + t.Errorf("initFailureBackoffDelay(1, transient) = %s, want %s (unchanged transient behavior)", got, want) + } + if got, want := initFailureBackoffDelay(7, transientMsg), 5*time.Minute; got != want { + t.Errorf("initFailureBackoffDelay(7, transient) = %s, want %s (transient ceiling unchanged)", got, want) + } + if got := initFailureBackoffDelay(7, transientMsg); got == structuralInitFailureBackoff { + t.Errorf("initFailureBackoffDelay(7, transient) = %s, must not equal the structural backoff by coincidence", got) + } +} diff --git a/cmd/gc/cmd_version.go b/cmd/gc/cmd_version.go index 95376d0f43..ed25175772 100644 --- a/cmd/gc/cmd_version.go +++ b/cmd/gc/cmd_version.go @@ -27,9 +27,9 @@ var ( buildBase = "" beadsVersion = "unknown" goPseudoVersionSuffixRes = []*regexp.Regexp{ - regexp.MustCompile(`^(.*)\.0\.\d{14}-[0-9a-f]{12,}$`), - regexp.MustCompile(`^(.*)-0\.\d{14}-[0-9a-f]{12,}$`), - regexp.MustCompile(`^(.*)-\d{14}-[0-9a-f]{12,}$`), + regexp.MustCompile(`^(.*)\.0\.\d{14}-[0-9a-f]{12,}(?:\+\S*)?$`), + regexp.MustCompile(`^(.*)-0\.\d{14}-[0-9a-f]{12,}(?:\+\S*)?$`), + regexp.MustCompile(`^(.*)-\d{14}-[0-9a-f]{12,}(?:\+\S*)?$`), } ) @@ -104,9 +104,9 @@ func normalizeVersion(v string) string { if v == "" || v == "(devel)" { return "dev" } - if i := strings.IndexByte(v, '+'); i >= 0 { - v = v[:i] - } + // Strip +incompatible only (Go v2+ module compat sentinel for repos without a /vN import path). + // Preserve all other build metadata (e.g. +ra.1 marks a locally-patched release). + v = strings.TrimSuffix(v, "+incompatible") for _, re := range goPseudoVersionSuffixRes { if m := re.FindStringSubmatch(v); len(m) == 2 { v = m[1] diff --git a/cmd/gc/cmd_version_test.go b/cmd/gc/cmd_version_test.go index 82440b35e1..695946a31e 100644 --- a/cmd/gc/cmd_version_test.go +++ b/cmd/gc/cmd_version_test.go @@ -16,6 +16,13 @@ func TestNormalizeVersion(t *testing.T) { {in: "v0.0.0-20260317225312-41a12e4914cb", want: "dev"}, {in: "(devel)", want: "dev"}, {in: "", want: "dev"}, + // SemVer build metadata must be preserved. + {in: "1.3.5+ra.1", want: "1.3.5+ra.1"}, + {in: "1.3.5", want: "1.3.5"}, + // Pseudo-version with a newer timestamp still collapses. + {in: "v0.0.0-20260719191849-4c2927134266", want: "dev"}, + // +incompatible is the one Go-specific suffix we strip. + {in: "1.2.3+incompatible", want: "1.2.3"}, } for _, tt := range tests { if got := normalizeVersion(tt.in); got != tt.want { diff --git a/cmd/gc/cmd_wait_test.go b/cmd/gc/cmd_wait_test.go index 3f816d677e..d7428c6c82 100644 --- a/cmd/gc/cmd_wait_test.go +++ b/cmd/gc/cmd_wait_test.go @@ -26,6 +26,7 @@ import ( "github.com/gastownhall/gascity/internal/overlay" "github.com/gastownhall/gascity/internal/runtime" sessionpkg "github.com/gastownhall/gascity/internal/session" + "golang.org/x/mod/semver" ) type waitErrorStore struct { @@ -702,7 +703,7 @@ func pinnedBeadsModuleVersion() (string, error) { return "", fmt.Errorf("github.com/steveyegge/beads not found in build info deps") } -// TestBuildPinnedBDBinaryForTestsMatchesGoModVersion locks in the fix for +// TestBuildPinnedBDBinaryForTestsUsesGoModSource locks in the fix for // ga-r9cvmi: a bd binary resolved by searching PATH/home-dir locations (the // old waitTestRealBDPath behavior, still used elsewhere via // findPreferredBinary) carries no guarantee of matching the schema/migration @@ -761,7 +762,7 @@ func depsEnvBDPins(t *testing.T) (bdVersion, sourceRef string) { return bdVersion, sourceRef } -func TestBuildPinnedBDBinaryForTestsMatchesGoModVersion(t *testing.T) { +func TestBuildPinnedBDBinaryForTestsUsesGoModSource(t *testing.T) { // Load-bearing for the census even though waitTestRealBDPath calls it // again: this is the cmd/gc+untagged slow_process_gate call site the // 57 -> 58 bump accounts for across census.go, test-resources.toml, and @@ -805,9 +806,39 @@ func TestBuildPinnedBDBinaryForTestsMatchesGoModVersion(t *testing.T) { if err != nil { t.Fatalf("%s version: %v\n%s", bdPath, err, out) } - if !strings.Contains(string(out), wantVersion) { - t.Fatalf("%s version output %q does not reflect pinned beads module version %q", bdPath, out, pinned) + versionLine := "" + for _, line := range strings.Split(string(out), "\n") { + if strings.HasPrefix(line, "bd version ") { + versionLine = line + break + } + } + fields := strings.Fields(versionLine) + if len(fields) < 3 || !semver.IsValid("v"+fields[2]) { + t.Fatalf("%s version output %q does not report a declared Beads release version", bdPath, out) + } + if fields[2] != wantVersion { + t.Fatalf("%s reports version %q, want %q — the version deps.env says the pinned commit declares (for a pseudo-version pin) or the pinned release itself", bdPath, fields[2], wantVersion) + } + metadata, err := exec.Command("go", "version", "-m", bdPath).CombinedOutput() + if err != nil { + t.Fatalf("go version -m %s: %v\n%s", bdPath, err, metadata) + } + foundPinnedModule := false + for _, line := range strings.Split(string(metadata), "\n") { + fields := strings.Fields(line) + if len(fields) >= 3 && fields[0] == "mod" && fields[1] == "github.com/steveyegge/beads" && fields[2] == pinned { + foundPinnedModule = true + break + } + } + if !foundPinnedModule { + t.Fatalf("%s build metadata %q does not retain pinned Beads module version %q", bdPath, metadata, pinned) } + // `bd version` reports the release variable declared by Beads source + // (currently 1.1.0), not the Go module pseudo-version used to fetch that + // source. The exact source guarantee is therefore checked through the + // compiled binary's module metadata above. } func TestLoadWaitBeadsByLabelUsesBoundedLookup(t *testing.T) { diff --git a/cmd/gc/codex_hooks_dual_write_test.go b/cmd/gc/codex_hooks_dual_write_test.go new file mode 100644 index 0000000000..282c1a9a44 --- /dev/null +++ b/cmd/gc/codex_hooks_dual_write_test.go @@ -0,0 +1,325 @@ +package main + +import ( + "encoding/json" + "io" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/gastownhall/gascity/internal/bootstrap/packs/core" + "github.com/gastownhall/gascity/internal/config" + "github.com/gastownhall/gascity/internal/fsys" + "github.com/gastownhall/gascity/internal/hooks" + "github.com/gastownhall/gascity/internal/runtime" +) + +// seedCodexOverlay writes the real embedded core codex hooks overlay into a +// temp overlay source dir (per-provider/codex/.codex/hooks.json) so staging and +// hooks.Install operate on the same bytes the reconciler uses in production. +func seedCodexOverlay(t *testing.T) string { + t.Helper() + data, err := core.PackFS.ReadFile("overlay/per-provider/codex/.codex/hooks.json") + if err != nil { + t.Fatalf("read embedded codex hooks overlay: %v", err) + } + src := t.TempDir() + dstDir := filepath.Join(src, "per-provider", "codex", ".codex") + if err := os.MkdirAll(dstDir, 0o755); err != nil { + t.Fatalf("mkdir codex overlay: %v", err) + } + if err := os.WriteFile(filepath.Join(dstDir, "hooks.json"), data, 0o644); err != nil { + t.Fatalf("write codex overlay: %v", err) + } + return src +} + +// codexSessionStartMatchers returns the "matcher" value of every SessionStart +// hook entry in a codex hooks.json document. +func codexSessionStartMatchers(t *testing.T, path string) []string { + t.Helper() + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read %s: %v", path, err) + } + var doc struct { + Hooks map[string][]struct { + Matcher string `json:"matcher"` + } `json:"hooks"` + } + if err := json.Unmarshal(data, &doc); err != nil { + t.Fatalf("unmarshal %s: %v", path, err) + } + matchers := make([]string, 0, len(doc.Hooks["SessionStart"])) + for _, e := range doc.Hooks["SessionStart"] { + matchers = append(matchers, e.Matcher) + } + return matchers +} + +// driftedCodexHooks is a live hybrid captured from a drifted Codex +// agent (see #3866 / #3808): the reconciler's bound `matcher:"startup"` +// SessionStart entry coexisting with the overlay's pre-#3866 unbound +// `matcher:""` `gc prime` entry, plus the unbound PreCompact/UserPromptSubmit +// entries. `gc doctor` flags this as codex-hooks-drift ("needs upgrade") +// forever because the two writers keep re-seeding disagreeing matchers. +const driftedCodexHooks = `{ + "hooks": { + "PreCompact": [ + { + "hooks": [ + { + "command": "export PATH=\"$HOME/go/bin:$HOME/.local/bin:$PATH\" && gc handoff --auto --hook-format codex \"context cycle\"", + "type": "command" + } + ], + "matcher": "" + } + ], + "SessionStart": [ + { + "hooks": [ + { + "command": "export PATH=\"$HOME/go/bin:$HOME/.local/bin:$PATH\" && GC_MANAGED_SESSION_HOOK=1 GC_HOOK_EVENT_NAME=SessionStart gc --city '__CITY__' prime --hook --hook-format codex", + "type": "command" + } + ], + "matcher": "startup" + }, + { + "hooks": [ + { + "command": "export PATH=\"$HOME/go/bin:$HOME/.local/bin:$PATH\" && GC_MANAGED_SESSION_HOOK=1 GC_HOOK_EVENT_NAME=SessionStart gc prime --hook --hook-format codex", + "type": "command" + } + ], + "matcher": "" + } + ], + "UserPromptSubmit": [ + { + "hooks": [ + { + "command": "export PATH=\"$HOME/go/bin:$HOME/.local/bin:$PATH\" && gc hook run --timeout 15s --timeout-exit-code 0 -- nudge drain --inject --hook-format codex", + "type": "command" + }, + { + "command": "export PATH=\"$HOME/go/bin:$HOME/.local/bin:$PATH\" && gc hook run --timeout 15s --timeout-exit-code 0 -- mail check --inject --hook-format codex", + "type": "command" + } + ], + "matcher": "" + } + ] + } +}` + +// seedDriftedHybrid writes the live hybrid fixture into workDir/.codex/hooks.json +// with its bound SessionStart entry pinned to cityDir, reproducing the drifted +// starting state a reconcile tick must converge. +func seedDriftedHybrid(t *testing.T, cityDir, workDir string) { + t.Helper() + dir := filepath.Join(workDir, ".codex") + if err := os.MkdirAll(dir, 0o755); err != nil { + t.Fatalf("mkdir .codex: %v", err) + } + body := strings.ReplaceAll(driftedCodexHooks, "__CITY__", cityDir) + if err := os.WriteFile(filepath.Join(dir, "hooks.json"), []byte(body), 0o644); err != nil { + t.Fatalf("seed drifted hybrid: %v", err) + } +} + +// stageCodex runs the staging half of the build_desired_state home-dir tick. +// skipMergeable selects the fixed (skip) vs legacy (no-skip) path. +func stageCodex(t *testing.T, overlaySrc, workDir string, skipMergeable bool) { + t.Helper() + var err error + if skipMergeable { + err = runtime.StageProviderOverlayDirSkippingMergeable(overlaySrc, workDir, []string{"codex"}, nil) + } else { + err = runtime.StageProviderOverlayDir(overlaySrc, workDir, []string{"codex"}, nil) + } + if err != nil { + t.Fatalf("stage codex overlay (skip=%v): %v", skipMergeable, err) + } +} + +// installCodex runs the hooks.Install half of the tick on the same workDir. +func installCodex(t *testing.T, cityDir, workDir string) { + t.Helper() + if err := hooks.Install(fsys.OSFS{}, cityDir, workDir, []string{"codex"}); err != nil { + t.Fatalf("hooks.Install codex: %v", err) + } +} + +// TestCodexHooksConvergeWithSkipStaging is the dual-writer reproduce+fix test. +// +// The build_desired_state home-dir tick is staging followed by hooks.Install on +// the SAME dir. Starting from the live drifted hybrid, hooks.Install converges +// the document to a single bound SessionStart entry — but the LEGACY staging +// path re-merges the overlay's unbound `matcher:""` entry back in on the very +// next tick, so the on-disk document a fresh `gc doctor`/session-start reads +// right after staging is perpetually drifted ([startup, ""]). That oscillation +// is why codex-hooks-drift never clears without --fix. +// +// The observation point that matters is therefore the post-staging state. With +// the skip path staging no longer touches the mergeable file, so the converged +// [startup] document is stable at every point in the cycle. +func TestCodexHooksConvergeWithSkipStaging(t *testing.T) { + overlaySrc := seedCodexOverlay(t) + cityDir := t.TempDir() + + assertSingleBound := func(t *testing.T, workDir, when string) { + t.Helper() + hooksPath := filepath.Join(workDir, ".codex", "hooks.json") + matchers := codexSessionStartMatchers(t, hooksPath) + data, _ := os.ReadFile(hooksPath) + if len(matchers) != 1 || matchers[0] != "startup" { + t.Fatalf("%s: SessionStart matchers = %v, want exactly [startup] (converged, bound)\n%s", when, matchers, data) + } + if !strings.Contains(string(data), "--city") { + t.Fatalf("%s: converged SessionStart not bound to city root (missing --city)\n%s", when, data) + } + if strings.Contains(string(data), "gc prime --hook") { + t.Fatalf("%s: unbound `gc prime` SessionStart entry still present (drift)\n%s", when, data) + } + } + + // assertManagedEventsIntact guards the dual-writer regression surface. Because + // the home-dir staging path now skips the ENTIRE .codex/hooks.json, hooks.Install + // must remain the sole, COMPLETE writer: the converged document has to keep the + // managed PreCompact (context-cycle handoff) and UserPromptSubmit (mail check + + // nudge drain) hooks, not just SessionStart. A future change to the installer's + // fresh-write/upgrade path that dropped either event would otherwise slip past + // assertSingleBound, which only inspects SessionStart. + assertManagedEventsIntact := func(t *testing.T, workDir, when string) { + t.Helper() + hooksPath := filepath.Join(workDir, ".codex", "hooks.json") + data, err := os.ReadFile(hooksPath) + if err != nil { + t.Fatalf("%s: read %s: %v", when, hooksPath, err) + } + var doc struct { + Hooks map[string][]struct { + Hooks []struct { + Command string `json:"command"` + } `json:"hooks"` + } `json:"hooks"` + } + if err := json.Unmarshal(data, &doc); err != nil { + t.Fatalf("%s: unmarshal %s: %v", when, hooksPath, err) + } + commandsFor := func(event string) string { + var b strings.Builder + for _, e := range doc.Hooks[event] { + for _, h := range e.Hooks { + b.WriteString(h.Command) + b.WriteByte('\n') + } + } + return b.String() + } + if !strings.Contains(commandsFor("PreCompact"), "handoff") { + t.Fatalf("%s: converged doc dropped the managed PreCompact handoff hook\n%s", when, data) + } + prompt := commandsFor("UserPromptSubmit") + if !strings.Contains(prompt, "mail check") || !strings.Contains(prompt, "nudge drain") { + t.Fatalf("%s: converged doc dropped managed UserPromptSubmit hooks (want mail check + nudge drain)\n%s", when, data) + } + } + + // Fixed path: seed the drifted hybrid, then run stage → install → stage. + // The file must be converged and bound at EVERY observation point, including + // the post-staging states where the legacy path re-drifts. + fixedWork := t.TempDir() + seedDriftedHybrid(t, cityDir, fixedWork) + stageCodex(t, overlaySrc, fixedWork, true) + installCodex(t, cityDir, fixedWork) + assertSingleBound(t, fixedWork, "fixed after install") + assertManagedEventsIntact(t, fixedWork, "fixed after install") + stageCodex(t, overlaySrc, fixedWork, true) + assertSingleBound(t, fixedWork, "fixed after re-stage") + assertManagedEventsIntact(t, fixedWork, "fixed after re-stage") + + // Legacy path: identical sequence with non-skip staging. After the trailing + // staging step the unbound overlay entry is merged back in, re-creating the + // hybrid a reconcile tick can never settle. This is the drift the fix removes. + legacyWork := t.TempDir() + seedDriftedHybrid(t, cityDir, legacyWork) + stageCodex(t, overlaySrc, legacyWork, false) + installCodex(t, cityDir, legacyWork) + stageCodex(t, overlaySrc, legacyWork, false) + legacyMatchers := codexSessionStartMatchers(t, filepath.Join(legacyWork, ".codex", "hooks.json")) + if len(legacyMatchers) <= 1 { + t.Fatalf("expected legacy non-skip staging to re-drift the hybrid (>1 SessionStart entry) after re-staging, got %v; if this no longer reproduces, the dual-write may have been fixed elsewhere — re-verify the skip is still required", legacyMatchers) + } +} + +// TestMaterializeProviderOverlays_SkipsMergeableCodexHook guards the production +// caller wiring: materializeProviderOverlaysBeforeFingerprint (the +// staging-only half of prepareTemplateResolution) must skip the reconciler-owned +// mergeable .codex/hooks.json while still staging non-mergeable overlay +// siblings. This is the observation point where skip vs non-skip staging +// diverge — the trailing hooks.Install converges either way, so only the +// staging-only state distinguishes a reverted caller wiring. +func TestMaterializeProviderOverlays_SkipsMergeableCodexHook(t *testing.T) { + cityDir := t.TempDir() + rigDir := filepath.Join(cityDir, "myrig") + if err := os.MkdirAll(rigDir, 0o755); err != nil { + t.Fatalf("MkdirAll(rig): %v", err) + } + overlayDir := filepath.Join(cityDir, "packs", "myrig", "overlay") + codexOverlay := filepath.Join(overlayDir, "per-provider", "codex", ".codex") + if err := os.MkdirAll(codexOverlay, 0o755); err != nil { + t.Fatalf("MkdirAll(overlay): %v", err) + } + if err := os.WriteFile(filepath.Join(codexOverlay, "hooks.json"), []byte(`{"hooks":{"SessionStart":[]}}`), 0o644); err != nil { + t.Fatalf("write codex hooks overlay: %v", err) + } + sibling := filepath.Join(overlayDir, "per-provider", "codex", "AGENTS.codex.md") + if err := os.WriteFile(sibling, []byte("codex"), 0o644); err != nil { + t.Fatalf("write codex sibling overlay: %v", err) + } + + codexBase := "builtin:codex" + cfg := &config.City{ + Workspace: config.Workspace{Name: "test-city"}, + Agents: []config.Agent{{ + Name: "polecat", + Provider: "codex", + Scope: "rig", + Dir: "myrig", + }}, + Providers: map[string]config.ProviderSpec{ + // Explicit command + resume_command so resolution does not depend on + // a real codex binary on PATH; base still yields the codex family. + "codex": {Base: &codexBase, Command: "/bin/echo", ResumeCommand: "/bin/echo resume {{.SessionKey}}"}, + }, + Rigs: []config.Rig{{Name: "myrig", Path: rigDir}}, + RigOverlayDirs: map[string][]string{"myrig": {overlayDir}}, + } + + bp := newAgentBuildParams("test-city", cityDir, cfg, runtime.NewFake(), time.Now().UTC(), nil, io.Discard) + cfgAgent := &cfg.Agents[0] + resolved, err := config.ResolveProvider(cfgAgent, bp.workspace, bp.providers, bp.lookPath) + if err != nil { + t.Fatalf("ResolveProvider: %v", err) + } + workDir, err := resolveConfiguredWorkDir(bp.cityPath, bp.cityName, "myrig/polecat", cfgAgent, bp.rigs) + if err != nil { + t.Fatalf("resolveConfiguredWorkDir: %v", err) + } + rigName := sessionSetupContextForAgent(bp.cityPath, bp.cityName, "myrig/polecat", cfgAgent, bp.rigs).Rig + + // Staging only — hooks.Install is a separate step in prepareTemplateResolution. + materializeProviderOverlaysBeforeFingerprint(bp, cfgAgent, resolved, "myrig/polecat", rigName, workDir, io.Discard) + + if _, err := os.Stat(filepath.Join(workDir, ".codex", "hooks.json")); !os.IsNotExist(err) { + t.Fatalf("build_desired_state staging wrote reconciler-owned .codex/hooks.json (err=%v); caller must use the skip variant so hooks.Install is sole writer", err) + } + if _, err := os.Stat(filepath.Join(workDir, "AGENTS.codex.md")); err != nil { + t.Fatalf("non-mergeable codex overlay sibling not staged: %v", err) + } +} diff --git a/cmd/gc/compute_awake_bridge.go b/cmd/gc/compute_awake_bridge.go index 59464b96e3..3c181f4f37 100644 --- a/cmd/gc/compute_awake_bridge.go +++ b/cmd/gc/compute_awake_bridge.go @@ -89,8 +89,15 @@ func buildAwakeInputFromReconciler( a := strings.TrimSpace(wb.Assignee) if a != "" && (wb.Status == "open" || wb.Status == "in_progress") { ready := i < len(readyAssignedFlags) && readyAssignedFlags[i] + // Blocked mirrors #4726's hook-side fix on the wake side: an + // in_progress bead's IsBlocked projection (bd's denormalized + // ready-work verdict, which folds in open blocking dependencies + // and gates) tells WakeWork not to fire on a bead the hook would + // not dispatch. Only meaningful for in_progress -- open work's + // blocker state is already folded into `ready` above. + blocked := wb.Status == "in_progress" && wb.IsBlocked != nil && *wb.IsBlocked input.WorkBeads = append(input.WorkBeads, AwakeWorkBead{ - ID: wb.ID, Assignee: a, Status: wb.Status, Ready: ready, + ID: wb.ID, Assignee: a, Status: wb.Status, Ready: ready, Blocked: blocked, }) } } diff --git a/cmd/gc/compute_awake_bridge_test.go b/cmd/gc/compute_awake_bridge_test.go index 957e82697b..e15d0f7803 100644 --- a/cmd/gc/compute_awake_bridge_test.go +++ b/cmd/gc/compute_awake_bridge_test.go @@ -413,6 +413,105 @@ func TestBuildAwakeInputFromReconciler_InProgressAssignedBeadStillWakes(t *testi } } +// TestBuildAwakeInputFromReconciler_BlockedInProgressBeadDoesNotWake pins the +// AwakeWorkBead.Blocked population expression, including its nil guard. Blocked +// is derived only for in_progress work — open work's blocker state is already +// folded into Ready — and a nil IsBlocked (what minimum-supported bd v1.0.4 +// produces, and what any store that omits the projection produces) must fail +// open to not-blocked. That fail-open default is what makes the wake-side +// narrowing unable to over-suppress: absent an explicit blocked verdict, the +// session keeps waking exactly as it did before. +func TestBuildAwakeInputFromReconciler_BlockedInProgressBeadDoesNotWake(t *testing.T) { + tests := []struct { + name string + status string + isBlocked *bool + wantBlocked bool + wantWake bool + }{ + { + name: "in_progress with is_blocked=true is blocked and does not wake", + status: "in_progress", + isBlocked: boolPtr(true), + wantBlocked: true, + wantWake: false, + }, + { + name: "in_progress with nil is_blocked fails open and still wakes", + status: "in_progress", + isBlocked: nil, + wantBlocked: false, + wantWake: true, + }, + { + // Open work routes through Ready, so its blocker state must not be + // double-counted into Blocked. With readyAssignedFlags omitted the + // bead is not ready, so it does not wake — via Ready, not Blocked. + name: "open with is_blocked=true is not marked blocked", + status: "open", + isBlocked: boolPtr(true), + wantBlocked: false, + wantWake: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + now := time.Now().UTC() + cfg := &config.City{Agents: []config.Agent{{Name: "gc.run-operator"}}} + sessionBead := beads.Bead{ + ID: "mc-session-1", + Status: "open", + Type: "session", + Metadata: map[string]string{ + "state": "active", + "session_name": "gc__run-operator-mc-1", + "template": "gc.run-operator", + }, + } + work := beads.Bead{ + ID: "ga-active", + Status: tt.status, + Assignee: "gc__run-operator-mc-1", + IsBlocked: tt.isBlocked, + } + + input := buildAwakeInputFromReconciler( + cfg, + "", + []session.Info{sessiontest.SeedBead(t, sessionBead)}, + nil, + nil, + nil, + nil, + nil, + []beads.Bead{work}, + nil, // readyAssignedFlags omitted entirely + nil, + runtime.NewFake(), + now, + ) + + if len(input.WorkBeads) != 1 { + t.Fatalf("WorkBeads = %+v, want exactly one bead", input.WorkBeads) + } + if got := input.WorkBeads[0].Blocked; got != tt.wantBlocked { + t.Errorf("WorkBeads[0].Blocked = %v, want %v", got, tt.wantBlocked) + } + + decisions := ComputeAwakeSet(input) + got := decisions["gc__run-operator-mc-1"] + if tt.wantWake { + if !got.ShouldWake || got.Reason != "assigned-work" { + t.Fatalf("session should wake on assigned-work; got decision = %+v", got) + } + } else if got.ShouldWake { + t.Fatalf("session should stay asleep; got decision = %+v", got) + } + }) + } +} + // TestBuildAwakeInputFromReconciler_CrossStoreSameIDReadinessIsStoreScoped pins // the cross-store readiness fix: AssignedWorkBeads can carry the same bead ID // from independent city and rig stores. A ready city bead must NOT mark a diff --git a/cmd/gc/compute_awake_set.go b/cmd/gc/compute_awake_set.go index 3cf687b71f..7d7f26e1f9 100644 --- a/cmd/gc/compute_awake_set.go +++ b/cmd/gc/compute_awake_set.go @@ -85,6 +85,17 @@ type AwakeWorkBead struct { Assignee string Status string // "open", "in_progress" Ready bool // true for open work only after readiness/blocker filtering + // Blocked is true when an in_progress bead carries an open + // ready-blocking dependency or gate (bd's IsBlocked projection). It is + // meaningless for open work, whose blocker state is already folded into + // Ready. Zero value is false, so every existing in_progress caller that + // does not populate it keeps today's unconditional-wake behavior. + // + // Setting it is not purely suppressive: workBeadHasAwakeDemand also feeds + // countAssignedScaleSlots, so blocked in_progress work additionally + // releases the session's scale slot, which can wake a different session + // as scaled:demand. + Blocked bool } // AwakeDecision is the output for a single session. @@ -702,7 +713,7 @@ func sessionHasAssignedWork(workBeads []AwakeWorkBead, named []AwakeNamedSession func workBeadHasAwakeDemand(bead AwakeWorkBead) bool { switch bead.Status { case "in_progress": - return true + return !bead.Blocked case "open": return bead.Ready default: diff --git a/cmd/gc/compute_awake_set_test.go b/cmd/gc/compute_awake_set_test.go index a408e3f301..06b9e904f7 100644 --- a/cmd/gc/compute_awake_set_test.go +++ b/cmd/gc/compute_awake_set_test.go @@ -1321,6 +1321,54 @@ func TestRegression_PolecatWithInProgressWork_StaysAwake(t *testing.T) { assertAwake(t, result, "polecat-mc-p1") } +// TestRegression_PolecatWithBlockedInProgressWork_DoesNotWake covers the +// WakeWork/hook disagreement: an in_progress bead that carries an open +// ready-blocking dependency or gate is not dispatchable by the hook (see +// upstream #4726, which taught the hook's crash-recovery tier to skip it), +// but ComputeAwakeSet fired assigned-work demand from the bead's mere +// presence, regardless of blocked state. That mismatch re-wakes the session +// every reconcile tick while the hook returns no_work every cycle. +func TestRegression_PolecatWithBlockedInProgressWork_DoesNotWake(t *testing.T) { + result := ComputeAwakeSet(AwakeInput{ + Agents: []AwakeAgent{{QualifiedName: "hello-world/polecat"}}, + SessionBeads: []AwakeSessionBead{ + {ID: "mc-p1", SessionName: "polecat-mc-p1", Template: "hello-world/polecat", State: "asleep"}, + }, + WorkBeads: []AwakeWorkBead{{ID: "hw-1", Assignee: "mc-p1", Status: "in_progress", Blocked: true}}, + ScaleCheckCounts: map[string]int{"hello-world/polecat": 0}, + Now: now, + }) + assertAsleep(t, result, "polecat-mc-p1") +} + +// TestBlockedInProgressWorkDoesNotFillScaleSlot pins the second-order effect of +// the blocked-work narrowing: workBeadHasAwakeDemand also feeds +// countAssignedScaleSlots, so a session parked on blocked in_progress work no +// longer occupies a scale slot. This is intended, not incidental — a session +// that cannot progress should not hold a pool slot hostage — but it means the +// change is not purely suppressive: releasing the slot lets a *different* +// session wake as scaled:demand. +// +// mc-p1 is asleep holding blocked work, so it is not a scaled candidate itself +// (collectActiveBeads requires state=active) but is still counted by +// countAssignedScaleSlots. With scale_check=1, mc-p2 wakes only if mc-p1's +// blocked bead released the slot. +func TestBlockedInProgressWorkDoesNotFillScaleSlot(t *testing.T) { + result := ComputeAwakeSet(AwakeInput{ + Agents: []AwakeAgent{{QualifiedName: "hello-world/polecat"}}, + SessionBeads: []AwakeSessionBead{ + {ID: "mc-p1", SessionName: "polecat-mc-p1", Template: "hello-world/polecat", State: "asleep"}, + {ID: "mc-p2", SessionName: "polecat-mc-p2", Template: "hello-world/polecat", State: "active"}, + }, + WorkBeads: []AwakeWorkBead{{ID: "hw-1", Assignee: "mc-p1", Status: "in_progress", Blocked: true}}, + ScaleCheckCounts: map[string]int{"hello-world/polecat": 1}, + Now: now, + }) + assertAsleep(t, result, "polecat-mc-p1") + assertAwake(t, result, "polecat-mc-p2") + assertReason(t, result, "polecat-mc-p2", "scaled:demand") +} + func TestRegression_SessionWithOpenWorkByBeadID_StaysAwake(t *testing.T) { result := ComputeAwakeSet(AwakeInput{ Agents: []AwakeAgent{{QualifiedName: "hello-world/polecat"}}, diff --git a/cmd/gc/cross_store_pipeline_test.go b/cmd/gc/cross_store_pipeline_test.go index 86db8fa041..e7a7535b24 100644 --- a/cmd/gc/cross_store_pipeline_test.go +++ b/cmd/gc/cross_store_pipeline_test.go @@ -10,11 +10,11 @@ import ( ) // TestCrossStorePipeline_ReadThenClaim verifies the composition of the -// cross-store read half (firstStoreWithWork) and the write half +// cross-store read half (bestStoreWithWork) and the write half // (crossStoreClaimDir): a bead ID surfaced by federation from a rig store // must be correctly redirected to that same rig store by the claim path. // -// Uses the same injectable-runner approach as TestFirstStoreWithWork so no +// Uses the same injectable-runner approach as TestBestStoreWithWork so no // real Dolt or gc subprocess is needed. func TestCrossStorePipeline_ReadThenClaim(t *testing.T) { rigPath := t.TempDir() @@ -38,9 +38,9 @@ func TestCrossStorePipeline_ReadThenClaim(t *testing.T) { return `[]`, nil } - out, gotStore, err := firstStoreWithWork("fake-query", stores, stores[0], run) + out, gotStore, err := bestStoreWithWork("fake-query", stores, stores[0], run) if err != nil { - t.Fatalf("firstStoreWithWork: %v", err) + t.Fatalf("bestStoreWithWork: %v", err) } if filepath.Clean(gotStore.dir) != filepath.Clean(rigPath) { t.Fatalf("selected store = %q, want %q (rig store)", gotStore.dir, rigPath) diff --git a/cmd/gc/dispatch_control_ready_hold_label_test.go b/cmd/gc/dispatch_control_ready_hold_label_test.go index 38988db490..d3ef6f7341 100644 --- a/cmd/gc/dispatch_control_ready_hold_label_test.go +++ b/cmd/gc/dispatch_control_ready_hold_label_test.go @@ -1,6 +1,9 @@ package main import ( + "fmt" + "os" + "path/filepath" "testing" "time" @@ -62,3 +65,107 @@ func TestEvaluateControlReadyExcludesDispatchHoldLabels(t *testing.T) { t.Fatalf("evaluateControlReady ids = %v, want %v (hold-labeled routed bead must be excluded, including a bead carrying both hold labels at once)", beadIDs(got), want) } } + +// TestTryControlReadyFromCacheOrFallbackExcludesDispatchHoldLabelsFromCache is +// ga-5736js end-to-end on the cache path: a routed_to-matching bead carrying a +// beadmeta.DispatchHoldLabels value must not reach the control dispatcher's +// queue when the answer is served from CachedReady(). The filter-level tests +// above pin the rule; this one pins that the cache actually carries Labels far +// enough for the rule to fire. (End-to-end coverage originates from PR #4787.) +func TestTryControlReadyFromCacheOrFallbackExcludesDispatchHoldLabelsFromCache(t *testing.T) { + cityDir, store := setUpControlReadyFileStoreCity(t) + noBDOnPathForTest(t) + + target := "gascity/control-dispatcher" + routed, err := store.Create(beads.Bead{Metadata: map[string]string{beadmeta.RoutedToMetadataKey: target}}) + if err != nil { + t.Fatalf("create routed bead: %v", err) + } + heldMayor, err := store.Create(beads.Bead{ + Metadata: map[string]string{beadmeta.RoutedToMetadataKey: target}, + Labels: []string{beadmeta.HoldMayorLabel}, + }) + if err != nil { + t.Fatalf("create %s routed bead: %v", beadmeta.HoldMayorLabel, err) + } + heldExternal, err := store.Create(beads.Bead{ + Metadata: map[string]string{beadmeta.RoutedToMetadataKey: target}, + Labels: []string{beadmeta.HoldExternalLabel}, + }) + if err != nil { + t.Fatalf("create %s routed bead: %v", beadmeta.HoldExternalLabel, err) + } + + agentCfg := config.Agent{Name: config.ControlDispatcherAgentName, Dir: "gascity"} + query := workflowServeControlReadyQuery(agentCfg) + + queue, handled, err := tryControlReadyFromCacheOrFallback(query, cityDir, nil) + if err != nil { + t.Fatalf("tryControlReadyFromCacheOrFallback: %v", err) + } + if !handled { + t.Fatalf("tryControlReadyFromCacheOrFallback: handled = false, want true for a control-ready query") + } + + var gotIDs []string + for _, b := range queue { + gotIDs = append(gotIDs, b.ID) + } + wantIDs := []string{routed.ID} + if !stringSlicesEqual(gotIDs, wantIDs) { + t.Fatalf("queue ids = %#v, want %#v (held beads %s and %s must not be auto-routed to the pool)", gotIDs, wantIDs, heldMayor.ID, heldExternal.ID) + } +} + +// TestTryControlReadyFromCacheOrFallbackExcludesDispatchHoldLabelsOnFallbackPath +// is ga-5736js end-to-end on the fallback path: a routed_to-matching bead +// carrying a beadmeta.DispatchHoldLabels value in the single batched +// `bd ready --json` response must not reach the control dispatcher's queue, +// matching the cache-path behavior above. The hold labels are spelled as +// literal JSON in the fake bd script on purpose -- this test pins the wire +// format bd emits, so substituting the Go constants here would defeat it. +// (End-to-end coverage originates from PR #4787.) +func TestTryControlReadyFromCacheOrFallbackExcludesDispatchHoldLabelsOnFallbackPath(t *testing.T) { + configureIsolatedRuntimeEnv(t) + cityDir := t.TempDir() + if err := os.WriteFile(filepath.Join(cityDir, "city.toml"), []byte("[workspace]\nname = \"test-city\"\n"), 0o644); err != nil { + t.Fatalf("write city.toml: %v", err) + } + + tmp := t.TempDir() + bdPath := filepath.Join(tmp, "bd") + target := "gascity/control-dispatcher" + script := fmt.Sprintf(`#!/bin/sh +set -eu +case "$1" in + list) + exit 7 + ;; +esac +printf '[{"id":"ga-fallback-routed","metadata":{"gc.routed_to":"%s"}},{"id":"ga-fallback-held-mayor","metadata":{"gc.routed_to":"%s"},"labels":["hold:mayor"]},{"id":"ga-fallback-held-external","metadata":{"gc.routed_to":"%s"},"labels":["hold:external"]}]' +`, target, target, target) + if err := os.WriteFile(bdPath, []byte(script), 0o755); err != nil { + t.Fatalf("write fake bd: %v", err) + } + t.Setenv("PATH", tmp+string(os.PathListSeparator)+os.Getenv("PATH")) + t.Setenv("GC_BEADS", "bd") + + agentCfg := config.Agent{Name: config.ControlDispatcherAgentName, Dir: "gascity"} + query := workflowServeControlReadyQuery(agentCfg) + + queue, handled, err := tryControlReadyFromCacheOrFallback(query, cityDir, nil) + if err != nil { + t.Fatalf("tryControlReadyFromCacheOrFallback: %v", err) + } + if !handled { + t.Fatalf("handled = false, want true") + } + var gotIDs []string + for _, b := range queue { + gotIDs = append(gotIDs, b.ID) + } + wantIDs := []string{"ga-fallback-routed"} + if !stringSlicesEqual(gotIDs, wantIDs) { + t.Fatalf("queue ids = %#v, want %#v (held beads ga-fallback-held-mayor and ga-fallback-held-external must not be auto-routed to the pool)", gotIDs, wantIDs) + } +} diff --git a/cmd/gc/dolt_runtime_publication.go b/cmd/gc/dolt_runtime_publication.go index 77915e8f82..951c45b6e9 100644 --- a/cmd/gc/dolt_runtime_publication.go +++ b/cmd/gc/dolt_runtime_publication.go @@ -71,6 +71,13 @@ func managedDoltLifecycleOwned(cityPath string) (bool, error) { if cityUsesDoltliteBeadsBackend(cityPath) { return false, nil } + completeBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(cityPath)) + if err != nil { + return false, err + } + if completeBinding { + return false, nil + } _, usesPostgres, err := postgresMetadataForScope(cityPath, cityPath) if err != nil { return false, err @@ -207,6 +214,13 @@ func clearManagedDoltRuntimeState(cityPath string) error { func clearManagedDoltRuntimeStateUnlessPostgres(cityPath string) error { if cityUsesBdStoreContract(cityPath) { + completeBinding, err := scopeHasCompleteStorageBinding(scopeMetadataJSONPath(cityPath)) + if err != nil { + return err + } + if completeBinding { + return nil + } _, usesPostgres, err := postgresMetadataForScope(cityPath, cityPath) if err != nil { return err diff --git a/cmd/gc/dolt_runtime_publication_storage_binding_test.go b/cmd/gc/dolt_runtime_publication_storage_binding_test.go new file mode 100644 index 0000000000..25f2ceb110 --- /dev/null +++ b/cmd/gc/dolt_runtime_publication_storage_binding_test.go @@ -0,0 +1,153 @@ +package main + +import ( + "bytes" + "os" + "path/filepath" + "strings" + "testing" +) + +const completeBoundStorageMetadata = `{ + "backend": "postgres", + "storage_endpoint": "opaque-remote", + "storage_database": "work", + "dolt_mode": "server", + "dolt_database": "legacy", + "unknown": {"preserve": true} +} +` + +func writeBoundStorageLifecycleFixture(t *testing.T, metadata string) (string, string) { + t.Helper() + cityPath := t.TempDir() + metadataPath := scopeMetadataJSONPath(cityPath) + if err := os.MkdirAll(filepath.Dir(metadataPath), 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(metadataPath, []byte(metadata), 0o600); err != nil { + t.Fatal(err) + } + script := gcBeadsBdScriptPath(cityPath) + if err := os.MkdirAll(filepath.Dir(script), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(script, []byte("#!/bin/sh\nexit 99\n"), 0o755); err != nil { + t.Fatal(err) + } + t.Setenv("GC_BEADS", "exec:"+script) + t.Setenv("GC_BEADS_SCOPE_ROOT", cityPath) + return cityPath, metadataPath +} + +func TestManagedDoltLifecycleOwnedSkipsCompleteStorageBinding(t *testing.T) { + cityPath, metadataPath := writeBoundStorageLifecycleFixture(t, completeBoundStorageMetadata) + wantMetadata, err := os.ReadFile(metadataPath) + if err != nil { + t.Fatal(err) + } + + owned, err := managedDoltLifecycleOwned(cityPath) + if err != nil { + t.Fatalf("managedDoltLifecycleOwned: %v", err) + } + if owned { + t.Fatal("managedDoltLifecycleOwned = true, want false for complete storage binding") + } + gotMetadata, err := os.ReadFile(metadataPath) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(gotMetadata, wantMetadata) { + t.Fatal("managed Dolt ownership probe changed storage metadata") + } +} + +func TestManagedDoltRuntimePreflightSkipsCompleteStorageBinding(t *testing.T) { + cityPath, _ := writeBoundStorageLifecycleFixture(t, completeBoundStorageMetadata) + var stderr bytes.Buffer + healthCalls := 0 + portCalls := 0 + + ensureManagedDoltPublishedForRuntime( + cityPath, + &stderr, + "gc test", + func(string) error { healthCalls++; return nil }, + managedDoltLifecycleOwned, + func(string) string { portCalls++; return "" }, + ) + + if stderr.Len() != 0 { + t.Fatalf("runtime preflight stderr = %q, want empty", stderr.String()) + } + if healthCalls != 0 || portCalls != 0 { + t.Fatalf("runtime preflight calls: health=%d port=%d, want neither", healthCalls, portCalls) + } +} + +func TestShutdownBeadsProviderSkipsCompleteStorageBinding(t *testing.T) { + cityPath, metadataPath := writeBoundStorageLifecycleFixture(t, completeBoundStorageMetadata) + runtimePath := managedDoltStatePath(cityPath) + if err := os.MkdirAll(filepath.Dir(runtimePath), 0o755); err != nil { + t.Fatal(err) + } + const runtimeState = "stale managed runtime state\n" + if err := os.WriteFile(runtimePath, []byte(runtimeState), 0o600); err != nil { + t.Fatal(err) + } + wantMetadata, err := os.ReadFile(metadataPath) + if err != nil { + t.Fatal(err) + } + + if err := shutdownBeadsProvider(cityPath); err != nil { + t.Fatalf("shutdownBeadsProvider: %v", err) + } + gotRuntime, err := os.ReadFile(runtimePath) + if err != nil { + t.Fatalf("read preserved managed runtime state: %v", err) + } + if string(gotRuntime) != runtimeState { + t.Fatalf("managed runtime state = %q, want preserved %q", gotRuntime, runtimeState) + } + gotMetadata, err := os.ReadFile(metadataPath) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(gotMetadata, wantMetadata) { + t.Fatal("shutdown changed storage metadata") + } +} + +func TestManagedDoltLifecycleOwnedStillRejectsIncompleteStorageMetadata(t *testing.T) { + tests := []struct { + name string + metadata string + want string + }{ + { + name: "partial storage binding", + metadata: `{"backend":"postgres","storage_endpoint":"opaque-remote","dolt_mode":"server"}`, + want: "partial beads storage binding", + }, + { + name: "ordinary mixed metadata", + metadata: `{"backend":"postgres","dolt_mode":"server","dolt_database":"legacy"}`, + want: "cannot mix dolt and postgres fields", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cityPath, _ := writeBoundStorageLifecycleFixture(t, tt.metadata) + owned, err := managedDoltLifecycleOwned(cityPath) + if err == nil { + t.Fatalf("managedDoltLifecycleOwned error = nil, owned=%v", owned) + } + if !strings.Contains(err.Error(), tt.want) { + t.Fatalf("managedDoltLifecycleOwned error = %q, want %q", err, tt.want) + } + }) + } +} diff --git a/cmd/gc/hook_cross_store.go b/cmd/gc/hook_cross_store.go index fddbe898cc..747201717a 100644 --- a/cmd/gc/hook_cross_store.go +++ b/cmd/gc/hook_cross_store.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "os" "strings" "time" @@ -97,7 +98,7 @@ func appendOneRigHookStore(stores []hookStore, cityPath string, cfg *config.City // controllerWorkQueryEnv at city coordinates; identity overrides are preserved // so the query still matches work routed/assigned to this agent. Best-effort: // returns stores unchanged when the city env cannot be built, and the city -// entry is appended LAST so the rig store keeps firstStoreWithWork's +// entry is appended LAST so the rig store keeps bestStoreWithWork's // emit-on-timeout contract as the primary entry. func appendCityHookStore(stores []hookStore, cityPath string, cfg *config.City, a *config.Agent, identityOverrides map[string]string) []hookStore { if cfg == nil || a == nil { @@ -144,10 +145,36 @@ func rigScopedHookRig(cfg *config.City, agentIdentity string) string { return "" } -// firstStoreWithWork runs command against each store in order and returns the -// output and store of the FIRST store that reports ready work (applying the same -// normalize + unready-filter that doHook uses, so a store with only -// deferred/blocked rows is not treated as a hit). run is injectable for tests. +// bestStoreWithWork runs command against each store and returns the output and +// store holding the work the agent should pick up NEXT — the best-ranked ready +// candidate across every federated store, not merely the first store that has +// anything (applying the same normalize + unready-filter that doHook uses, so a +// store with only deferred/blocked rows is not a hit). run is injectable for +// tests. +// +// Why ranking rather than first-hit: the store list puts a city-scoped agent's +// OWN store ahead of the federated rig stores, so returning the first hit meant +// a rig-routed P0 stayed invisible behind a city P2 for as long as the city +// store had anything at all. Priority was never compared across the store +// boundary, so priority could not rescue it — for a crew agent that always has +// some city work, rig-routed beads were not deprioritized but unreachable. +// Ranking compares candidates the way the three-tier work_query intends them to +// be consumed (see hookCandidateRank), which makes the ordering hold ACROSS +// stores as well as within one. This changes only WHICH already-matching store +// is selected: every store's query still matches this agent's own identity, so +// no bead becomes visible that was not already routed or assigned to it. +// +// Ties keep the slice order, so an equally-ranked candidate in the agent's own +// store still wins — the pre-existing behavior whenever ranking is a wash. +// +// Two deliberate carve-outs from ranking: +// - A tier-0 (in_progress) candidate in the PRIMARY store short-circuits. +// Resuming this session's own interrupted work is unconditional, nothing may +// preempt it, and short-circuiting keeps the hot resume path at one query. +// - If any hit's output cannot be ranked (non-JSON, or JSON that is not an +// array of objects), selection degrades to first-hit for the whole call. +// Reordering on a comparison we could not actually make would be worse than +// the behavior it replaces. // // When no store has ready work, an error on the agent's OWN store (identified by // primary, not by slice position) is surfaced so emitCityWorkQueryFailure can @@ -159,23 +186,60 @@ func rigScopedHookRig(cfg *config.City, agentIdentity string) string { // federated claim loop reselects over a shrinking store set: once the primary // store has been dropped it is no longer in stores, so no later federated store // may inherit its emit-on-timeout semantics. -func firstStoreWithWork(command string, stores []hookStore, primary hookStore, run hookStoreRunner) (string, hookStore, error) { +func bestStoreWithWork(command string, stores []hookStore, primary hookStore, run hookStoreRunner) (string, hookStore, error) { var lastOut string var ownStoreOut string var ownStoreErr error + + var firstHitOut string + var firstHitStore hookStore + firstHit := false + unrankable := false + + var bestOut string + var bestStore hookStore + var bestRank hookCandidateRank + haveBest := false + + now := time.Now() for _, st := range stores { out, err := run(command, st.dir, st.env) - if err == nil { - ready := filterUnreadyHookCandidates(normalizeWorkQueryOutput(strings.TrimSpace(out)), time.Now()) - if workQueryHasReadyWork(ready) { - return out, st, nil + if err != nil { + if sameHookStore(st, primary) { + ownStoreOut, ownStoreErr = out, err } + continue + } + ready := filterUnreadyHookCandidates(normalizeWorkQueryOutput(strings.TrimSpace(out)), now) + if !workQueryHasReadyWork(ready) { lastOut = out continue } - if sameHookStore(st, primary) { - ownStoreOut, ownStoreErr = out, err + if !firstHit { + firstHitOut, firstHitStore, firstHit = out, st, true } + rank, ok := bestHookCandidateRank(ready) + if !ok { + unrankable = true + continue + } + // Resuming this session's own in-progress work is unconditional. + if rank.tier == hookTierInProgress && sameHookStore(st, primary) { + return out, st, nil + } + if !haveBest || rank.less(bestRank) { + bestOut, bestStore, bestRank, haveBest = out, st, rank, true + } + } + + if unrankable && firstHit { + return firstHitOut, firstHitStore, nil + } + if haveBest { + return bestOut, bestStore, nil + } + if firstHit { + return firstHitOut, firstHitStore, nil } if ownStoreErr != nil { return ownStoreOut, hookStore{}, ownStoreErr @@ -183,6 +247,80 @@ func firstStoreWithWork(command string, stores []hookStore, primary hookStore, r return lastOut, hookStore{}, nil } +// Work-query tiers, ordered most-urgent first. They mirror the three tiers of +// the default work_query (config.Agent.WorkQuery): in_progress work assigned to +// this session (crash recovery), then ready work already assigned to it, then +// ready unassigned work routed to it. Every store's query matches this agent's +// own identity, so a row carrying an assignee is assigned to THIS agent and an +// unassigned row is a routed one — which is what lets the tier be read off the +// row without re-plumbing the caller's identity down here. +const ( + hookTierInProgress = iota + hookTierAssigned + hookTierRouted +) + +// hookDefaultCandidatePriority is the priority assumed for a row whose priority +// field is absent. bd's priority is a *int and omitempty, so "no priority" and +// "priority 0" are different states on the wire; treating an absent priority as +// P0 would let a field that simply was not serialized outrank a real P0. +const hookDefaultCandidatePriority = 2 + +// hookCandidateRank orders one ready work-query candidate: lower is more urgent, +// tier first and priority second. Comparing this across stores is the whole +// point — within a single store bd already applies the same ordering. +type hookCandidateRank struct { + tier int + priority int +} + +// less reports whether r should be picked ahead of other. Equal ranks report +// false in both directions, so callers that only replace on a strict improvement +// keep the store slice order as the tiebreak. +func (r hookCandidateRank) less(other hookCandidateRank) bool { + if r.tier != other.tier { + return r.tier < other.tier + } + return r.priority < other.priority +} + +// bestHookCandidateRank returns the rank of the most urgent candidate in one +// store's ready work-query output. ok is false when the output cannot be ranked +// — not JSON, not a JSON array, or an array holding a non-object — which the +// caller treats as "do not reorder on a comparison that was not made" rather +// than as an absence of work. +func bestHookCandidateRank(ready string) (hookCandidateRank, bool) { + var rows []map[string]any + if err := json.Unmarshal([]byte(strings.TrimSpace(ready)), &rows); err != nil { + return hookCandidateRank{}, false + } + best := hookCandidateRank{} + found := false + for _, row := range rows { + rank := hookRankCandidate(row) + if !found || rank.less(best) { + best, found = rank, true + } + } + return best, found +} + +// hookRankCandidate reads one row's tier and priority. An unrecognized status or +// a missing priority falls back to the least-urgent defensible reading, so a row +// gc cannot classify never preempts one it can. +func hookRankCandidate(row map[string]any) hookCandidateRank { + rank := hookCandidateRank{tier: hookTierRouted, priority: hookDefaultCandidatePriority} + if status, ok := row["status"].(string); ok && strings.EqualFold(strings.TrimSpace(status), "in_progress") { + rank.tier = hookTierInProgress + } else if assignee, ok := row["assignee"].(string); ok && strings.TrimSpace(assignee) != "" { + rank.tier = hookTierAssigned + } + if p, ok := row["priority"].(float64); ok { + rank.priority = int(p) + } + return rank +} + // claimStoreWithFallback re-validates the discovery-selected store for // claim-time freshness, then falls back to federated re-selection across all // stores when that store has emptied since discovery. It exists because @@ -197,7 +335,7 @@ func firstStoreWithWork(command string, stores []hookStore, primary hookStore, r // // A re-validation error on the selected store is surfaced only when that store // is the primary (own) store; a federated store erroring at claim time is -// best-effort and falls through to re-selection, mirroring firstStoreWithWork's +// best-effort and falls through to re-selection, mirroring bestStoreWithWork's // emit-on-timeout contract so a flaky rig store can't wedge the claim. func claimStoreWithFallback(command string, stores []hookStore, selected, primary hookStore, run hookStoreRunner) (string, hookStore, error) { selectedOut, err := run(command, selected.dir, selected.env) @@ -205,16 +343,16 @@ func claimStoreWithFallback(command string, stores []hookStore, selected, primar if sameHookStore(selected, primary) { return "", hookStore{}, err } - return firstStoreWithWork(command, stores, primary, run) + return bestStoreWithWork(command, stores, primary, run) } ready := filterUnreadyHookCandidates(normalizeWorkQueryOutput(strings.TrimSpace(selectedOut)), time.Now()) if workQueryHasReadyWork(ready) { return selectedOut, selected, nil } - return firstStoreWithWork(command, stores, primary, run) + return bestStoreWithWork(command, stores, primary, run) } -// isZeroHookStore reports whether s is the zero hookStore that firstStoreWithWork +// isZeroHookStore reports whether s is the zero hookStore that bestStoreWithWork // returns when no store has ready work (no dir and no env). func isZeroHookStore(s hookStore) bool { return strings.TrimSpace(s.dir) == "" && len(s.env) == 0 diff --git a/cmd/gc/hook_cross_store_test.go b/cmd/gc/hook_cross_store_test.go index f54d3e6a04..fc5a183876 100644 --- a/cmd/gc/hook_cross_store_test.go +++ b/cmd/gc/hook_cross_store_test.go @@ -67,7 +67,7 @@ func TestAppendOneRigHookStoreSkipsUnknownInput(t *testing.T) { } } -func TestFirstStoreWithWorkReturnsFirstStoreThatHasWork(t *testing.T) { +func TestBestStoreWithWorkReturnsTheOnlyStoreThatHasWork(t *testing.T) { stores := []hookStore{{dir: "city"}, {dir: "riga"}, {dir: "rigb"}} var calls []string run := func(_, dir string, _ []string) (string, error) { @@ -77,7 +77,7 @@ func TestFirstStoreWithWorkReturnsFirstStoreThatHasWork(t *testing.T) { } return `[]`, nil } - out, gotStore, err := firstStoreWithWork("q", stores, stores[0], run) + out, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) if err != nil { t.Fatalf("err: %v", err) } @@ -87,16 +87,199 @@ func TestFirstStoreWithWorkReturnsFirstStoreThatHasWork(t *testing.T) { if gotStore.dir != "riga" { t.Fatalf("store.dir = %q, want riga", gotStore.dir) } - // Stops at the first store with work — does not query rigb. - if len(calls) != 2 || calls[0] != "city" || calls[1] != "riga" { - t.Fatalf("calls = %v, want [city riga]", calls) + // Every store is consulted: selection is a comparison, not a first hit. + if len(calls) != 3 || calls[0] != "city" || calls[1] != "riga" || calls[2] != "rigb" { + t.Fatalf("calls = %v, want [city riga rigb]", calls) } } -func TestFirstStoreWithWorkReturnsLastWhenNoneHasWork(t *testing.T) { +// TestBestStoreWithWorkPrefersHigherPriorityInALaterStore is the regression this +// selection change exists for: the agent's own store is first in the slice and +// has ready work, so first-hit selection returned it and the rig-routed P0 was +// unreachable no matter how urgent it was. +func TestBestStoreWithWorkPrefersHigherPriorityInALaterStore(t *testing.T) { + stores := []hookStore{{dir: "city"}, {dir: "riga"}} + run := func(_, dir string, _ []string) (string, error) { + if dir == "city" { + return `[{"id":"ci-1","priority":2}]`, nil + } + return `[{"id":"va-1","priority":0}]`, nil + } + out, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) + if err != nil { + t.Fatalf("err: %v", err) + } + if gotStore.dir != "riga" { + t.Fatalf("store.dir = %q, want riga (P0 must beat the own store's P2)", gotStore.dir) + } + if out != `[{"id":"va-1","priority":0}]` { + t.Fatalf("out = %q, want riga work", out) + } +} + +// TestBestStoreWithWorkDoesNotInvertTheBug guards the other direction: a +// higher-priority candidate in the agent's OWN store must still win, and so must +// an equal-priority one (ties keep slice order). A fix that simply preferred the +// federated store would pass the regression test above and be just as wrong. +func TestBestStoreWithWorkDoesNotInvertTheBug(t *testing.T) { + for _, tc := range []struct { + name string + rigRow string + wantDir string + wantNote string + }{ + {"own store higher priority", `[{"id":"va-1","priority":3}]`, "city", "P1 in own store beats rig P3"}, + {"equal priority keeps slice order", `[{"id":"va-1","priority":1}]`, "city", "tie must not move the selection"}, + } { + t.Run(tc.name, func(t *testing.T) { + stores := []hookStore{{dir: "city"}, {dir: "riga"}} + run := func(_, dir string, _ []string) (string, error) { + if dir == "city" { + return `[{"id":"ci-1","priority":1}]`, nil + } + return tc.rigRow, nil + } + _, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) + if err != nil { + t.Fatalf("err: %v", err) + } + if gotStore.dir != tc.wantDir { + t.Fatalf("store.dir = %q, want %q (%s)", gotStore.dir, tc.wantDir, tc.wantNote) + } + }) + } +} + +// TestBestStoreWithWorkRanksTierAheadOfPriority pins that priority is compared +// WITHIN a tier, never across one: the three-tier work_query means crash +// recovery and pre-assigned work outrank routed work regardless of number. +func TestBestStoreWithWorkRanksTierAheadOfPriority(t *testing.T) { + for _, tc := range []struct { + name string + cityRow string + rigRow string + wantDir string + }{ + { + name: "in_progress in a rig store beats a routed P0 in the own store", + cityRow: `[{"id":"ci-1","priority":0}]`, + rigRow: `[{"id":"va-1","priority":3,"status":"in_progress","assignee":"me"}]`, + wantDir: "riga", + }, + { + name: "assigned beats routed at worse priority", + cityRow: `[{"id":"ci-1","priority":0}]`, + rigRow: `[{"id":"va-1","priority":3,"assignee":"me"}]`, + wantDir: "riga", + }, + { + name: "within the routed tier, priority decides", + cityRow: `[{"id":"ci-1","priority":3}]`, + rigRow: `[{"id":"va-1","priority":0}]`, + wantDir: "riga", + }, + } { + t.Run(tc.name, func(t *testing.T) { + stores := []hookStore{{dir: "city"}, {dir: "riga"}} + run := func(_, dir string, _ []string) (string, error) { + if dir == "city" { + return tc.cityRow, nil + } + return tc.rigRow, nil + } + _, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) + if err != nil { + t.Fatalf("err: %v", err) + } + if gotStore.dir != tc.wantDir { + t.Fatalf("store.dir = %q, want %q", gotStore.dir, tc.wantDir) + } + }) + } +} + +// TestBestStoreWithWorkShortCircuitsOwnInProgress pins the resume carve-out: +// this session's own interrupted work is unconditional, so the primary store's +// in_progress row is taken without consulting any federated store at all. +func TestBestStoreWithWorkShortCircuitsOwnInProgress(t *testing.T) { + stores := []hookStore{{dir: "city"}, {dir: "riga"}} + var calls []string + run := func(_, dir string, _ []string) (string, error) { + calls = append(calls, dir) + if dir == "city" { + return `[{"id":"ci-1","priority":3,"status":"in_progress","assignee":"me"}]`, nil + } + return `[{"id":"va-1","priority":0,"status":"in_progress","assignee":"me"}]`, nil + } + _, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) + if err != nil { + t.Fatalf("err: %v", err) + } + if gotStore.dir != "city" { + t.Fatalf("store.dir = %q, want city (own in_progress work is unconditional)", gotStore.dir) + } + if len(calls) != 1 || calls[0] != "city" { + t.Fatalf("calls = %v, want [city] — the resume path must not query rig stores", calls) + } +} + +// TestBestStoreWithWorkDegradesToFirstHitOnUnrankableOutput pins the degradation +// rule: a work_query that does not emit a JSON array of objects cannot be +// compared, so selection falls back to the pre-existing first-hit behavior +// rather than reordering on a comparison that was never made. +func TestBestStoreWithWorkDegradesToFirstHitOnUnrankableOutput(t *testing.T) { + stores := []hookStore{{dir: "city"}, {dir: "riga"}} + run := func(_, dir string, _ []string) (string, error) { + if dir == "city" { + return "va-1 some plain-text row", nil + } + return `[{"id":"va-2","priority":0}]`, nil + } + _, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) + if err != nil { + t.Fatalf("err: %v", err) + } + if gotStore.dir != "city" { + t.Fatalf("store.dir = %q, want city (unrankable output degrades to first-hit)", gotStore.dir) + } +} + +// TestBestHookCandidateRank exercises the ranking primitive directly, including +// the wire-shape distinction that motivates hookDefaultCandidatePriority: bd's +// priority is *int with omitempty, so an ABSENT priority must not be read as P0. +func TestBestHookCandidateRank(t *testing.T) { + for _, tc := range []struct { + name string + ready string + want hookCandidateRank + ok bool + }{ + {"routed with priority", `[{"id":"a","priority":1}]`, hookCandidateRank{hookTierRouted, 1}, true}, + {"absent priority is not P0", `[{"id":"a"}]`, hookCandidateRank{hookTierRouted, hookDefaultCandidatePriority}, true}, + {"assignee lifts the tier", `[{"id":"a","assignee":"me","priority":3}]`, hookCandidateRank{hookTierAssigned, 3}, true}, + {"in_progress is the top tier", `[{"id":"a","assignee":"me","status":"in_progress","priority":3}]`, hookCandidateRank{hookTierInProgress, 3}, true}, + {"blank assignee stays routed", `[{"id":"a","assignee":" ","priority":1}]`, hookCandidateRank{hookTierRouted, 1}, true}, + {"best of several rows wins", `[{"id":"a","priority":3},{"id":"b","priority":0}]`, hookCandidateRank{hookTierRouted, 0}, true}, + {"empty array is unrankable", `[]`, hookCandidateRank{}, false}, + {"non-JSON is unrankable", `not json`, hookCandidateRank{}, false}, + {"array of non-objects is unrankable", `["a"]`, hookCandidateRank{}, false}, + } { + t.Run(tc.name, func(t *testing.T) { + got, ok := bestHookCandidateRank(tc.ready) + if ok != tc.ok { + t.Fatalf("ok = %v, want %v", ok, tc.ok) + } + if ok && got != tc.want { + t.Fatalf("rank = %+v, want %+v", got, tc.want) + } + }) + } +} + +func TestBestStoreWithWorkReturnsLastWhenNoneHasWork(t *testing.T) { stores := []hookStore{{dir: "city"}, {dir: "riga"}} run := func(_, _ string, _ []string) (string, error) { return `[]`, nil } - out, gotStore, err := firstStoreWithWork("q", stores, stores[0], run) + out, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) if err != nil { t.Fatalf("err: %v", err) } @@ -108,7 +291,7 @@ func TestFirstStoreWithWorkReturnsLastWhenNoneHasWork(t *testing.T) { } } -func TestFirstStoreWithWorkSurfacesOwnStoreErrorWhenNoWork(t *testing.T) { +func TestBestStoreWithWorkSurfacesOwnStoreErrorWhenNoWork(t *testing.T) { // The agent's own store (first) timing out must be surfaced even if a // federated rig store returns no work — otherwise emitCityWorkQueryFailure // never fires and a transient timeout is silently downgraded to "no work". @@ -119,12 +302,12 @@ func TestFirstStoreWithWorkSurfacesOwnStoreErrorWhenNoWork(t *testing.T) { } return `[]`, nil } - if _, _, err := firstStoreWithWork("q", stores, stores[0], run); !errors.Is(err, errTestStoreTimeout) { + if _, _, err := bestStoreWithWork("q", stores, stores[0], run); !errors.Is(err, errTestStoreTimeout) { t.Fatalf("own-store error must be surfaced when no store has work; got %v", err) } } -func TestFirstStoreWithWorkIgnoresRigStoreErrorWhenOwnStoreHasNoWork(t *testing.T) { +func TestBestStoreWithWorkIgnoresRigStoreErrorWhenOwnStoreHasNoWork(t *testing.T) { // A flaky federated rig store must not wedge the hook: when the agent's own // store is healthy (no work), a rig-store error is best-effort and dropped. stores := []hookStore{{dir: "city"}, {dir: "riga"}} @@ -134,7 +317,7 @@ func TestFirstStoreWithWorkIgnoresRigStoreErrorWhenOwnStoreHasNoWork(t *testing. } return "", errTestStoreTimeout } - out, gotStore, err := firstStoreWithWork("q", stores, stores[0], run) + out, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) if err != nil { t.Fatalf("rig-store error must not surface when own store is healthy; got %v", err) } @@ -146,7 +329,7 @@ func TestFirstStoreWithWorkIgnoresRigStoreErrorWhenOwnStoreHasNoWork(t *testing. } } -func TestFirstStoreWithWorkSkipsStoreWithOnlyUnreadyRows(t *testing.T) { +func TestBestStoreWithWorkSkipsStoreWithOnlyUnreadyRows(t *testing.T) { // A store whose only row is dep-blocked is NOT a hit; federation moves on. stores := []hookStore{{dir: "city"}, {dir: "riga"}} run := func(_, dir string, _ []string) (string, error) { @@ -155,7 +338,7 @@ func TestFirstStoreWithWorkSkipsStoreWithOnlyUnreadyRows(t *testing.T) { } return `[{"id":"va-2"}]`, nil } - out, gotStore, err := firstStoreWithWork("q", stores, stores[0], run) + out, gotStore, err := bestStoreWithWork("q", stores, stores[0], run) if err != nil { t.Fatalf("err: %v", err) } diff --git a/cmd/gc/main_test.go b/cmd/gc/main_test.go index 87389e1ca8..55741c459b 100644 --- a/cmd/gc/main_test.go +++ b/cmd/gc/main_test.go @@ -7306,7 +7306,7 @@ base = "builtin:codex"`) } } -func TestDoPrimeHookIgnoresProviderSessionKeyFromHookStdinForNonCodex(t *testing.T) { +func TestDoPrimeClaudeHookPersistsProviderSessionKeyFromHookStdin(t *testing.T) { dir, sessionID := setupPrimeHookProviderSessionKeyTest(t, "claude", `[providers.claude] base = "builtin:claude"`) setPrimeHookStdinJSON(t, map[string]string{ @@ -7321,6 +7321,34 @@ base = "builtin:claude"`) t.Fatalf("doPrimeWithMode = %d, want 0; stderr: %s", code, stderr.String()) } + updatedStore, err := openCityStoreAt(dir) + if err != nil { + t.Fatal(err) + } + updated, err := updatedStore.Get(sessionID) + if err != nil { + t.Fatal(err) + } + if got := strings.TrimSpace(updated.Metadata["session_key"]); got != "claude-provider-session" { + t.Fatalf("session_key = %q, want Claude provider session id from hook stdin", got) + } +} + +func TestDoPrimeHookIgnoresProviderSessionKeyFromHookStdinForUnsupportedProvider(t *testing.T) { + dir, sessionID := setupPrimeHookProviderSessionKeyTest(t, "gemini", `[providers.gemini] +base = "builtin:gemini"`) + setPrimeHookStdinJSON(t, map[string]string{ + "session_id": "gemini-provider-session", + "hook_event_name": "SessionStart", + "source": "startup", + }) + + var stdout, stderr bytes.Buffer + code := doPrimeWithMode(nil, &stdout, &stderr, true, false) + if code != 0 { + t.Fatalf("doPrimeWithMode = %d, want 0; stderr: %s", code, stderr.String()) + } + updatedStore, err := openCityStoreAt(dir) if err != nil { t.Fatal(err) @@ -7330,7 +7358,7 @@ base = "builtin:claude"`) t.Fatal(err) } if got := strings.TrimSpace(updated.Metadata["session_key"]); got != "" { - t.Fatalf("session_key = %q, want empty for non-Codex hook stdin session id", got) + t.Fatalf("session_key = %q, want empty for hook stdin session id from a provider outside the hook-stdin allowlist (gemini surfaces its id via env)", got) } } diff --git a/cmd/gc/order_dispatch.go b/cmd/gc/order_dispatch.go index 065011e532..deed1ad19c 100644 --- a/cmd/gc/order_dispatch.go +++ b/cmd/gc/order_dispatch.go @@ -571,25 +571,36 @@ func (m *memoryOrderDispatcher) dispatch(ctx context.Context, cityPath string, n storeKeysForGate = append(storeKeysForGate, orderStoreTargetKey(legacyOrderCityTarget(cityPath, m.cfg))) } scoped := a.ScopedName() - if m.gateBackoffActive(scoped, now) { - continue - } - hasOpenTracking, err := gateOpenWorkBounded(ctx, orderGateTimeout, scoped, func() (bool, error) { - return trackingIndex.hasOpenTracking(storesForGate, storeKeysForGate, scoped) - }) - if err != nil { - if m.gateFailClosed(ctx, a, scoped, err) { - if errors.Is(err, errGateTimeout) { - // Anchor to actual wall clock after the gate consumed orderGateTimeout; - // using the tick-start 'now' would set a deadline that has already passed. - m.setGateBackoff(scoped, time.Now().Add(orderGateBackoffDuration)) + // NoWorkGate orders (pure probes/sweeps that track no beads) opt out of + // BOTH open-work gates entirely. The gates exist to suppress re-dispatch + // while bead work is in flight, which is meaningless for an order that + // consumes no bead work; running them makes the order's dispatch + // contingent on a Dolt read completing inside orderGateTimeout, so a slow + // store times the gate out and skips the order every cycle (#2893 + // dispatch starvation -> stale cooldown cache -> fail-closed health). + // These orders are still single-flight-bounded by their own cooldown + // interval plus the synchronous tracking bead created below. + if !a.NoWorkGate { + if m.gateBackoffActive(scoped, now) { + continue + } + hasOpenTracking, err := gateOpenWorkBounded(ctx, orderGateTimeout, scoped, func() (bool, error) { + return trackingIndex.hasOpenTracking(storesForGate, storeKeysForGate, scoped) + }) + if err != nil { + if m.gateFailClosed(ctx, a, scoped, err) { + if errors.Is(err, errGateTimeout) { + // Anchor to actual wall clock after the gate consumed orderGateTimeout; + // using the tick-start 'now' would set a deadline that has already passed. + m.setGateBackoff(scoped, time.Now().Add(orderGateBackoffDuration)) + } + continue } + } + if hasOpenTracking { continue } } - if hasOpenTracking { - continue - } baseLastRunFn := trackingIndex.lastRunFunc(storesForGate, storeKeysForGate, orders.LastRunAcross(orderFrontDoorsForStores(storesForGate))) var lastRunErr error @@ -684,23 +695,26 @@ func (m *memoryOrderDispatcher) dispatch(ctx context.Context, cityPath string, n // Skip dispatch if previous work hasn't been processed yet. // Bound the wisp-aware open-work gate (#2921) with our per-order - // timeout so a slow store can't starve later orders. - hasOpenWork, err := gateOpenWorkBounded(ctx, orderGateTimeout, scoped, func() (bool, error) { - return trackingIndex.hasOpenWork(storesForGate, storeKeysForGate, scoped, m.hasOpenWorkInStoresStrict, true) - }) - if err != nil { - if m.gateFailClosed(ctx, a, scoped, err) { - if errors.Is(err, errGateTimeout) { - // Anchor to actual wall clock after the gate consumed orderGateTimeout; - // using the tick-start 'now' would set a deadline that has already passed. - m.setGateBackoff(scoped, time.Now().Add(orderGateBackoffDuration)) + // timeout so a slow store can't starve later orders. NoWorkGate orders + // skip this gate too (see the first-gate skip above). + if !a.NoWorkGate { + hasOpenWork, err := gateOpenWorkBounded(ctx, orderGateTimeout, scoped, func() (bool, error) { + return trackingIndex.hasOpenWork(storesForGate, storeKeysForGate, scoped, m.hasOpenWorkInStoresStrict, true) + }) + if err != nil { + if m.gateFailClosed(ctx, a, scoped, err) { + if errors.Is(err, errGateTimeout) { + // Anchor to actual wall clock after the gate consumed orderGateTimeout; + // using the tick-start 'now' would set a deadline that has already passed. + m.setGateBackoff(scoped, time.Now().Add(orderGateBackoffDuration)) + } + continue } + } + if hasOpenWork { continue } } - if hasOpenWork { - continue - } // Create the tracking bead (which suppresses re-fire on the next tick) // and launch the shared dispatch core. The webhook receiver fires the @@ -2649,6 +2663,56 @@ func sweepClosedOrderTrackingRetentionBounded(store beads.Store, now time.Time, return deleted, deleteErr } +// countClosedOrderTrackingRetentionEligible returns the number of closed +// order-tracking beads across stores that would be deleted by +// sweepClosedOrderTrackingRetentionAcrossStores. It performs no deletions. +// +// It reads via orders.Store.ClosedRunsForRetention and buckets via +// bucketClosedRetentionRuns — the exact read and bucketing the sweep itself +// uses — so this preview count cannot drift from what the sweep would delete. +// The remaining logic (recent-history floor, then the deleteAfterClose cutoff on +// the closed reference time) mirrors the sweep's, counting instead of deleting. +func countClosedOrderTrackingRetentionEligible(stores []beads.Store, now time.Time, policy orderTrackingRetentionPolicy, onlyOrders map[string]struct{}) (int, error) { + if policy.deleteAfterClose <= 0 { + return 0, nil + } + if policy.retainLast < minClosedOrderTrackingRetained { + policy.retainLast = minClosedOrderTrackingRetained + } + total := 0 + cutoff := now.Add(-policy.deleteAfterClose) + var errs []error + for i, store := range stores { + if store == nil { + continue + } + runs, err := orders.NewStore(beads.OrdersStore{Store: store}).ClosedRunsForRetention() + if err != nil { + errs = append(errs, fmt.Errorf("listing closed order-tracking %s: %w", orderTrackingSweepStoreLabel(store, i), err)) + continue + } + for _, group := range bucketClosedRetentionRuns(runs, onlyOrders) { + sort.Slice(group, func(a, b int) bool { + l := orderTrackingClosedReferenceTime(group[a]) + r := orderTrackingClosedReferenceTime(group[b]) + if l.Equal(r) { + return group[a].ID > group[b].ID + } + return l.After(r) + }) + if len(group) <= policy.retainLast { + continue + } + for _, run := range group[policy.retainLast:] { + if orderTrackingClosedReferenceTime(run).Before(cutoff) { + total++ + } + } + } + } + return total, errors.Join(errs...) +} + func orderTrackingRetentionBucket(run orders.OrderRun, onlyOrders map[string]struct{}) (string, bool) { if run.Scoped == "" { return "", false diff --git a/cmd/gc/order_dispatch_gate_policy_test.go b/cmd/gc/order_dispatch_gate_policy_test.go index 7597002818..63ea938149 100644 --- a/cmd/gc/order_dispatch_gate_policy_test.go +++ b/cmd/gc/order_dispatch_gate_policy_test.go @@ -16,6 +16,17 @@ import ( "github.com/gastownhall/gascity/internal/orders" ) +// countAndDelayGateQuery records one gate query against counter and then blocks +// for delay. The call-counting stores share it so this file keeps a single +// direct sleep call site; see internal/testpolicy/resourcecensus, whose +// untagged fixed_sleep ledger is pinned and trips on a net-new direct sleep. +func countAndDelayGateQuery(mu *sync.Mutex, counter *int, delay time.Duration) { + mu.Lock() + *counter++ + mu.Unlock() + time.Sleep(delay) +} + // gateTimeoutStore makes the strict open-work gate scan (the // `order-run:`-labeled, !IncludeClosed, Limit==0 List that hasOpenWorkStrict // issues) block past the per-order gate timeout, reproducing the #2893 hang @@ -117,10 +128,7 @@ type openWorkGateCallCountStore struct { func (s *openWorkGateCallCountStore) List(q beads.ListQuery) ([]beads.Bead, error) { if strings.HasPrefix(q.Label, "order-run:") && !q.IncludeClosed && q.Limit == 0 { - s.mu.Lock() - s.gateCalls++ - s.mu.Unlock() - time.Sleep(s.delay) + countAndDelayGateQuery(&s.mu, &s.gateCalls, s.delay) } return s.Store.List(q) } @@ -355,3 +363,111 @@ func TestOrderDispatchNonIdempotentBackoffOnOpenTrackingTimeout(t *testing.T) { t.Fatalf("tick 2: no tracking bead expected while gate-timeout backoff is active; got %d", len(got)) } } + +// bothGatesCallCountStore counts every List call that belongs to an open-work +// gate query — the first gate (listCanonicalOpenOrderTrackingBeads: Label == +// labelOrderTracking, Status open, !IncludeClosed, Limit 0) and the second +// gate (hasOpenWorkStrict: Label order-run:*, !IncludeClosed, Limit 0). Each +// such call also sleeps past orderGateTimeout so a non-opt-out order is +// skipped (fail-closed) — reproducing the #2893 dispatch starvation that +// NoWorkGate exists to bypass. +type bothGatesCallCountStore struct { + beads.Store + delay time.Duration + mu sync.Mutex + calls int +} + +func (s *bothGatesCallCountStore) List(q beads.ListQuery) ([]beads.Bead, error) { + if s.isGateQuery(q) { + countAndDelayGateQuery(&s.mu, &s.calls, s.delay) + } + return s.Store.List(q) +} + +func (s *bothGatesCallCountStore) isGateQuery(q beads.ListQuery) bool { + if q.IncludeClosed || q.Limit != 0 { + return false + } + if q.Label == labelOrderTracking && q.Status == "open" { + return true + } + if strings.HasPrefix(q.Label, "order-run:") { + return true + } + return false +} + +func (s *bothGatesCallCountStore) gateCalls() int { + s.mu.Lock() + defer s.mu.Unlock() + return s.calls +} + +// TestOrderDispatchNoWorkGateSkipsGatesUnderStoreDelay is the vp-cixi.6 +// regression test: a pure cooldown probe that tracks no beads sets +// NoWorkGate, so the dispatcher must NOT run either open-work gate for it — +// not even under a store so slow the gate would time out and skip the probe +// every cycle (#2893 dispatch starvation -> stale provider-health cache -> +// fail-closed provider health). The probe still dispatches on its cooldown, +// and a plain (gate-protected) order under the same slow store is still +// skipped (fail-closed) as before. +func TestOrderDispatchNoWorkGateSkipsGatesUnderStoreDelay(t *testing.T) { + prev := orderGateTimeout + orderGateTimeout = 20 * time.Millisecond + defer func() { orderGateTimeout = prev }() + + store := &bothGatesCallCountStore{Store: beads.NewMemStore(), delay: 300 * time.Millisecond} + now := time.Date(2026, 7, 5, 12, 0, 0, 0, time.UTC) + + aa := []orders.Order{ + {Name: "provider-health-probe", Trigger: "cooldown", Interval: "1m", Exec: "true", NoWorkGate: true}, + {Name: "merge-loop-sweep", Trigger: "cooldown", Interval: "1m", Exec: "true"}, + } + ad := buildOrderDispatcherFromListExec(aa, store, nil, successfulExec, nil) + if ad == nil { + t.Fatal("expected non-nil dispatcher") + } + ad.dispatch(context.Background(), t.TempDir(), now) + ad.drain(context.Background()) + + // The NoWorkGate probe must dispatch (fail-closed starvation bypassed). + if got := trackingBeads(t, store.Store, "order-run:provider-health-probe"); len(got) == 0 { + t.Error("NoWorkGate order should dispatch without entering the gate, but no tracking bead was created (the #2893 starvation this fixes)") + } + // The plain order must still be skipped (fail-closed) under the slow store. + if got := trackingBeads(t, store.Store, "order-run:merge-loop-sweep"); len(got) != 0 { + t.Errorf("plain order should fail CLOSED on gate timeout and skip; got %d tracking beads", len(got)) + } + // No gate query should have run for the NoWorkGate order. The plain order's + // first gate (hasOpenTracking) runs once before timing out, so the total is + // exactly one gate call — NOT one per order, and NOT the second gate. + if got := store.gateCalls(); got != 1 { + t.Errorf("expected exactly 1 gate query (the plain order's first gate, timed out); got %d — NoWorkGate must skip both gates entirely (#2893)", got) + } +} + +// TestOrderDispatchNoWorkGateSkipsTrackingGateDirectly narrows the NoWorkGate +// behavior to the first gate site: a NoWorkGate order must skip the tracking +// gate and dispatch, issuing ZERO gate queries. +func TestOrderDispatchNoWorkGateSkipsTrackingGateDirectly(t *testing.T) { + store := &bothGatesCallCountStore{Store: beads.NewMemStore(), delay: 0} + now := time.Date(2026, 7, 5, 12, 0, 0, 0, time.UTC) + + aa := []orders.Order{ + {Name: "provider-health-probe", Trigger: "cooldown", Interval: "1m", Exec: "true", NoWorkGate: true}, + } + ad := buildOrderDispatcherFromListExec(aa, store, nil, successfulExec, nil) + if ad == nil { + t.Fatal("expected non-nil dispatcher") + } + ad.dispatch(context.Background(), t.TempDir(), now) + ad.drain(context.Background()) + + if got := trackingBeads(t, store.Store, "order-run:provider-health-probe"); len(got) == 0 { + t.Fatal("NoWorkGate order should dispatch without entering either gate") + } + if got := store.gateCalls(); got != 0 { + t.Errorf("NoWorkGate order must issue ZERO gate queries; got %d", got) + } +} diff --git a/cmd/gc/order_dispatch_test.go b/cmd/gc/order_dispatch_test.go index bbb37fc4d2..1e2cadd030 100644 --- a/cmd/gc/order_dispatch_test.go +++ b/cmd/gc/order_dispatch_test.go @@ -10490,3 +10490,52 @@ func TestRunDispatchGuardedRecoversPanic(t *testing.T) { t.Errorf("expected the recovered panic to be logged, got %q", logs.String()) } } + +func TestCountClosedOrderTrackingRetentionEligible(t *testing.T) { + now := time.Date(2026, 6, 7, 12, 0, 0, 0, time.UTC) + + t.Run("returns correct eligible count without deleting", func(t *testing.T) { + seed := make([]beads.Bead, 0, minClosedOrderTrackingRetained+3) + for i := range minClosedOrderTrackingRetained + 3 { + seed = append(seed, beads.Bead{ + ID: fmt.Sprintf("count-%02d", i), + Title: "order:count", + Status: "closed", + Type: "task", + CreatedAt: now.Add(-8*24*time.Hour + time.Duration(i)*time.Minute), + Labels: []string{"order-run:count", labelOrderTracking}, + Ephemeral: true, + }) + } + store := beads.NewMemStoreFrom(100, seed, nil) + policy := orderTrackingRetentionPolicyForConfig(nil) + + count, err := countClosedOrderTrackingRetentionEligible([]beads.Store{store}, now, policy, nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + // 3 beads exceed the retain-10 floor and are past the 7d TTL. + if count != 3 { + t.Fatalf("count = %d, want 3", count) + } + // Store must be unchanged — count does not delete. + for i := range minClosedOrderTrackingRetained + 3 { + id := fmt.Sprintf("count-%02d", i) + if _, err := store.Get(id); err != nil { + t.Fatalf("%s should still exist after count: %v", id, err) + } + } + }) + + t.Run("returns 0 when nothing is eligible", func(t *testing.T) { + store := beads.NewMemStore() + policy := orderTrackingRetentionPolicyForConfig(nil) + count, err := countClosedOrderTrackingRetentionEligible([]beads.Store{store}, now, policy, nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if count != 0 { + t.Fatalf("count = %d, want 0 for empty store", count) + } + }) +} diff --git a/cmd/gc/order_store.go b/cmd/gc/order_store.go index d910fd1eab..16f80ae01a 100644 --- a/cmd/gc/order_store.go +++ b/cmd/gc/order_store.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strconv" "strings" + "sync" "github.com/gastownhall/gascity/internal/beads" "github.com/gastownhall/gascity/internal/beads/contract" @@ -639,10 +640,17 @@ func orderTrackingSweepStoresFromTargets(targets []orderTrackingSweepTarget, ope return stores, errors.Join(errs...) } +// cachedOrderHistoryStoresResolver returns a resolver that opens each scope's +// store once and reuses it. The returned resolver is safe for concurrent use: +// the order-firing doctor check fans its per-order lookups out across +// goroutines, and an unguarded cache map would be a data race there. func cachedOrderHistoryStoresResolver(cityPath string, cfg *config.City, stderr io.Writer) orderStoresResolver { + var mu sync.Mutex stores := make(map[string]beads.Store) openCached := func(target execStoreTarget) (beads.Store, error) { key := orderStoreTargetKey(target) + mu.Lock() + defer mu.Unlock() if store, ok := stores[key]; ok { return store, nil } diff --git a/cmd/gc/order_store_concurrency_test.go b/cmd/gc/order_store_concurrency_test.go new file mode 100644 index 0000000000..7dd0a4e6cd --- /dev/null +++ b/cmd/gc/order_store_concurrency_test.go @@ -0,0 +1,59 @@ +package main + +import ( + "io" + "sync" + "testing" + + "github.com/gastownhall/gascity/internal/orders" +) + +// TestCachedOrderHistoryStoresResolverIsConcurrencySafe guards the contract the +// order-firing doctor check now depends on. That check resolves its per-order +// lookups in parallel, and this resolver memoises opened stores in a map; left +// unguarded that map is a data race, and under `go test -race` (or, in +// production, at random) a concurrent write panics the whole gc process. +// +// Run this with -race for it to mean anything. +func TestCachedOrderHistoryStoresResolverIsConcurrencySafe(t *testing.T) { + cityPath := writeOrderHistoryTestCity(t) + cfg, err := loadCityConfig(cityPath, io.Discard) + if err != nil { + t.Fatalf("loadCityConfig: %v", err) + } + + resolve := cachedOrderHistoryStoresResolver(cityPath, cfg, io.Discard) + + // Distinct orders so the resolver races on inserting cache entries, not + // just on reading one already-populated key. + targets := []orders.Order{ + {Name: "digest"}, + {Name: "cleanup"}, + {Name: "sweep"}, + {Name: "patrol"}, + } + + var wg sync.WaitGroup + var mu sync.Mutex + resolved := 0 + for i := 0; i < 32; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + stores, err := resolve(targets[i%len(targets)]) + if err != nil || len(stores) == 0 { + return + } + mu.Lock() + resolved++ + mu.Unlock() + }(i) + } + wg.Wait() + + // Self-validation: if nothing resolved, the goroutines never reached the + // memo map and the test would pass without exercising the race at all. + if resolved == 0 { + t.Fatal("no concurrent resolution succeeded; the test never exercised the store cache") + } +} diff --git a/cmd/gc/prime_session_key_capture_test.go b/cmd/gc/prime_session_key_capture_test.go new file mode 100644 index 0000000000..dc0f21bf21 --- /dev/null +++ b/cmd/gc/prime_session_key_capture_test.go @@ -0,0 +1,215 @@ +package main + +import ( + "bytes" + "strings" + "testing" + + "github.com/gastownhall/gascity/internal/beads" +) + +// primeCaptureTestStore stands up a file-backed city store the same way +// bd_env_test.go does, so persistPrimeHookProviderSessionKey — which resolves +// the city from GC_CITY and opens its own store handle — reads and writes the +// same on-disk store the test inspects. +func primeCaptureTestStore(t *testing.T) (cityDir string, store beads.Store) { + t.Helper() + cityDir = t.TempDir() + t.Setenv("GC_BEADS", "file") + if err := ensureScopedFileStoreLayout(cityDir); err != nil { + t.Fatalf("ensureScopedFileStoreLayout: %v", err) + } + if err := ensurePersistedScopeLocalFileStore(cityDir); err != nil { + t.Fatalf("ensurePersistedScopeLocalFileStore: %v", err) + } + t.Setenv("GC_CITY", cityDir) + s, err := openCityStoreAt(cityDir) + if err != nil { + t.Fatalf("openCityStoreAt: %v", err) + } + return cityDir, s +} + +// createCaptureSessionBead creates a session bead for the given provider family +// with an empty session_key and returns its id. +func createCaptureSessionBead(t *testing.T, store beads.Store, providerKind string) string { + t.Helper() + b, err := store.Create(beads.Bead{ + Title: "session " + providerKind, + Type: "session", + Metadata: map[string]string{ + "provider_kind": providerKind, + "session_key": "", + }, + }) + if err != nil { + t.Fatalf("create session bead: %v", err) + } + return b.ID +} + +// isolateProviderSessionEnv clears the ambient provider-session env so the test +// exercises the hook-stdin capture path deterministically (the live session this +// test may run inside can otherwise leak GC_PROVIDER_SESSION_ID). +func isolateProviderSessionEnv(t *testing.T) { + t.Helper() + t.Setenv("GC_PROVIDER_SESSION_ID", "") + t.Setenv("GEMINI_SESSION_ID", "") + t.Setenv("GC_PROVIDER_SESSION_ID_REQUIRED", "1") +} + +// TestPersistPrimeHookProviderSessionKey_ClaudeHookStdinCaptured is the +// regression guard: a claude session must capture the resume id its +// SessionStart hook delivers on stdin. Without it session_key stays empty, +// wake_mode=resume has nothing to resume, and every recycle starts fresh. +func TestPersistPrimeHookProviderSessionKey_ClaudeHookStdinCaptured(t *testing.T) { + cityDir, store := primeCaptureTestStore(t) + id := createCaptureSessionBead(t, store, "claude") + t.Setenv("GC_SESSION_ID", id) + isolateProviderSessionEnv(t) + + const claudeSessionID = "8273e9ca-ff09-4260-a03a-1f8534cc1ba5" + var stderr bytes.Buffer + persistPrimeHookProviderSessionKey(claudeSessionID, &stderr) + + got := reloadSessionKey(t, cityDir, id) + if got != claudeSessionID { + t.Fatalf("claude session_key = %q, want %q (hook stdin session id must be captured for claude; stderr=%q)", got, claudeSessionID, stderr.String()) + } + if !strings.Contains(stderr.String(), "persisted resume session_key") { + t.Errorf("successful capture must be observable, got stderr=%q", stderr.String()) + } +} + +// TestPersistPrimeHookProviderSessionKey_CodexHookStdinStillCaptured pins the +// pre-existing codex behavior so the claude fix does not regress it. +func TestPersistPrimeHookProviderSessionKey_CodexHookStdinStillCaptured(t *testing.T) { + cityDir, store := primeCaptureTestStore(t) + id := createCaptureSessionBead(t, store, "codex") + t.Setenv("GC_SESSION_ID", id) + isolateProviderSessionEnv(t) + + const codexSessionID = "codex-abc-123" + var stderr bytes.Buffer + persistPrimeHookProviderSessionKey(codexSessionID, &stderr) + + if got := reloadSessionKey(t, cityDir, id); got != codexSessionID { + t.Fatalf("codex session_key = %q, want %q", got, codexSessionID) + } +} + +// TestPersistPrimeHookProviderSessionKey_ClaudeDoesNotOverwrite confirms an +// already-captured key is authoritative: a resume-wake's SessionStart hook must +// not clobber the stored key. +func TestPersistPrimeHookProviderSessionKey_ClaudeDoesNotOverwrite(t *testing.T) { + cityDir, store := primeCaptureTestStore(t) + b, err := store.Create(beads.Bead{ + Title: "session claude", + Type: "session", + Metadata: map[string]string{ + "provider_kind": "claude", + "session_key": "original-uuid", + }, + }) + if err != nil { + t.Fatalf("create: %v", err) + } + t.Setenv("GC_SESSION_ID", b.ID) + isolateProviderSessionEnv(t) + + var stderr bytes.Buffer + persistPrimeHookProviderSessionKey("different-uuid", &stderr) + + if got := reloadSessionKey(t, cityDir, b.ID); got != "original-uuid" { + t.Fatalf("session_key = %q, want unchanged %q", got, "original-uuid") + } +} + +// TestProviderAcceptsHookStdinSessionID locks the allowlist boundary: only the +// families whose SessionStart hook delivers their authoritative resume id on +// stdin (codex, claude) are accepted; every other family is not. +func TestProviderAcceptsHookStdinSessionID(t *testing.T) { + cases := map[string]bool{ + "codex": true, + "claude": true, + "gemini": false, + "pi": false, + "opencode": false, + "unknown": false, + "": false, + } + for family, want := range cases { + if got := providerAcceptsHookStdinSessionID(family); got != want { + t.Errorf("providerAcceptsHookStdinSessionID(%q) = %v, want %v", family, got, want) + } + } +} + +// TestPersistPrimeHookProviderSessionKey_UnsupportedFamilyHookStdinRejected pins +// the safety boundary: a family outside the allowlist must NOT capture a +// hook-stdin session id. Such providers surface their id via env instead, which +// is handled before this gate. +func TestPersistPrimeHookProviderSessionKey_UnsupportedFamilyHookStdinRejected(t *testing.T) { + cityDir, store := primeCaptureTestStore(t) + id := createCaptureSessionBead(t, store, "gemini") + t.Setenv("GC_SESSION_ID", id) + isolateProviderSessionEnv(t) + + var stderr bytes.Buffer + persistPrimeHookProviderSessionKey("11111111-2222-3333-4444-555555555555", &stderr) + + if got := reloadSessionKey(t, cityDir, id); got != "" { + t.Fatalf("gemini session_key = %q, want empty (hook stdin id must not be captured for non-allowlisted families)", got) + } +} + +// TestPersistPrimeHookProviderSessionKey_ClaudeEnvSessionIDCaptured confirms the +// change is surgical — it touches only the hook-stdin branch. An id delivered +// via GC_PROVIDER_SESSION_ID (fromHookStdin=false) is captured for claude +// regardless of the gate, exactly as before. +func TestPersistPrimeHookProviderSessionKey_ClaudeEnvSessionIDCaptured(t *testing.T) { + cityDir, store := primeCaptureTestStore(t) + id := createCaptureSessionBead(t, store, "claude") + t.Setenv("GC_SESSION_ID", id) + t.Setenv("GEMINI_SESSION_ID", "") + t.Setenv("GC_PROVIDER_SESSION_ID_REQUIRED", "1") + const envSessionID = "env-1a2b3c4d" + t.Setenv("GC_PROVIDER_SESSION_ID", envSessionID) + + var stderr bytes.Buffer + persistPrimeHookProviderSessionKey("", &stderr) + + if got := reloadSessionKey(t, cityDir, id); got != envSessionID { + t.Fatalf("claude env session_key = %q, want %q (env path must be unaffected by the stdin gate)", got, envSessionID) + } +} + +// TestPersistPrimeHookProviderSessionKey_RejectsIDEqualToGCSessionID guards the +// pre-existing collision check for the claude path: a provider id equal to the +// gc session id is never stored as a resume key. +func TestPersistPrimeHookProviderSessionKey_RejectsIDEqualToGCSessionID(t *testing.T) { + cityDir, store := primeCaptureTestStore(t) + id := createCaptureSessionBead(t, store, "claude") + t.Setenv("GC_SESSION_ID", id) + isolateProviderSessionEnv(t) + + var stderr bytes.Buffer + persistPrimeHookProviderSessionKey(id, &stderr) // hook id == gc session id + + if got := reloadSessionKey(t, cityDir, id); got != "" { + t.Fatalf("session_key = %q, want empty (provider id equal to GC_SESSION_ID must be rejected)", got) + } +} + +func reloadSessionKey(t *testing.T, cityDir, id string) string { + t.Helper() + store, err := openCityStoreAt(cityDir) + if err != nil { + t.Fatalf("reopen store: %v", err) + } + b, err := store.Get(id) + if err != nil { + t.Fatalf("get session bead: %v", err) + } + return strings.TrimSpace(b.Metadata["session_key"]) +} diff --git a/cmd/gc/productmetrics_testhook.go b/cmd/gc/productmetrics_testhook.go index e25a401edc..ce051e13d9 100644 --- a/cmd/gc/productmetrics_testhook.go +++ b/cmd/gc/productmetrics_testhook.go @@ -14,6 +14,7 @@ import ( "net/url" "os" "strings" + "time" "github.com/gastownhall/gascity/internal/gchome" "github.com/gastownhall/gascity/internal/productmetrics" @@ -65,6 +66,9 @@ func openProductMetricsTesthookService() (*productmetrics.Service, error) { if !roots.AppendCertsFromPEM(certificatePEM) { return nil, errors.New("product metrics testhook CA file has no certificate") } + // Keep the tagged process contract independent of scheduler time spent + // inside RecordOnce's production 50 ms best-effort decision window. + now := time.Now() return productmetrics.OpenTesthook(productmetrics.TesthookOptions{ Home: gchome.ResolveReadOnly(), ReleaseVersion: taggedProductMetricsReleaseVersion, @@ -72,6 +76,7 @@ func openProductMetricsTesthookService() (*productmetrics.Service, error) { NoticeVersion: 1, NoticeText: []byte("Gas City product metrics test-only notice."), Endpoint: endpoint, + Now: func() time.Time { return now }, Client: &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{ MinVersion: tls.VersionTLS12, RootCAs: roots, diff --git a/cmd/gc/session_beads.go b/cmd/gc/session_beads.go index e03b35192a..2bd9194d07 100644 --- a/cmd/gc/session_beads.go +++ b/cmd/gc/session_beads.go @@ -1781,8 +1781,15 @@ func syncSessionBeadsWithSnapshotAndRigStores( bySessionName[createdSessionName] = newBead indexBySessionName[createdSessionName] = len(openBeads) - 1 if liveAlias := strings.TrimSpace(meta["alias"]); liveAlias != "" && state == "active" { - if err := session.SyncRuntimeAlias(sp, createdSessionName, liveAlias); err != nil { - fmt.Fprintf(stderr, "session beads: syncing runtime alias %q for %s: %v\n", liveAlias, agentName, err) //nolint:errcheck + runtimeInfo, infoErr := sessFront.Get(newBead.ID) + if infoErr != nil { + fmt.Fprintf(stderr, "session beads: reading runtime identity for %s: %v\n", agentName, infoErr) //nolint:errcheck + } else { + runtimeInfo.SessionName = createdSessionName + runtimeInfo.Alias = liveAlias + if err := session.SyncRuntimeAlias(sp, runtimeInfo); err != nil { + fmt.Fprintf(stderr, "session beads: syncing runtime alias %q for %s: %v\n", liveAlias, agentName, err) //nolint:errcheck + } } } } @@ -1975,8 +1982,15 @@ func syncSessionBeadsWithSnapshotAndRigStores( openBeads[idx] = b } if aliasValue, ok := batch["alias"]; ok && state == "active" { - if err := session.SyncRuntimeAlias(sp, sn, aliasValue); err != nil { - fmt.Fprintf(stderr, "session beads: syncing runtime alias %q for %s: %v\n", aliasValue, agentName, err) //nolint:errcheck + runtimeInfo, infoErr := sessFront.Get(b.ID) + if infoErr != nil { + fmt.Fprintf(stderr, "session beads: reading runtime identity for %s: %v\n", agentName, infoErr) //nolint:errcheck + } else { + runtimeInfo.SessionName = sn + runtimeInfo.Alias = aliasValue + if err := session.SyncRuntimeAlias(sp, runtimeInfo); err != nil { + fmt.Fprintf(stderr, "session beads: syncing runtime alias %q for %s: %v\n", aliasValue, agentName, err) //nolint:errcheck + } } } } diff --git a/cmd/gc/session_beads_test.go b/cmd/gc/session_beads_test.go index fd8fe8e6af..ebfb543fb1 100644 --- a/cmd/gc/session_beads_test.go +++ b/cmd/gc/session_beads_test.go @@ -2697,6 +2697,13 @@ func TestSyncSessionBeads_ClearsManagedAliasWhenRemoved(t *testing.T) { } else if got != "" { t.Fatalf("GC_ALIAS = %q, want empty", got) } + for _, key := range []string{"GC_AGENT", "BEADS_ACTOR"} { + if got, err := sp.GetMeta("s-gc-123", key); err != nil { + t.Fatalf("GetMeta(%s): %v", key, err) + } else if got != "s-gc-123" { + t.Fatalf("%s = %q, want session-name fallback", key, got) + } + } } func TestSyncSessionBeads_Idempotent(t *testing.T) { diff --git a/cmd/gc/session_lifecycle_parallel.go b/cmd/gc/session_lifecycle_parallel.go index 8497ae12b3..d162eb048f 100644 --- a/cmd/gc/session_lifecycle_parallel.go +++ b/cmd/gc/session_lifecycle_parallel.go @@ -1146,13 +1146,10 @@ func buildPreparedStartWithWorkDirResolver( // recoverRunningPendingCreate / direct-call paths where it was empty. candidate.info = candidate.info.ApplyPatch(sessionpkg.MetadataPatch{"instance_token": instanceToken}) } - beadAlias := strings.TrimSpace(candidate.info.Alias) + runtimeInfo := candidate.info + runtimeInfo.SessionName = candidate.name() runtimeEnv := sessionpkg.RuntimeEnvWithSessionContext( - candidate.info.ID, - candidate.name(), - beadAlias, - strings.TrimSpace(candidate.info.Template), - strings.TrimSpace(candidate.info.SessionOrigin), + runtimeInfo, generation, continuationEpoch, instanceToken, diff --git a/cmd/gc/session_lifecycle_parallel_test.go b/cmd/gc/session_lifecycle_parallel_test.go index 9412677bd4..041eefd270 100644 --- a/cmd/gc/session_lifecycle_parallel_test.go +++ b/cmd/gc/session_lifecycle_parallel_test.go @@ -7050,13 +7050,11 @@ func TestPrepareStartCandidate_PreservesRuntimeConfigAndProviderEnv(t *testing.T t.Fatalf("continuation_epoch metadata = %q: %v", stored.Metadata["continuation_epoch"], err) } + expectedInfo := sessiontest.SeedBead(t, stored) + expectedInfo.SessionName = tp.SessionName expected := templateParamsToConfig(tp) expected.Env = mergeEnv(expected.Env, sessionpkg.RuntimeEnvWithSessionContext( - stored.ID, - tp.SessionName, - tp.Alias, - stored.Metadata["template"], - stored.Metadata["session_origin"], + expectedInfo, generation, continuationEpoch, stored.Metadata["instance_token"], diff --git a/cmd/gc/session_reconciler.go b/cmd/gc/session_reconciler.go index e428df3dd6..fcf93e45e1 100644 --- a/cmd/gc/session_reconciler.go +++ b/cmd/gc/session_reconciler.go @@ -543,13 +543,13 @@ func finalizeDrainAckStoppedSession( Payload: api.SessionLifecyclePayloadJSON(info.ID, template, "drain acknowledged"), }) } - hasAssignedWork, assignedErr := sessionHasOpenAssignedWorkForReachableStore(cityPath, cfg, store, rigStores, info) + hasAssignedWork, assignedErr := sessionHasOpenAssignedWorkForReachableStoreForCloseGate(cityPath, cfg, store, rigStores, info) if assignedErr != nil { fmt.Fprintf(stderr, "session reconciler: checking assigned work for drain-acked %s: %v\n", name, assignedErr) //nolint:errcheck hasAssignedWork = true } if closeIfUnassigned && !hasAssignedWork { - if closeSessionBeadIfReachableStoreUnassigned(cityPath, cfg, store, rigStores, info, "drained", clk.Now().UTC(), stderr) { + if closeSessionBeadIfReachableStoreUnassigned(cityPath, cfg, store, rigStores, info, "drained", clk.Now().UTC(), stderr, true) { closePatch := sessionpkg.ClosePatch(clk.Now().UTC(), "drained") if dops != nil { _ = dops.clearDrain(name) @@ -589,7 +589,7 @@ func finalizeDrainAckStoppedSession( recordStopped(false) return drainAckFinalizeResult{witnessInfo: &witnessInfo} } - assignedAfterCloseGate, closeGateAssignedErr := sessionHasOpenAssignedWorkForReachableStore(cityPath, cfg, store, rigStores, info) + assignedAfterCloseGate, closeGateAssignedErr := sessionHasOpenAssignedWorkForReachableStoreForCloseGate(cityPath, cfg, store, rigStores, info) if closeGateAssignedErr != nil { fmt.Fprintf(stderr, "session reconciler: checking assigned work after failed drain-ack close gate for %s: %v\n", name, closeGateAssignedErr) //nolint:errcheck assignedAfterCloseGate = true @@ -1869,7 +1869,7 @@ func reconcileSessionBeadsTracedWithNamedDemand( if storeQueryPartial || reconcileOpts.deferSessionClosesOnBoot { continue } - if closeSessionBeadIfReachableStoreUnassigned(cityPath, cfg, store, rigStores, infoByID[id], string(sessionpkg.StateFailedCreate), clk.Now().UTC(), stderr) { + if closeSessionBeadIfReachableStoreUnassigned(cityPath, cfg, store, rigStores, infoByID[id], string(sessionpkg.StateFailedCreate), clk.Now().UTC(), stderr, false) { // Reflect the in-memory close on the snapshot: the cross-session // min-floor scan (below) reads Info.Closed off infoByID, so a // session closed this tick must not still count as open in its @@ -2178,7 +2178,7 @@ func reconcileSessionBeadsTracedWithNamedDemand( if storeQueryPartial || reconcileOpts.deferSessionClosesOnBoot { continue } - if closeSessionBeadIfReachableStoreUnassigned(cityPath, cfg, store, rigStores, infoByID[id], reason, clk.Now().UTC(), stderr) { + if closeSessionBeadIfReachableStoreUnassigned(cityPath, cfg, store, rigStores, infoByID[id], reason, clk.Now().UTC(), stderr, false) { // Keep the snapshot's Info.Closed in step with the in-memory // close so the cross-session min-floor scan does not count this // orphan. Store-only close (closeBead/closeFailedCreateBead stamp @@ -4047,6 +4047,159 @@ func sessionHasOpenAssignedWorkForReachableStore( return false, nil } +// sessionHasOpenAssignedWorkForReachableStoreForCloseGate is the drain-ack +// close-gate form of sessionHasOpenAssignedWorkForReachableStore: identical +// reachability/identifier resolution, but the per-store probe additionally +// excludes the session's own mol-do-work "drain" step. That +// step's title is literally "Close drain step and signal completion" — counting +// it as assigned work means a session that has already signaled completion is +// judged to still have work, so the session bead never closes and the pool +// controller respawns a fresh session onto the same still-open step forever. +// +// This is a deliberately SEPARATE chain from sessionHasOpenAssignedWorkForReachableStore, +// not a shared-helper change: sessionHasOpenAssignedWorkForTier and +// sessionHasOpenAssignedWispWork (the functions that would otherwise need the +// exclusion) are also called from the awake-work chain +// (sessionHasInProgressAssignedWorkForTier), which gates unrelated decisions +// (config-drift drain deferral, the max-session-age timer, the pool-slot-freeable +// check, wake-on-assigned-work). None of those should start ignoring a session's +// own drain step — only the drain-ack close decision should. Use this function +// (and closeSessionBeadIfReachableStoreUnassigned's excludeOwnDrainStep=true form) +// ONLY from the drain-ack finalize path. +func sessionHasOpenAssignedWorkForReachableStoreForCloseGate( + cityPath string, + cfg *config.City, + store beads.Store, + rigStores map[string]beads.Store, + info sessionpkg.Info, +) (bool, error) { + identifiers := sessionAssignmentIdentifiersForConfigInfo(info, cfg) + stores, err := reachableStoresForSessionInfo(cityPath, cfg, store, rigStores, info) + if err != nil { + return false, err + } + for _, s := range stores { + if has, err := sessionHasOpenAssignedWorkInStoreByIdentifiersForCloseGate(s, identifiers); err != nil || has { + return has, err + } + } + return false, nil +} + +func sessionHasOpenAssignedWorkInStoreByIdentifiersForCloseGate(store beads.Store, identifiers []string) (bool, error) { + return sessionHasAssignedWorkInStoreByIdentifiersForStatusesForCloseGate(store, identifiers, []string{"open", "in_progress"}) +} + +func sessionHasAssignedWorkInStoreByIdentifiersForStatusesForCloseGate(store beads.Store, identifiers []string, statuses []string) (bool, error) { + if store == nil { + return false, nil + } + seen := make(map[string]struct{}, len(identifiers)) + for _, status := range statuses { + for _, assignee := range identifiers { + if assignee == "" { + continue + } + key := status + "\x00" + assignee + if _, ok := seen[key]; ok { + continue + } + seen[key] = struct{}{} + if has, err := sessionHasOpenAssignedWorkForTierForCloseGate(store, assignee, status, beads.TierIssues, true); err != nil || has { + return has, err + } + if has, err := sessionHasOpenAssignedWispWorkForCloseGate(store, assignee, status); err != nil || has { + return has, err + } + } + } + return false, nil +} + +// sessionHasOpenAssignedWorkForTierForCloseGate mirrors sessionHasOpenAssignedWorkForTier +// but filters through hasNonSessionNonOwnDrainStepWork instead of the shared +// wa.HasNonSessionWork, so the drain-step exclusion cannot leak into +// sessionHasOpenAssignedWorkForTier's other caller (the awake-work chain). +func sessionHasOpenAssignedWorkForTierForCloseGate(store beads.Store, assignee, status string, tierMode beads.TierMode, live bool) (bool, error) { + wa := workAssignmentForStore(beads.WorkStore{Store: store}) + items, err := wa.OpenAssignedTo(assignee, status, tierMode, live) + if err != nil { + return false, err + } + return hasNonSessionNonOwnDrainStepWork(store, items), nil +} + +// sessionHasOpenAssignedWispWorkForCloseGate mirrors sessionHasOpenAssignedWispWork +// for the close gate. It intentionally skips the CachedOpenAssignedWisps fast +// path: that cache is a positive-only accelerator built on the shared +// wa.HasNonSessionWork filter, and drain-ack is not a hot loop, so the extra +// live read here is cheap and keeps the exclusion correct rather than stale. +func sessionHasOpenAssignedWispWorkForCloseGate(store beads.Store, assignee, status string) (bool, error) { + return sessionHasOpenAssignedWorkForTierForCloseGate(store, assignee, status, beads.TierWisps, true) +} + +// hasNonSessionNonOwnDrainStepWork is wa.HasNonSessionWork plus the own-drain-step +// exclusion: skips session beads/repairable session beads (as HasNonSessionWork +// already does) AND the session's own mol-do-work drain step. +func hasNonSessionNonOwnDrainStepWork(store beads.Store, items []beads.Bead) bool { + for _, item := range items { + if sessionpkg.IsSessionBeadOrRepairable(item) { + continue + } + if isSessionOwnDrainStepBead(store, item) { + continue + } + return true + } + return false +} + +// isSessionOwnDrainStepBead reports whether item is a mol-do-work "drain" step +// bead: gc.step_ref's final dot-separated segment is "drain" AND its molecule +// root (gc.root_bead_id) was compiled from the mol-do-work formula. The store +// writes gc.step_ref formula-qualified (e.g. "mol-do-work.drain"), never the +// bare step id, so the match is on the LAST segment, not the whole string. +// The formula pin below already narrows to mol-do-work, so this +// segment check only has to identify "this is the drain step", not re-pin the +// formula itself. The match is deliberately narrow — it must not match +// any other step, including one that happens to reuse the literal step id +// "drain" in an unrelated formula. The identifiers-scoped assignee filter +// upstream already guarantees any matching item is assigned to THIS session, +// so no separate "is this session's own molecule" check is needed beyond +// confirming the step/formula shape itself. +func isSessionOwnDrainStepBead(store beads.Store, item beads.Bead) bool { + stepRef := strings.TrimSpace(item.Metadata[beadmeta.StepRefMetadataKey]) + if idx := strings.LastIndex(stepRef, "."); idx >= 0 { + stepRef = stepRef[idx+1:] + } + if stepRef != "drain" { + return false + } + rootID := strings.TrimSpace(item.Metadata[beadmeta.RootBeadIDMetadataKey]) + if rootID == "" || store == nil { + return false + } + root, err := store.Get(rootID) + if err != nil { + return false + } + return drainStepRootFormulaName(root) == "mol-do-work" +} + +// drainStepRootFormulaName mirrors internal/api's workflowFormulaName (root.Ref, +// falling back to gc.formula_name, falling back to the root bead's own ID) — the +// canonical way this codebase names the formula a molecule root was compiled +// from (see internal/formula/compile.go's rootStep stamping). +func drainStepRootFormulaName(root beads.Bead) string { + if name := strings.TrimSpace(root.Ref); name != "" { + return name + } + if name := strings.TrimSpace(root.Metadata[beadmeta.FormulaNameMetadataKey]); name != "" { + return name + } + return root.ID +} + // sessionHasAwakeAssignedWorkForReachableStore reports whether assigned work // should keep a session awake: in-progress work always counts, while open work // counts only when it is ready: unblocked, not deferred, and not ready-excluded. diff --git a/cmd/gc/session_reconciler_test.go b/cmd/gc/session_reconciler_test.go index 0acb5e4066..3f97f4bf7b 100644 --- a/cmd/gc/session_reconciler_test.go +++ b/cmd/gc/session_reconciler_test.go @@ -16,6 +16,7 @@ import ( "github.com/gastownhall/gascity/internal/agent" "github.com/gastownhall/gascity/internal/api" + "github.com/gastownhall/gascity/internal/beadmeta" "github.com/gastownhall/gascity/internal/beads" "github.com/gastownhall/gascity/internal/clock" "github.com/gastownhall/gascity/internal/config" @@ -1892,6 +1893,208 @@ func TestReconcileSessionBeads_DrainAckMidPhaseEmitsAssignedWorkEvent(t *testing } } +// TestReconcileSessionBeads_DrainAckOwnDrainStepClosesWithoutEvent pins that +// a session whose ONLY assigned work is its own mol-do-work "drain" step +// must actually close on drain-ack (no pool respawn) and must NOT emit +// SessionDrainAckedWithAssignedWork, since nothing is genuinely stranded. +// Before the close-gate fix, the drain step counted as assigned work, so the +// bead stayed open forever and the pool controller respawned a fresh session +// onto the same still-open step every ~20s. +func TestReconcileSessionBeads_DrainAckOwnDrainStepClosesWithoutEvent(t *testing.T) { + env := newReconcilerTestEnv() + fake := events.NewFake() + env.rec = fake + + session := env.createSessionBead("worker", "worker") + env.markSessionActive(&session) + if err := env.sp.Start(context.Background(), "worker", runtime.Config{Command: "test-cmd"}); err != nil { + t.Fatalf("Start(worker): %v", err) + } + + root, err := env.store.Create(beads.Bead{ + Title: "Run of mol-do-work", + Type: "task", + Metadata: map[string]string{ + beadmeta.FormulaNameMetadataKey: "mol-do-work", + }, + }) + if err != nil { + t.Fatalf("Create(root): %v", err) + } + drainStep, err := env.store.Create(beads.Bead{ + Title: "Close drain step and signal completion", + Type: "task", + Status: "in_progress", + Assignee: session.ID, + Metadata: map[string]string{ + // Formula-qualified, matching what the live store actually writes + // — a bare "drain" fixture would pass before and + // after the fix and prove nothing. + beadmeta.StepRefMetadataKey: "mol-do-work.drain", + beadmeta.RootBeadIDMetadataKey: root.ID, + }, + }) + if err != nil { + t.Fatalf("Create(drainStep): %v", err) + } + + dops := newFakeDrainOps() + if err := dops.setDrainAck("worker"); err != nil { + t.Fatalf("setDrainAck: %v", err) + } + + woken := reconcileSessionBeads( + context.Background(), + []beads.Bead{session}, + env.desiredState, + nil, + env.cfg, + env.sp, + env.store, + dops, + nil, + nil, + env.dt, + nil, + false, + nil, + "", + nil, + env.clk, + env.rec, + 0, + 0, + &env.stdout, + &env.stderr, + ) + if woken != 0 { + t.Fatalf("woken = %d, want 0", woken) + } + gotSession := env.reconcileStopPendingToTerminal(t, env.sp, session, dops, nil) + if gotSession.Status != "closed" { + t.Fatalf("session bead status = %q, want closed (own drain step must not block close): metadata=%v", + gotSession.Status, gotSession.Metadata) + } + + matches := 0 + for i := range fake.Events { + if fake.Events[i].Type == events.SessionDrainAckedWithAssignedWork { + matches++ + } + } + if matches != 0 { + t.Fatalf("%s events = %d, want 0 — the session's own drain step is not stranded work", events.SessionDrainAckedWithAssignedWork, matches) + } + + // The drain step itself is untouched by the close gate — the event path + // (firstOpenAssignedWorkBeadForReachableStore) and IsSessionBeadOrRepairable + // classification are deliberately unchanged; this just confirms the fix + // didn't mutate the step bead as a side effect. + gotStep, err := env.store.Get(drainStep.ID) + if err != nil { + t.Fatalf("Get(drainStep): %v", err) + } + if gotStep.Status == "closed" { + t.Errorf("drain step status = %q, the close gate must not itself close the step bead", gotStep.Status) + } +} + +// TestReconcileSessionBeads_DrainAckStepNamedDrainInOtherFormulaStillBlocksClose +// guards the narrow-match requirement in isSessionOwnDrainStepBead: a step bead +// that happens to reuse the literal step id "drain" but whose molecule root was +// NOT compiled from the mol-do-work formula must still count as assigned work — +// the exclusion is scoped to mol-do-work's drain step specifically, not to any +// step named "drain". +func TestReconcileSessionBeads_DrainAckStepNamedDrainInOtherFormulaStillBlocksClose(t *testing.T) { + env := newReconcilerTestEnv() + env.cfg = &config.City{Agents: []config.Agent{{Name: "worker"}}} + env.addDesired("worker", "worker", true) + fake := events.NewFake() + env.rec = fake + + session := env.createSessionBead("worker", "worker") + env.markSessionActive(&session) + + root, err := env.store.Create(beads.Bead{ + Title: "Run of some-other-formula", + Type: "task", + Metadata: map[string]string{ + beadmeta.FormulaNameMetadataKey: "some-other-formula", + }, + }) + if err != nil { + t.Fatalf("Create(root): %v", err) + } + decoyStep, err := env.store.Create(beads.Bead{ + Title: "drain the widget queue", + Type: "task", + Status: "in_progress", + Assignee: session.ID, + Metadata: map[string]string{ + beadmeta.StepRefMetadataKey: "some-other-formula.drain", + beadmeta.RootBeadIDMetadataKey: root.ID, + }, + }) + if err != nil { + t.Fatalf("Create(decoyStep): %v", err) + } + + dops := newFakeDrainOps() + if err := dops.setDrainAck("worker"); err != nil { + t.Fatalf("setDrainAck: %v", err) + } + + woken := reconcileSessionBeads( + context.Background(), + []beads.Bead{session}, + env.desiredState, + map[string]bool{"worker": true}, + env.cfg, + env.sp, + env.store, + dops, + nil, + nil, + env.dt, + nil, + false, + nil, + "", + nil, + env.clk, + env.rec, + 0, + 0, + &env.stdout, + &env.stderr, + ) + if woken != 0 { + t.Fatalf("woken = %d, want 0", woken) + } + gotSession := env.reconcileStopPendingToTerminal(t, env.sp, session, dops, map[string]bool{"worker": true}) + if gotSession.Status == "closed" { + t.Fatalf("session bead closed unexpectedly: a same-named 'drain' step from an unrelated formula must still block close: metadata=%v", gotSession.Metadata) + } + + matches := 0 + for i := range fake.Events { + if fake.Events[i].Type == events.SessionDrainAckedWithAssignedWork { + matches++ + } + } + if matches != 1 { + t.Fatalf("%s events = %d, want exactly 1 for the genuinely-stranded decoy step", events.SessionDrainAckedWithAssignedWork, matches) + } + + got, err := env.store.Get(decoyStep.ID) + if err != nil { + t.Fatalf("Get(decoyStep): %v", err) + } + if got.Assignee != session.ID { + t.Errorf("decoy step assignee = %q, want %q", got.Assignee, session.ID) + } +} + func TestReconcileSessionBeads_DeadDesiredDrainAckWithAssignedWorkEmitsOneEvent(t *testing.T) { env := newReconcilerTestEnv() env.cfg = &config.City{Agents: []config.Agent{{Name: "worker"}}} diff --git a/cmd/gc/session_work_guard.go b/cmd/gc/session_work_guard.go index 754a816d34..ae0562caa5 100644 --- a/cmd/gc/session_work_guard.go +++ b/cmd/gc/session_work_guard.go @@ -90,6 +90,14 @@ func closeSessionInfoIfUnassigned( // (which already funnels its writes through sessionFrontDoor AND runs the // extmsg/orphaned-work release cascade Store.Close does not — so the close stays // on closeBead, not Store.Close, to preserve that behavior). +// +// excludeOwnDrainStep selects the drain-ack close-gate form of the +// assigned-work probe (sessionHasOpenAssignedWorkForReachableStoreForCloseGate), +// which excludes the session's own mol-do-work "drain" step so a session that +// has already signaled completion is not judged to still have work. +// Pass true ONLY from the drain-ack finalize path; every +// other caller (failed-create close, generic idle/config-drift close) passes +// false to keep its existing behavior unchanged. func closeSessionBeadIfReachableStoreUnassigned( cityPath string, cfg *config.City, @@ -99,11 +107,16 @@ func closeSessionBeadIfReachableStoreUnassigned( reason string, now time.Time, stderr io.Writer, + excludeOwnDrainStep bool, ) bool { if stderr == nil { stderr = io.Discard } - hasAssignedWork, err := sessionHasOpenAssignedWorkForReachableStore(cityPath, cfg, store, rigStores, info) + assignedWorkProbe := sessionHasOpenAssignedWorkForReachableStore + if excludeOwnDrainStep { + assignedWorkProbe = sessionHasOpenAssignedWorkForReachableStoreForCloseGate + } + hasAssignedWork, err := assignedWorkProbe(cityPath, cfg, store, rigStores, info) if err != nil { fmt.Fprintf(stderr, "session work guard: checking reachable assigned work for %s: %v\n", info.ID, err) //nolint:errcheck return false diff --git a/cmd/gc/session_wpool_twins_test.go b/cmd/gc/session_wpool_twins_test.go index 6ae4d88824..4f81783644 100644 --- a/cmd/gc/session_wpool_twins_test.go +++ b/cmd/gc/session_wpool_twins_test.go @@ -395,3 +395,73 @@ func TestSnapshotAddInfoConcurrentAndCoherent(t *testing.T) { } } } + +// TestNormalizeNonExpandingPoolSessionInfoForSelectionDrainedNamedPredecessor pins +// the production call site of the #2885 self-owner exception. An asleep, drained +// configured-named predecessor for canonical identity X used to squat X's alias +// forever: the alias claim failed with ErrSessionAliasExists, selection fell back +// to recording deferred pool-alias-conflict bookkeeping, and the live pool-managed +// session never collapsed onto its own canonical identity. +// +// Both cfg.NamedSessions arrangements are exercised because the owner-scoped +// claim changes behavior in the trailing reserved-alias loop too: with X present +// in cfg.NamedSessions, selfOwner == reserved short-circuits the reservation that +// would otherwise refuse the alias. +func TestNormalizeNonExpandingPoolSessionInfoForSelectionDrainedNamedPredecessor(t *testing.T) { + cfgAgent := &config.Agent{Name: "mayor", MaxActiveSessions: intPtr(1)} + canonical := cfgAgent.QualifiedName() + + cases := []struct { + name string + city *config.City + }{ + { + name: "canonical absent from cfg.NamedSessions", + city: &config.City{}, + }, + { + name: "canonical reserved by cfg.NamedSessions", + city: &config.City{NamedSessions: []config.NamedSession{{Name: "mayor", Template: "mayor"}}}, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + predecessor := wpoolSessionBead("gm-drained-named", "open", "mayor", nil, map[string]string{ + "session_name": canonical, "session_origin": "named", + "configured_named_session": "true", "configured_named_identity": canonical, + "state": "asleep", "sleep_reason": "drained", + }) + liveBead := wpoolSessionBead("gm-live", "open", "mayor-1", nil, map[string]string{ + "template": "mayor", "agent_name": "mayor-1", "alias": "mayor-1", + "session_name": "s-live", "pool_managed": "true", "state": "awake", + }) + store := beads.NewMemStoreFrom(1, []beads.Bead{predecessor, liveBead}, nil) + bp := &agentBuildParams{beadStore: store, city: tc.city} + + folded, err := normalizeNonExpandingPoolSessionInfoForSelection(bp, cfgAgent, sessiontest.SeedBead(t, liveBead)) + if err != nil { + t.Fatalf("normalizeNonExpandingPoolSessionInfoForSelection: %v", err) + } + if folded.Alias != canonical { + t.Errorf("alias = %q, want %q (drained named predecessor must not block the collapse)", folded.Alias, canonical) + } + if folded.PoolAliasConflict != "" || folded.PoolAliasConflictCount != "" || folded.PoolAliasConflictAt != "" { + t.Errorf("deferred-conflict bookkeeping recorded: conflict=%q count=%q at=%q", + folded.PoolAliasConflict, folded.PoolAliasConflictCount, folded.PoolAliasConflictAt) + } + + persisted, err := session.NewStore(beads.SessionStore{Store: store}).Get("gm-live") + if err != nil { + t.Fatalf("store Get: %v", err) + } + if persisted.Alias != canonical { + t.Errorf("persisted alias = %q, want %q", persisted.Alias, canonical) + } + if persisted.PoolAliasConflict != "" || persisted.PoolAliasConflictCount != "" || persisted.PoolAliasConflictAt != "" { + t.Errorf("persisted deferred-conflict bookkeeping: conflict=%q count=%q at=%q", + persisted.PoolAliasConflict, persisted.PoolAliasConflictCount, persisted.PoolAliasConflictAt) + } + }) + } +} diff --git a/cmd/gc/template_resolve.go b/cmd/gc/template_resolve.go index edfddf3cae..88bfdd6a33 100644 --- a/cmd/gc/template_resolve.go +++ b/cmd/gc/template_resolve.go @@ -281,7 +281,6 @@ func resolveTemplate(p *agentBuildParams, cfgAgent *config.Agent, qualifiedName "GC_SESSION_ORIGIN": "ephemeral", "GC_AGENT": sessName, "GC_ALIAS": qualifiedName, - "BEADS_ACTOR": sessName, "GC_DIR": workDir, "GC_BEADS_SCOPE_ROOT": p.cityPath, // Explicit empty values matter here. tmux session creation uses `env -u` diff --git a/cmd/gc/usage_compute.go b/cmd/gc/usage_compute.go index a7463c57b3..39f0891507 100644 --- a/cmd/gc/usage_compute.go +++ b/cmd/gc/usage_compute.go @@ -28,6 +28,20 @@ const usageComputeEmittedAtKey = "usage_compute_emitted_at" // session-interval accounting markers, not domain metadata). const usageModelSweptAtKey = "usage_model_swept_at" +// liveModelSweepMinInterval floors how often the reconcile tick re-sweeps one +// awake session's transcript for model usage. The terminal lane is gated by a +// persisted per-interval marker, so it touches each session once; a live session +// has no such endpoint and is a candidate on EVERY tick, which makes the live +// lane's cost fleet-proportional AND repeated at the tick cadence — a bounded +// rollout discovery scan plus a transcript tail read per awake session, on the +// SYNCHRONOUS reconcile tick. Without a floor, a poke-driven sub-second cadence +// turns that into per-tick file I/O across the whole live fleet. Thirty seconds +// is far below the interval-scale staleness this lane exists to fix (usage +// previously appeared only at retirement, hours later) and far above the tick +// cadence that produces the storm; nothing is lost by waiting, because the +// cursor-guarded sweep bills the whole batch pending at the moment it next runs. +const liveModelSweepMinInterval = 30 * time.Second + // isComputeTerminalState reports whether a session state marks the end of an // awake interval, at which a compute fact should be emitted. It covers every // non-running lifecycle endpoint the controller's open-bead scan can observe: @@ -45,6 +59,17 @@ func isComputeTerminalState(state string) bool { return false } +// isLiveModelSweepState reports whether a session is currently awake and may +// still append model invocations to its transcript. It is deliberately +// disjoint from isComputeTerminalState. +func isLiveModelSweepState(state string) bool { + switch session.State(strings.TrimSpace(state)) { + case session.StateActive, session.StateAwake: + return true + } + return false +} + // emitComputeFactForBead records one compute Fact for a session bead's // completed awake interval, exactly once per awake_started_at epoch. Returns // true when a fact was recorded. It is a no-op when the sink is discard/nil, @@ -166,16 +191,34 @@ func computeFactGetCandidate(info session.Info) bool { return strings.TrimSpace(info.UsageComputeEmittedAt) != start } -// emitDueComputeFacts emits a compute Fact for any of the given open sessions whose -// awake interval has ended (terminal state) and has not yet been recorded. It reuses the -// reconcile tick's already-loaded Info snapshot for the cheap candidate filter -// (computeFactGetCandidate), then fetches the raw bead ONLY for the few sessions that -// pass it: the usage lane genuinely needs the whole bead (ResolveRunID walks the -// run-chain keys, and slept_at is not projected onto session.Info), so this is the usage -// lane's OWN edge read rather than a snapshot raw-half read. A steady fleet of parked -// sessions whose intervals are already accounted issues zero Gets. Best-effort: it never -// blocks or fails the reconcile tick. -func (cr *CityRuntime) emitDueComputeFacts(ctx context.Context, sessions []session.Info) { +// liveModelSweepCandidate reports whether an open snapshot row is worth +// loading for an incremental transcript sweep. Unlike terminal compute +// accounting, a live session remains a candidate every tick; the persisted +// invocation cursor makes repeated sweeps idempotent. +func liveModelSweepCandidate(info session.Info) bool { + return isLiveModelSweepState(info.MetadataState) && + strings.TrimSpace(info.AwakeStartedAt) != "" +} + +// emitDueComputeFacts accounts for terminal compute intervals and incrementally +// sweeps model usage from awake sessions. It reuses the reconcile tick's already-loaded +// Info snapshot for the cheap candidate filters (computeFactGetCandidate, +// liveModelSweepCandidate), then fetches the raw bead ONLY for the few sessions that +// pass one: the usage lane genuinely needs the whole bead (ResolveRunID walks the +// run-chain keys, and neither slept_at nor the transcript cursor is projected onto +// session.Info), so this is the usage lane's OWN edge read rather than a snapshot +// raw-half read. A steady fleet of parked sessions whose intervals are already +// accounted issues zero Gets. Best-effort: it never blocks or fails the reconcile +// tick. +// +// bootReconcile disables the live lane. The terminal lane's cost is unchanged by +// boot — it is gated by a persisted per-interval marker, so it fires once per +// interval whenever the pass runs — but the live lane's transcript discovery and +// reads are proportional to the awake fleet, and the boot pass covers the whole +// fleet at once on the synchronous readiness path. Deferring the live lane to the +// first steady-state tick costs one tick of billing latency and keeps startup off +// the critical path (the same trade beadReconcileTick makes for the pool sweep). +func (cr *CityRuntime) emitDueComputeFacts(ctx context.Context, sessions []session.Info, bootReconcile bool) { if cr.cs == nil { return } @@ -227,21 +270,27 @@ func (cr *CityRuntime) emitDueComputeFacts(ctx context.Context, sessions []sessi return sweepFactory } now := time.Now().UTC() - for _, info := range sessions { - if !computeFactGetCandidate(info) { - continue + liveLane := !bootReconcile + processSessionBead := func(b beads.Bead) { + if b.Metadata == nil { + return } - b, err := store.Get(info.ID) - if err != nil { - logf("usage: loading session %s for compute fact failed: %v", info.ID, err) - continue + state := b.Metadata["state"] + if isLiveModelSweepState(state) { + // Routed off the FRESH bead, so a session that woke since the snapshot + // lands here too — and on the boot pass it is skipped just like a + // snapshot-live one. + if liveLane { + cr.sweepLiveSessionModelUsage(ctx, b, now, logf, modelSweepFactory) + } + return } // Re-check the terminal state from the FRESH bead: a session that re-awoke in // the window since the snapshot was taken must not mint a tiny-wall fact for its // just-STARTED interval and suppress the real end-of-interval emission. Best- // effort accounting, the same NDI class as the sync-tail re-list delta. - if b.Metadata == nil || !isComputeTerminalState(b.Metadata["state"]) { - continue + if !isComputeTerminalState(state) { + return } awakeStart := strings.TrimSpace(b.Metadata["awake_started_at"]) // Model-usage lane FIRST, symmetric to and beside the compute fact: recover the @@ -277,4 +326,114 @@ func (cr *CityRuntime) emitDueComputeFacts(ctx context.Context, sessions []sessi // sweep. emitComputeFactForBead(ctx, sink, store, b, runtimeKind, cr.cityName, now, logf, sweepSettled) } + for _, info := range sessions { + // A canceled tick (controller shutdown, reconcile deadline) stops here + // rather than working through the rest of the fleet: every remaining + // session is picked up idempotently by the next tick. + if ctx.Err() != nil { + return + } + liveCandidate := liveLane && liveModelSweepCandidate(info) + if !computeFactGetCandidate(info) && !liveCandidate { + continue + } + b, err := store.Get(info.ID) + if err != nil { + logf("usage: loading session %s for usage facts failed: %v", info.ID, err) + continue + } + processSessionBead(b) + } +} + +// liveSweepMemo is one awake session's live model-usage sweep state, held for +// the process lifetime because the worker factory is rebuilt every tick. +// +// awakeStart and sessionKey stamp the epoch and conversation the memo describes: +// a re-wake or a replacement conversation invalidates it, so it resolves its own +// rollout rather than sweeping a stale path. Keying the map by session id (with +// the epoch inside the value) means a long-lived session replaces its memo on +// each wake instead of accumulating one entry per epoch forever. +type liveSweepMemo struct { + awakeStart string + sessionKey string + // path is the resolved transcript, empty until discovery succeeds. + path string + // settledMiss records a DEFINITIVE discovery miss — there is nothing to find + // for this epoch, so discovery is never re-attempted for it. + settledMiss bool + // nextSweepAt floors the sweep cadence (liveModelSweepMinInterval). It also + // backs off an unsettled discovery miss, so a session whose transcript cannot + // be resolved yet re-attempts discovery on that same floor instead of on + // every tick forever. + nextSweepAt time.Time +} + +// sweepLiveSessionModelUsage incrementally records model usage for an awake +// session without closing its compute interval or stamping the terminal sweep +// marker. Transcript discovery and the transcript read are both memoized and +// throttled per session (see liveSweepMemo and liveModelSweepMinInterval), so a +// live fleet costs at most one bounded discovery plus one tail read per session +// per liveModelSweepMinInterval no matter how fast the reconcile tick spins. +func (cr *CityRuntime) sweepLiveSessionModelUsage( + ctx context.Context, + b beads.Bead, + now time.Time, + logf func(string, ...any), + modelSweepFactory func() *worker.Factory, +) { + if b.Metadata == nil || !isLiveModelSweepState(b.Metadata["state"]) { + return + } + awakeStart := strings.TrimSpace(b.Metadata["awake_started_at"]) + if awakeStart == "" { + return + } + memo := cr.liveSweepMemoFor(b.ID, awakeStart, strings.TrimSpace(b.Metadata["session_key"])) + if memo.settledMiss || now.Before(memo.nextSweepAt) { + return + } + factory := modelSweepFactory() + if factory == nil { + return + } + if memo.path == "" { + // A settled miss is definitive for this epoch (unregistered provider family, + // or a keyless codex session whose CLEAN workdir+window scan found nothing — + // ambiguity, an out-of-window filename, or a TZ shift, none of which a retry + // resolves). Record it so the scan is never repeated; the session's usage is + // still recovered by the terminal sweep when its interval ends, and a re-wake + // starts a fresh epoch that discovers again. + path, settled := factory.DiscoverSweepTranscript(b.ID, b.Metadata, now) + memo.path = path + memo.settledMiss = path == "" && settled + } + // Persist the memo BEFORE the miss return: an unsettled miss must still take + // the interval floor, or discovery repeats on every tick for a session whose + // transcript never resolves. + memo.nextSweepAt = now.Add(liveModelSweepMinInterval) + cr.storeLiveSweepMemo(b.ID, memo) + if memo.path == "" { + return + } + if _, _, err := factory.SweepSessionModelUsageAtPath(ctx, b.ID, b.Metadata, memo.path, now); err != nil { + logf("usage: live model-usage sweep for session %s failed; will retry: %v", b.ID, err) + } +} + +// liveSweepMemoFor returns the session's memo for the given awake epoch and +// provider session key, or a fresh one stamped with that identity when none is +// held or the held one describes a superseded epoch or conversation. +func (cr *CityRuntime) liveSweepMemoFor(sessionID, awakeStart, sessionKey string) liveSweepMemo { + if value, ok := cr.liveSweepMemos.Load(sessionID); ok { + if memo, isMemo := value.(liveSweepMemo); isMemo && + memo.awakeStart == awakeStart && memo.sessionKey == sessionKey { + return memo + } + } + return liveSweepMemo{awakeStart: awakeStart, sessionKey: sessionKey} +} + +func (cr *CityRuntime) storeLiveSweepMemo(sessionID string, memo liveSweepMemo) { + cr.liveSweepMemos.Store(sessionID, memo) } diff --git a/cmd/gc/usage_compute_test.go b/cmd/gc/usage_compute_test.go index 6cf2e809eb..34977b0198 100644 --- a/cmd/gc/usage_compute_test.go +++ b/cmd/gc/usage_compute_test.go @@ -2,11 +2,13 @@ package main import ( "context" + "encoding/json" "errors" "fmt" "io" "os" "path/filepath" + "strings" "testing" "time" @@ -50,6 +52,32 @@ func TestComputeFactGetCandidate(t *testing.T) { } } +func TestLiveModelSweepCandidate(t *testing.T) { + const awakeStart = "2026-01-02T00:30:00Z" + for _, tc := range []struct { + name string + state string + awake string + want bool + }{ + {name: "active", state: "active", awake: awakeStart, want: true}, + {name: "awake alias", state: "awake", awake: awakeStart, want: true}, + {name: "missing interval anchor", state: "active", want: false}, + {name: "terminal", state: "asleep", awake: awakeStart, want: false}, + {name: "transitional", state: "draining", awake: awakeStart, want: false}, + } { + t.Run(tc.name, func(t *testing.T) { + info := session.Info{MetadataState: tc.state, AwakeStartedAt: tc.awake} + if got := liveModelSweepCandidate(info); got != tc.want { + t.Fatalf("liveModelSweepCandidate() = %v, want %v", got, tc.want) + } + if isLiveModelSweepState(tc.state) && isComputeTerminalState(tc.state) { + t.Fatalf("state %q is both live and compute-terminal", tc.state) + } + }) + } +} + type captureSink struct{ facts []usage.Fact } func (c *captureSink) Record(_ context.Context, f usage.Fact) error { @@ -275,20 +303,23 @@ func TestEmitComputeFactForBeadHungSinkReturnsPromptly(t *testing.T) { } } +const codexSweepSessionKey = "019e3e8e-3591-7532-a1ef-8b9e882bea2f" + // writeCodexRolloutForSweep fabricates a codex rollout transcript // (rollout--.jsonl) under root/YYYY/MM/DD reachable by the // window-free keyed discovery: a session_meta line whose cwd is workDir, a // turn_context supplying the model, and one event_msg token_count per element of -// tokenCounts ({total, lastInput, lastOutput}). Returns the rollout path. -func writeCodexRolloutForSweep(t *testing.T, root, workDir, sessionID string, tokenCounts [][3]int) { +// tokenCounts ({total, lastInput, lastOutput}). The keyed sweep scenarios share +// codexSweepSessionKey; callers vary only the transcript contents and location. +func writeCodexRolloutForSweep(t *testing.T, root, workDir string, tokenCounts [][3]int) { t.Helper() dayDir := filepath.Join(root, "2026", "06", "15") if err := os.MkdirAll(dayDir, 0o755); err != nil { t.Fatal(err) } - path := filepath.Join(dayDir, "rollout-2026-06-15T10-00-00-"+sessionID+".jsonl") + path := filepath.Join(dayDir, "rollout-2026-06-15T10-00-00-"+codexSweepSessionKey+".jsonl") lines := []string{ - fmt.Sprintf(`{"timestamp":"2026-06-15T10:00:00.000Z","type":"session_meta","payload":{"id":%q,"cwd":%q}}`, sessionID, workDir), + fmt.Sprintf(`{"timestamp":"2026-06-15T10:00:00.000Z","type":"session_meta","payload":{"id":%q,"cwd":%q}}`, codexSweepSessionKey, workDir), `{"timestamp":"2026-06-15T10:00:01.000Z","type":"turn_context","payload":{"model":"gpt-5-codex"}}`, } for i, tc := range tokenCounts { @@ -315,6 +346,443 @@ func kindCount(facts []usage.Fact, kind usage.Kind) int { return n } +// rawSinkModelFactCount counts the model facts APPENDED to the sink file, +// without usage.ReadFacts's IdempotencyKey dedup. Idempotency assertions must +// use this: ReadFacts collapses a replayed fact at read time, so it would +// silently pass even if a tick re-recorded work the cursor should have skipped. +func rawSinkModelFactCount(t *testing.T, path string) int { + t.Helper() + body, err := os.ReadFile(path) + if errors.Is(err, os.ErrNotExist) { + return 0 + } + if err != nil { + t.Fatalf("reading usage sink %s: %v", path, err) + } + n := 0 + for _, line := range strings.Split(string(body), "\n") { + if strings.TrimSpace(line) == "" { + continue + } + var f usage.Fact + if err := json.Unmarshal([]byte(line), &f); err != nil { + t.Fatalf("malformed usage fact %q: %v", line, err) + } + if f.Kind == usage.KindModel { + n++ + } + } + return n +} + +// liveSweepStart anchors a live fixture just behind the wall clock. A live +// session has no slept_at, so its transcript-discovery window runs from +// awake_started_at all the way to now: a hardcoded fixture date drifts out of +// discovery's bounded day lookback as real time advances, and the fixture stops +// being discoverable — the test would start failing for everyone on a fixed +// future day. Deriving the anchor from time.Now keeps the window an hour wide +// forever. +func liveSweepStart() time.Time { + return time.Now().UTC().Add(-time.Hour) +} + +// liveCodexSessionMeta is an AWAKE codex session's metadata: a non-terminal state +// and NO slept_at, so it is a live-lane candidate whose discovery window runs to +// the wall clock. An empty sessionKey is omitted entirely, selecting the keyless +// (work_dir, wake-window) discovery path. +func liveCodexSessionMeta(start time.Time, workDir, sessionKey string) map[string]string { + meta := map[string]string{ + "state": "active", + "session_name": "codex-live-1", + "awake_started_at": start.Format(time.RFC3339), + "work_dir": workDir, + "provider": "codex", + "builtin_ancestor": "codex", + "molecule_id": "run-L", + } + if sessionKey != "" { + meta["session_key"] = sessionKey + } + return meta +} + +// liveSweepHarness is the shared wiring for the live model-usage sweep cases: a +// session bead in a memory store, a real usage sink, and codexRoot as the only +// transcript search path. The cases differ only in session metadata and in what +// is on disk, so everything else is built once here. +type liveSweepHarness struct { + cr *CityRuntime + store *beads.MemStore + meta map[string]string + beadID string + sinkPath string + info session.Info +} + +func newLiveSweepHarness(t *testing.T, codexRoot string, meta map[string]string) liveSweepHarness { + t.Helper() + cityPath := t.TempDir() + sinkPath := filepath.Join(cityPath, ".gc", "usage.jsonl") + store := beads.NewMemStore() + cfg := &config.City{Daemon: config.DaemonConfig{ObservePaths: []string{codexRoot}}} + cs := &controllerState{cityBeadStore: store, usageSink: usage.NewLocalSink(sinkPath), cityName: "demo", cityPath: cityPath} + h := liveSweepHarness{ + cr: &CityRuntime{cs: cs, cfg: cfg, sp: runtime.NewFake(), cityName: "demo", cityPath: cityPath, stderr: io.Discard}, + store: store, + meta: meta, + sinkPath: sinkPath, + } + h.info = h.addSession(t, meta) + h.beadID = h.info.ID + return h +} + +// addSession creates another session bead in the harness store and returns the +// snapshot row the reconcile tick would hand emitDueComputeFacts for it. +func (h liveSweepHarness) addSession(t *testing.T, meta map[string]string) session.Info { + t.Helper() + b, err := h.store.Create(beads.Bead{ + Type: session.BeadType, + Status: "open", + Title: meta["session_name"], + Labels: []string{session.LabelSession}, + Metadata: meta, + }) + if err != nil { + t.Fatal(err) + } + return session.Info{ID: b.ID, MetadataState: meta["state"], AwakeStartedAt: meta["awake_started_at"]} +} + +// tick runs one STEADY-STATE reconcile-tick usage pass over the harness session. +// The boot pass is driven directly by the one case that covers it, which needs a +// two-session snapshot anyway. +func (h liveSweepHarness) tick() { + h.cr.emitDueComputeFacts(context.Background(), []session.Info{h.info}, false) +} + +// memo returns the live-sweep memo the tick holds for this session's current +// awake epoch and conversation. +func (h liveSweepHarness) memo() liveSweepMemo { + return h.cr.liveSweepMemoFor(h.beadID, h.meta["awake_started_at"], h.meta["session_key"]) +} + +// expireSweepThrottle clears the session's liveModelSweepMinInterval floor, +// standing in for that interval elapsing between ticks. It preserves the rest of +// the memo (resolved path, settled-miss sentinel) so a case advances only the +// clock. +func (h liveSweepHarness) expireSweepThrottle() { + memo := h.memo() + memo.nextSweepAt = time.Time{} + h.cr.storeLiveSweepMemo(h.beadID, memo) +} + +func (h liveSweepHarness) cursor(t *testing.T) string { + t.Helper() + b, err := h.store.Get(h.beadID) + if err != nil { + t.Fatal(err) + } + return b.Metadata[session.MetadataKeyInvocationUsageCursor] +} + +// TestEmitDueComputeFactsSweepsLiveSessionModelUsage is the undercount +// regression for "model calls today": model facts used to be minted only by the +// terminal end-of-interval sweep, so a session that stayed awake for hours +// contributed nothing to the day's totals until it finally closed. The reconcile +// tick must sweep an AWAKE session's transcript incrementally — billing each +// invocation as it lands, without minting a compute fact or closing the still-open +// interval — and the persisted invocation cursor must make a tick with no new +// transcript activity a no-op. +func TestEmitDueComputeFactsSweepsLiveSessionModelUsage(t *testing.T) { + workDir := t.TempDir() + codexRoot := t.TempDir() + start := liveSweepStart() + writeCodexRolloutForSweepAt(t, codexRoot, start, workDir, codexSweepSessionKey, [][3]int{ + {150, 100, 50}, // total=150, last input=100, output=50 + {450, 200, 100}, // total=450, last input=200, output=100 + }) + h := newLiveSweepHarness(t, codexRoot, liveCodexSessionMeta(start, workDir, codexSweepSessionKey)) + + // Tick 1: nothing terminal has happened, yet both invocations already on the + // transcript must bill now instead of waiting for retirement. + h.tick() + facts1, warnings, err := usage.ReadFacts(h.sinkPath) + if err != nil { + t.Fatalf("ReadFacts (tick 1): %v", err) + } + if len(warnings) != 0 { + t.Fatalf("unexpected sink warnings: %v", warnings) + } + if got := kindCount(facts1, usage.KindModel); got != 2 { + t.Fatalf("tick 1 model facts = %d, want 2 (a live session's invocations must bill before it closes); facts: %+v", got, facts1) + } + if got := kindCount(facts1, usage.KindCompute); got != 0 { + t.Fatalf("tick 1 compute facts = %d, want 0: the awake interval has not ended", got) + } + for _, f := range facts1 { + if f.RunID != "run-L" { + t.Fatalf("fact RunID = %q, want run-L: %+v", f.RunID, f) + } + if f.Provider != "codex" { + t.Fatalf("model fact Provider = %q, want codex", f.Provider) + } + } + + // The interval stays OPEN: stamping either accounting marker on a live sweep + // would suppress the real end-of-interval compute fact and terminal sweep. + afterTick1, err := h.store.Get(h.beadID) + if err != nil { + t.Fatal(err) + } + if got := afterTick1.Metadata[session.MetadataKeyInvocationUsageCursor]; got != "total:450" { + t.Fatalf("invocation_usage_cursor = %q, want total:450 (advanced past the swept batch)", got) + } + if got := afterTick1.Metadata[usageComputeEmittedAtKey]; got != "" { + t.Fatalf("live sweep closed the awake interval (usage_compute_emitted_at = %q), want unset", got) + } + if got := afterTick1.Metadata[usageModelSweptAtKey]; got != "" { + t.Fatalf("live sweep stamped the terminal sweep marker (%q), want unset while the interval accumulates", got) + } + + // Discovery is memoized for this awake epoch so a per-tick sweep does not + // repeat the bounded rollout scan. + if memo := h.memo(); memo.path == "" { + t.Fatalf("tick 1 did not memoize the resolved transcript path: memo=%+v", memo) + } + + // Tick 2: no transcript activity. The sweep-interval floor is cleared first so + // this asserts the CURSOR, not the throttle (TestEmitDueComputeFactsThrottles- + // LiveModelSweep owns the floor): a live session stays a candidate on every + // tick, so only the persisted cursor prevents a double-count. + h.expireSweepThrottle() + h.tick() + if got := rawSinkModelFactCount(t, h.sinkPath); got != 2 { + t.Fatalf("tick 2 appended model facts to a total of %d, want 2: the cursor must make a no-activity tick a no-op", got) + } + + // Tick 3: one new invocation lands. Only that delta bills, and the session is + // still awake, so still no compute fact. + writeCodexRolloutForSweepAt(t, codexRoot, start, workDir, codexSweepSessionKey, [][3]int{ + {150, 100, 50}, + {450, 200, 100}, + {750, 300, 150}, + }) + h.expireSweepThrottle() + h.tick() + facts3, _, err := usage.ReadFacts(h.sinkPath) + if err != nil { + t.Fatalf("ReadFacts (tick 3): %v", err) + } + if got := kindCount(facts3, usage.KindModel); got != 3 { + t.Fatalf("tick 3 model facts = %d, want 3 (one appended invocation): %+v", got, facts3) + } + if got := rawSinkModelFactCount(t, h.sinkPath); got != 3 { + t.Fatalf("tick 3 appended model facts to a total of %d, want 3 (only the delta)", got) + } + if got := kindCount(facts3, usage.KindCompute); got != 0 { + t.Fatalf("tick 3 compute facts = %d, want 0 while the session is awake", got) + } + if got := h.cursor(t); got != "total:750" { + t.Fatalf("invocation_usage_cursor = %q, want total:750", got) + } +} + +// TestEmitDueComputeFactsThrottlesLiveModelSweep pins the live lane's cost +// bound. Unlike the terminal lane — gated by a persisted per-interval marker, so +// it touches a session once — a live session is a candidate on EVERY tick, so +// without a floor the reconcile tick would run bounded transcript discovery and a +// transcript read for every awake session at whatever cadence the tick spins +// (pokes drive it sub-second). A session must be swept at most once per +// liveModelSweepMinInterval no matter how often the tick fires. +func TestEmitDueComputeFactsThrottlesLiveModelSweep(t *testing.T) { + workDir := t.TempDir() + codexRoot := t.TempDir() + start := liveSweepStart() + writeCodexRolloutForSweepAt(t, codexRoot, start, workDir, codexSweepSessionKey, [][3]int{ + {150, 100, 50}, + {450, 200, 100}, + }) + h := newLiveSweepHarness(t, codexRoot, liveCodexSessionMeta(start, workDir, codexSweepSessionKey)) + + h.tick() + if got := rawSinkModelFactCount(t, h.sinkPath); got != 2 { + t.Fatalf("tick 1 model facts = %d, want 2", got) + } + if memo := h.memo(); !memo.nextSweepAt.After(time.Now().UTC()) { + t.Fatalf("tick 1 left the sweep-interval floor unarmed: nextSweepAt=%v", memo.nextSweepAt) + } + + // A third invocation lands and the tick fires again immediately. The session is + // inside its floor, so it must not be re-swept — no discovery, no transcript + // read, no fact — even though there is genuinely new usage waiting. + writeCodexRolloutForSweepAt(t, codexRoot, start, workDir, codexSweepSessionKey, [][3]int{ + {150, 100, 50}, + {450, 200, 100}, + {750, 300, 150}, + }) + h.tick() + if got := rawSinkModelFactCount(t, h.sinkPath); got != 2 { + t.Fatalf("tick 2 model facts = %d, want 2: a tick inside liveModelSweepMinInterval must not re-sweep the session", got) + } + if got := h.cursor(t); got != "total:450" { + t.Fatalf("invocation_usage_cursor = %q, want total:450 (unmoved by the throttled tick)", got) + } + + // Once the floor elapses the same session is swept again and the delta bills: + // the throttle delays a sweep, it never drops one. + h.expireSweepThrottle() + h.tick() + if got := rawSinkModelFactCount(t, h.sinkPath); got != 3 { + t.Fatalf("tick 3 model facts = %d, want 3 (the delta bills once the floor elapses)", got) + } +} + +// TestEmitDueComputeFactsSkipsLiveModelSweepOnBootPass pins the boot carve-out. +// The boot reconcile covers the WHOLE fleet at once on the synchronous readiness +// path, which is exactly where fleet-proportional per-session file discovery and +// reads must not land. The live lane therefore waits for the first steady-state +// tick — while the terminal lane, whose per-interval marker makes it self-limiting, +// keeps running on boot as before. +func TestEmitDueComputeFactsSkipsLiveModelSweepOnBootPass(t *testing.T) { + workDir := t.TempDir() + codexRoot := t.TempDir() + start := liveSweepStart() + writeCodexRolloutForSweepAt(t, codexRoot, start, workDir, codexSweepSessionKey, [][3]int{ + {150, 100, 50}, + {450, 200, 100}, + }) + h := newLiveSweepHarness(t, codexRoot, liveCodexSessionMeta(start, workDir, codexSweepSessionKey)) + + // A retired session in the same snapshot: its interval ended, so the terminal + // lane owes it a compute fact on the boot pass. Its own workdir has no rollout, + // so it contributes no model facts either way. + slept := start.Add(90 * time.Second) + terminal := h.addSession(t, map[string]string{ + "state": "asleep", + "session_name": "codex-retired-1", + "awake_started_at": start.Format(time.RFC3339), + "slept_at": slept.Format(time.RFC3339), + "session_key": "019e7777-cccc-7000-8000-00000000000b", + "work_dir": t.TempDir(), + "provider": "codex", + "builtin_ancestor": "codex", + "molecule_id": "run-T", + }) + snapshot := []session.Info{h.info, terminal} + + h.cr.emitDueComputeFacts(context.Background(), snapshot, true) + bootFacts, _, err := usage.ReadFacts(h.sinkPath) + if err != nil { + t.Fatalf("ReadFacts (boot pass): %v", err) + } + if got := kindCount(bootFacts, usage.KindModel); got != 0 { + t.Fatalf("boot pass model facts = %d, want 0: the live lane must not run on the fleet-wide boot reconcile; facts: %+v", got, bootFacts) + } + if got := kindCount(bootFacts, usage.KindCompute); got != 1 { + t.Fatalf("boot pass compute facts = %d, want 1: the terminal lane's cost profile is unchanged and must keep running on boot", got) + } + if got := h.cursor(t); got != "" { + t.Fatalf("boot pass advanced the live session's invocation cursor to %q, want unset (it must not be swept at all)", got) + } + if memo := h.memo(); memo.path != "" || !memo.nextSweepAt.IsZero() { + t.Fatalf("boot pass touched the live session's sweep memo: %+v", memo) + } + + // The very next steady-state tick picks the live session up: boot DEFERS the + // lane, it does not disable it. + h.cr.emitDueComputeFacts(context.Background(), snapshot, false) + steadyFacts, _, err := usage.ReadFacts(h.sinkPath) + if err != nil { + t.Fatalf("ReadFacts (steady tick): %v", err) + } + if got := kindCount(steadyFacts, usage.KindModel); got != 2 { + t.Fatalf("steady tick model facts = %d, want 2 (the deferred live sweep runs on the first non-boot tick): %+v", got, steadyFacts) + } +} + +// TestEmitDueComputeFactsBacksOffUnresolvedLiveSweepDiscovery pins the miss +// memoization. A live session is a candidate on every tick, so an awake session +// whose transcript cannot be discovered yet would otherwise re-run the bounded +// rollout scan forever, once per tick, for its entire life. A TRANSIENT miss must +// be memoized as a backoff: re-attempted on the sweep floor rather than on every +// tick, and never dropped. +func TestEmitDueComputeFactsBacksOffUnresolvedLiveSweepDiscovery(t *testing.T) { + workDir := t.TempDir() + codexRoot := t.TempDir() + start := liveSweepStart() + h := newLiveSweepHarness(t, codexRoot, liveCodexSessionMeta(start, workDir, codexSweepSessionKey)) + + // Tick 1: the keyed rollout is not on disk yet. That miss is transient — the + // file may simply not be flushed — so it must not settle. + h.tick() + if got := rawSinkModelFactCount(t, h.sinkPath); got != 0 { + t.Fatalf("tick 1 model facts = %d, want 0 (no transcript on disk yet)", got) + } + memo := h.memo() + if memo.settledMiss { + t.Fatal("a keyed rollout that is merely not flushed yet must not be memoized as a settled miss") + } + if memo.nextSweepAt.IsZero() { + t.Fatal("an unresolved discovery must still arm the sweep floor, or discovery re-runs on every tick forever") + } + + // The transcript lands immediately after. Tick 2 is inside the backoff, so + // discovery is NOT re-attempted. + writeCodexRolloutForSweepAt(t, codexRoot, start, workDir, codexSweepSessionKey, [][3]int{ + {150, 100, 50}, + {450, 200, 100}, + }) + h.tick() + if got := rawSinkModelFactCount(t, h.sinkPath); got != 0 { + t.Fatalf("tick 2 model facts = %d, want 0: a memoized miss must not re-run discovery inside its backoff", got) + } + + // Once the floor elapses discovery is retried and the pending usage is + // recovered. + h.expireSweepThrottle() + h.tick() + if got := rawSinkModelFactCount(t, h.sinkPath); got != 2 { + t.Fatalf("tick 3 model facts = %d, want 2 (discovery retried once the backoff elapsed)", got) + } +} + +// TestEmitDueComputeFactsStopsRetryingSettledLiveSweepMiss pins the other half of +// the miss memoization: a DEFINITIVE miss is not retried at all. A keyless codex +// session whose bounded (work_dir, wake-window) scan comes up empty on a CLEAN +// scan has nothing to find — the outcome is ambiguity, an out-of-window filename, +// or a TZ shift, none of which a retry resolves — so the live lane records the +// verdict once and stops scanning for that awake epoch. +func TestEmitDueComputeFactsStopsRetryingSettledLiveSweepMiss(t *testing.T) { + workDir := t.TempDir() + codexRoot := t.TempDir() + start := liveSweepStart() + // No session_key: discovery takes the keyless workdir+window fallback. + h := newLiveSweepHarness(t, codexRoot, liveCodexSessionMeta(start, workDir, "")) + + h.tick() + memo := h.memo() + if !memo.settledMiss { + t.Fatalf("a clean keyless scan that found nothing is definitive and must settle: memo=%+v", memo) + } + + // Even with the floor cleared AND a matching rollout now on disk, the settled + // miss is never re-attempted. Nothing is lost: the interval's usage is still + // recovered by the terminal sweep when the session finally closes, and a re-wake + // starts a fresh epoch that discovers again. + writeCodexRolloutForSweepAt(t, codexRoot, start, workDir, "019e7777-cccc-7000-8000-00000000000c", [][3]int{ + {150, 100, 50}, + }) + h.expireSweepThrottle() + h.tick() + if got := rawSinkModelFactCount(t, h.sinkPath); got != 0 { + t.Fatalf("model facts = %d, want 0: a settled discovery miss must never re-run discovery", got) + } + if got := h.cursor(t); got != "" { + t.Fatalf("invocation_usage_cursor = %q, want unset (nothing was swept)", got) + } +} + // TestEmitDueComputeFactsAlsoSweepsModelUsage is the CORE regression for the // token-starvation bug: the controller reconcile tick emits per-interval compute // facts but never any model facts for pool-routed, hook-self-driven codex agents, @@ -330,8 +798,8 @@ func TestEmitDueComputeFactsAlsoSweepsModelUsage(t *testing.T) { // Codex names rollouts by the session_key uuid suffix; the keyed no-window // discovery matches on exactly that. - sessionKey := "019e3e8e-3591-7532-a1ef-8b9e882bea2f" - writeCodexRolloutForSweep(t, codexRoot, workDir, sessionKey, [][3]int{ + sessionKey := codexSweepSessionKey + writeCodexRolloutForSweep(t, codexRoot, workDir, [][3]int{ {150, 100, 50}, // total=150, last input=100, output=50 {450, 200, 100}, // total=450, last input=200, output=100 }) @@ -370,7 +838,7 @@ func TestEmitDueComputeFactsAlsoSweepsModelUsage(t *testing.T) { cr := &CityRuntime{cs: cs, cfg: cfg, sp: runtime.NewFake(), cityName: "demo", cityPath: cityPath, stderr: io.Discard} info := session.Info{ID: b.ID, MetadataState: "asleep", AwakeStartedAt: start.Format(time.RFC3339)} - cr.emitDueComputeFacts(context.Background(), []session.Info{info}) + cr.emitDueComputeFacts(context.Background(), []session.Info{info}, false) facts, warnings, err := usage.ReadFacts(sinkPath) if err != nil { @@ -423,7 +891,7 @@ func TestEmitDueComputeFactsAlsoSweepsModelUsage(t *testing.T) { // A second tick must add no new facts: the cursor blocks the model re-record // and the emit marker blocks the compute re-emit; ReadFacts also dedups any // replay by IdempotencyKey. - cr.emitDueComputeFacts(context.Background(), []session.Info{info}) + cr.emitDueComputeFacts(context.Background(), []session.Info{info}, false) facts2, _, err := usage.ReadFacts(sinkPath) if err != nil { t.Fatalf("ReadFacts (second tick): %v", err) @@ -446,7 +914,7 @@ func TestEmitDueComputeFactsRetriesUnsettledModelSweep(t *testing.T) { workDir := t.TempDir() codexRoot := t.TempDir() sinkPath := filepath.Join(cityPath, ".gc", "usage.jsonl") - sessionKey := "019e3e8e-3591-7532-a1ef-8b9e882bea2f" + sessionKey := codexSweepSessionKey store := beads.NewMemStore() start := time.Date(2026, 6, 15, 10, 0, 0, 0, time.UTC) @@ -480,7 +948,7 @@ func TestEmitDueComputeFactsRetriesUnsettledModelSweep(t *testing.T) { // Tick 1: the rollout is not on disk yet → the sweep misses (transient). The // compute fact still records, but neither the compute marker nor the sweep // marker is stamped, so the interval stays open for retry. - cr.emitDueComputeFacts(context.Background(), []session.Info{info}) + cr.emitDueComputeFacts(context.Background(), []session.Info{info}, false) facts1, _, err := usage.ReadFacts(sinkPath) if err != nil { t.Fatalf("ReadFacts (tick 1): %v", err) @@ -503,14 +971,14 @@ func TestEmitDueComputeFactsRetriesUnsettledModelSweep(t *testing.T) { } // The transcript is flushed to disk between ticks. - writeCodexRolloutForSweep(t, codexRoot, workDir, sessionKey, [][3]int{ + writeCodexRolloutForSweep(t, codexRoot, workDir, [][3]int{ {150, 100, 50}, {450, 200, 100}, }) // Tick 2: the interval is still a candidate → the sweep retries, discovers the // rollout, and recovers the model facts. No duplicate compute fact. - cr.emitDueComputeFacts(context.Background(), []session.Info{info}) + cr.emitDueComputeFacts(context.Background(), []session.Info{info}, false) facts2, _, err := usage.ReadFacts(sinkPath) if err != nil { t.Fatalf("ReadFacts (tick 2): %v", err) @@ -535,7 +1003,7 @@ func TestEmitDueComputeFactsRetriesUnsettledModelSweep(t *testing.T) { // Tick 3: both markers set → no re-Get work, no new facts. info.UsageComputeEmittedAt = awake // reflects the committed interval on the snapshot - cr.emitDueComputeFacts(context.Background(), []session.Info{info}) + cr.emitDueComputeFacts(context.Background(), []session.Info{info}, false) facts3, _, err := usage.ReadFacts(sinkPath) if err != nil { t.Fatalf("ReadFacts (tick 3): %v", err) @@ -545,14 +1013,17 @@ func TestEmitDueComputeFactsRetriesUnsettledModelSweep(t *testing.T) { } } -// writeKeylessCodexRolloutForSweep fabricates a codex rollout at the local-date -// path the codex CLI would use for `at` (session_meta cwd=workDir, a turn_context +// writeCodexRolloutForSweepAt fabricates a codex rollout at the local-date path +// the codex CLI would use for `at` (session_meta cwd=workDir, a turn_context // model, one token_count per {total, lastInput, lastOutput}). Unlike -// writeCodexRolloutForSweep — which hardcodes 2026-06-15 and is reachable by the -// TZ-tolerant keyed lookup — it derives the day dir and filename timestamp from -// `at` in time.Local, so the keyless workdir+window fallback (which parses rollout -// filenames in time.Local) resolves it on any host timezone. -func writeKeylessCodexRolloutForSweep(t *testing.T, root string, at time.Time, workDir, sessionID string, tokenCounts [][3]int) { +// writeCodexRolloutForSweep — which hardcodes 2026-06-15, fine only for a fixture +// whose slept_at also pins the discovery window to that date — it derives BOTH the +// day dir and the filename timestamp from `at` in time.Local, matching how codex +// names rollouts and how discovery parses them. Any test whose discovery window +// runs to the wall clock (a live session has no slept_at) must use this: a +// hardcoded day falls out of the bounded lookback as real time advances, so the +// fixture would silently stop being discoverable. +func writeCodexRolloutForSweepAt(t *testing.T, root string, at time.Time, workDir, sessionID string, tokenCounts [][3]int) { t.Helper() local := at.In(time.Local) dayDir := filepath.Join(root, local.Format("2006"), local.Format("01"), local.Format("02")) @@ -598,7 +1069,7 @@ func TestEmitDueComputeFactsSweepsKeylessCodexViaWorkdir(t *testing.T) { slept := start.Add(90 * time.Second) // A keyless codex rollout in this wisp's unique worktree — no session_key keys // it; only the cwd + interval window resolve it. - writeKeylessCodexRolloutForSweep(t, codexRoot, start, workDir, "019e7777-cccc-7000-8000-000000000009", [][3]int{ + writeCodexRolloutForSweepAt(t, codexRoot, start, workDir, "019e7777-cccc-7000-8000-000000000009", [][3]int{ {150, 100, 50}, {450, 200, 100}, }) @@ -631,7 +1102,7 @@ func TestEmitDueComputeFactsSweepsKeylessCodexViaWorkdir(t *testing.T) { cr := &CityRuntime{cs: cs, cfg: cfg, sp: runtime.NewFake(), cityName: "demo", cityPath: cityPath, stderr: io.Discard} info := session.Info{ID: b.ID, MetadataState: "asleep", AwakeStartedAt: start.Format(time.RFC3339)} - cr.emitDueComputeFacts(context.Background(), []session.Info{info}) + cr.emitDueComputeFacts(context.Background(), []session.Info{info}, false) facts, warnings, err := usage.ReadFacts(sinkPath) if err != nil { diff --git a/cmd/gc/wisp_gc.go b/cmd/gc/wisp_gc.go index f7fc1a371c..8c1905074f 100644 --- a/cmd/gc/wisp_gc.go +++ b/cmd/gc/wisp_gc.go @@ -14,6 +14,7 @@ import ( "github.com/gastownhall/gascity/internal/config" convoycore "github.com/gastownhall/gascity/internal/convoy" "github.com/gastownhall/gascity/internal/mail/beadmail" + "github.com/gastownhall/gascity/internal/molecule" "github.com/gastownhall/gascity/internal/sourceworkflow" ) @@ -165,6 +166,13 @@ func (m *memoryWispGC) runGC(graphStore beads.GraphStore, mailStore beads.MailSt log.Printf("wisp gc: closed %d generated spec sidecars for closed workflow roots", closedSpecs) } + closedMembers, memberErr := closeGeneratedMembersForClosedRoots(store) + if memberErr != nil { + deleteErr = errors.Join(deleteErr, fmt.Errorf("closing generated members for terminal workflow roots: %w", memberErr)) + } else if closedMembers > 0 { + log.Printf("wisp gc: closed %d generated members for terminal workflow roots", closedMembers) + } + // Close abandoned OPEN roots BEFORE the closed-root purge below so a // root the sweep closes this tick can be collected by the purge in the // same tick when it has already aged past m.ttl (the purge gates on @@ -212,6 +220,30 @@ func (m *memoryWispGC) runGC(graphStore beads.GraphStore, mailStore beads.MailSt return purged, deleteErr } +// closeGeneratedMembersForClosedRoots repairs terminal workflow roots whose +// finalizer, supersession, or partial materialization left generated members +// open. Closed roots are the authority boundary: live roots are never listed +// and therefore never touched. Each subtree close is ordered and idempotent. +func closeGeneratedMembersForClosedRoots(store beads.Store) (int, error) { + roots, err := closedWispGCEntries(store) + if err != nil { + return 0, err + } + closed := 0 + var closeErr error + for _, root := range roots { + n, err := molecule.CloseSubtreeWithMetadata(store, root.ID, map[string]string{ + beadmeta.OutcomeMetadataKey: beadmeta.OutcomeSkipped, + "close_reason": sourceworkflow.WorkflowSkippedCloseReason, + }) + closed += n + if err != nil { + closeErr = errors.Join(closeErr, fmt.Errorf("closing terminal workflow subtree %s: %w", root.ID, err)) + } + } + return closed, closeErr +} + // wispGCRootSelector pairs a List selector with a short label used for error // context. The selectors returned by wispGCRootSelectors, unioned, cover every // root class the wisp GC can close or collect. diff --git a/cmd/gc/wisp_gc_test.go b/cmd/gc/wisp_gc_test.go index d23ccda2f5..6938a6391a 100644 --- a/cmd/gc/wisp_gc_test.go +++ b/cmd/gc/wisp_gc_test.go @@ -110,6 +110,57 @@ func TestWispGC_NothingExpired(t *testing.T) { } } +func TestWispGCClosesGeneratedMembersOnlyForTerminalRoots(t *testing.T) { + now := time.Now() + store := newGCStore([]beads.Bead{ + makeGCBeadWithMetadata("completed-root", now.Add(-30*time.Minute), "closed", "task", map[string]string{ + "gc.kind": "workflow", + "gc.formula_contract": "graph.v2", + "gc.outcome": "pass", + }), + makeGCBeadWithMetadata("completed-step", now.Add(-30*time.Minute), "open", "task", map[string]string{ + "gc.root_bead_id": "completed-root", + }), + makeGCBeadWithMetadata("superseded-root", now.Add(-30*time.Minute), "closed", "task", map[string]string{ + "gc.kind": "workflow", + "gc.formula_contract": "graph.v2", + "gc.outcome": "canceled", + }), + makeGCBeadWithMetadata("partial-step", now.Add(-30*time.Minute), "open", "task", map[string]string{ + "gc.root_bead_id": "superseded-root", + }), + makeGCBeadWithMetadata("live-root", now.Add(-30*time.Minute), "in_progress", "task", map[string]string{ + "gc.kind": "workflow", + "gc.formula_contract": "graph.v2", + }), + makeGCBeadWithMetadata("live-step", now.Add(-30*time.Minute), "open", "task", map[string]string{ + "gc.root_bead_id": "live-root", + }), + }) + + wg := newWispGC(5*time.Minute, time.Hour, 0) + if _, err := wg.runGC(beads.GraphStore{Store: store}, beads.MailStore{Store: store}, now); err != nil { + t.Fatalf("runGC: %v", err) + } + + for _, id := range []string{"completed-step", "partial-step"} { + got, err := store.Get(id) + if err != nil { + t.Fatalf("Get(%s): %v", id, err) + } + if got.Status != "closed" || got.Metadata["gc.outcome"] != "skipped" { + t.Fatalf("%s = status %q outcome %q, want closed/skipped", id, got.Status, got.Metadata["gc.outcome"]) + } + } + live, err := store.Get("live-step") + if err != nil { + t.Fatalf("Get(live-step): %v", err) + } + if live.Status != "open" { + t.Fatalf("live-step status = %q, want open", live.Status) + } +} + func TestWispGC_ClosesOpenSpecSidecarsForClosedWorkflowRoots(t *testing.T) { now := time.Now() store := newGCStore([]beads.Bead{ diff --git a/deps.env b/deps.env index 4ea45eefd3..e2dbf62059 100644 --- a/deps.env +++ b/deps.env @@ -39,5 +39,5 @@ BR_VERSION=0.1.20 # BD_CURRENT_REF (a gastownhall/beads commit). Bump BD_CURRENT_REF deliberately, # in lockstep with the vendored corpus, per the coordination protocol. BD_PREV_VERSION=v1.0.4 -BD_CURRENT_VERSION=v1.1.0-rc.1 -BD_CURRENT_REF=8c958d225c8357cd474ea8056c2bd9b2e35d9622 +BD_CURRENT_VERSION=v1.1.1-0.20260805093327-bf97b73749ac +BD_CURRENT_REF=bf97b73749ac3ef2fca2365b54537ac041ad4293 diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 737e180363..db18257a79 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -2714,6 +2714,11 @@ Show execution history for orders. Queries bead history for past order runs. Optionally filter by order name. Use --rig to filter by rig. +The read is bounded by default: only the most recent runs are fetched. +Widen it with --limit (0 fetches every retained run) or bound it by time +with --since. On a city with a long order-run history an unbounded read +costs tens of seconds, so prefer keeping a bound when triaging. + ``` gc order history [name] [flags] ``` @@ -2721,7 +2726,9 @@ gc order history [name] [flags] | Flag | Type | Default | Description | |------|------|---------|-------------| | `--json` | bool | | output JSONL summary | +| `--limit` | int | `50` | maximum runs to show (0 = every retained run) | | `--rig` | string | | rig name to filter order history | +| `--since` | string | | only show runs from within this duration ago (e.g. 1h, 24h) | ## gc order list @@ -2818,12 +2825,18 @@ subtrees whose open descendants are also older than --stale-after. Pass one or more scoped order names when --include-wisps is set; wisp recovery is order-scoped to avoid scanning unrelated beads. +When the number of eligible closed-bead deletions exceeds +GC_BULK_DELETE_CONFIRM_THRESHOLD (default 20), --confirm is required to +proceed. This guard prevents accidental mass-deletes without an explicit +operator acknowledgement. + ``` gc order sweep-tracking [order ...] [flags] ``` | Flag | Type | Default | Description | |------|------|---------|-------------| +| `--confirm` | bool | | confirm bulk deletion when eligible count > GC_BULK_DELETE_CONFIRM_THRESHOLD (default 20) | | `--dry-run` | bool | | report stale order-tracking and order wisp beads without closing them | | `--include-wisps` | bool | | also close stale order-run wisp subtrees with open descendants | | `--quiet` | bool | | suppress success output | diff --git a/docs/reference/schema/openapi.json b/docs/reference/schema/openapi.json index f6f337060b..4000245af2 100644 --- a/docs/reference/schema/openapi.json +++ b/docs/reference/schema/openapi.json @@ -12200,7 +12200,9 @@ "emergency.acked": "#/components/schemas/TypedEventStreamEnvelopeEmergencyAcked", "emergency.signaled": "#/components/schemas/TypedEventStreamEnvelopeEmergencySignaled", "events.rotated": "#/components/schemas/TypedEventStreamEnvelopeEventsRotated", + "execution.step_completed": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepCompleted", "execution.step_defined": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepDefined", + "execution.step_started": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepStarted", "execution.work_associated": "#/components/schemas/TypedEventStreamEnvelopeExecutionWorkAssociated", "extmsg.adapter_added": "#/components/schemas/TypedEventStreamEnvelopeExtmsgAdapterAdded", "extmsg.adapter_removed": "#/components/schemas/TypedEventStreamEnvelopeExtmsgAdapterRemoved", @@ -12339,9 +12341,15 @@ { "$ref": "#/components/schemas/TypedEventStreamEnvelopeEventsRotated" }, + { + "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepCompleted" + }, { "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepDefined" }, + { + "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepStarted" + }, { "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionWorkAssociated" }, @@ -13692,6 +13700,8 @@ "bead.dead_assignee_reopened", "execution.work_associated", "execution.step_defined", + "execution.step_started", + "execution.step_completed", "mail.sent", "mail.read", "mail.archived", @@ -14001,6 +14011,63 @@ "title": "TypedEventStreamEnvelope events.rotated", "type": "object" }, + "TypedEventStreamEnvelopeExecutionStepCompleted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_completed", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload" + ], + "title": "TypedEventStreamEnvelope execution.step_completed", + "type": "object" + }, "TypedEventStreamEnvelopeExecutionStepDefined": { "additionalProperties": false, "properties": { @@ -14058,6 +14125,63 @@ "title": "TypedEventStreamEnvelope execution.step_defined", "type": "object" }, + "TypedEventStreamEnvelopeExecutionStepStarted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_started", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload" + ], + "title": "TypedEventStreamEnvelope execution.step_started", + "type": "object" + }, "TypedEventStreamEnvelopeExecutionWorkAssociated": { "additionalProperties": false, "properties": { @@ -17790,7 +17914,9 @@ "emergency.acked": "#/components/schemas/TypedTaggedEventStreamEnvelopeEmergencyAcked", "emergency.signaled": "#/components/schemas/TypedTaggedEventStreamEnvelopeEmergencySignaled", "events.rotated": "#/components/schemas/TypedTaggedEventStreamEnvelopeEventsRotated", + "execution.step_completed": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepCompleted", "execution.step_defined": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepDefined", + "execution.step_started": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepStarted", "execution.work_associated": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionWorkAssociated", "extmsg.adapter_added": "#/components/schemas/TypedTaggedEventStreamEnvelopeExtmsgAdapterAdded", "extmsg.adapter_removed": "#/components/schemas/TypedTaggedEventStreamEnvelopeExtmsgAdapterRemoved", @@ -17929,9 +18055,15 @@ { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeEventsRotated" }, + { + "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepCompleted" + }, { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepDefined" }, + { + "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepStarted" + }, { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionWorkAssociated" }, @@ -19361,6 +19493,8 @@ "bead.dead_assignee_reopened", "execution.work_associated", "execution.step_defined", + "execution.step_started", + "execution.step_completed", "mail.sent", "mail.read", "mail.archived", @@ -19687,6 +19821,67 @@ "title": "TypedTaggedEventStreamEnvelope events.rotated", "type": "object" }, + "TypedTaggedEventStreamEnvelopeExecutionStepCompleted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "city": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_completed", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload", + "city" + ], + "title": "TypedTaggedEventStreamEnvelope execution.step_completed", + "type": "object" + }, "TypedTaggedEventStreamEnvelopeExecutionStepDefined": { "additionalProperties": false, "properties": { @@ -19748,6 +19943,67 @@ "title": "TypedTaggedEventStreamEnvelope execution.step_defined", "type": "object" }, + "TypedTaggedEventStreamEnvelopeExecutionStepStarted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "city": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_started", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload", + "city" + ], + "title": "TypedTaggedEventStreamEnvelope execution.step_started", + "type": "object" + }, "TypedTaggedEventStreamEnvelopeExecutionWorkAssociated": { "additionalProperties": false, "properties": { diff --git a/docs/reference/schema/openapi.txt b/docs/reference/schema/openapi.txt index f6f337060b..4000245af2 100644 --- a/docs/reference/schema/openapi.txt +++ b/docs/reference/schema/openapi.txt @@ -12200,7 +12200,9 @@ "emergency.acked": "#/components/schemas/TypedEventStreamEnvelopeEmergencyAcked", "emergency.signaled": "#/components/schemas/TypedEventStreamEnvelopeEmergencySignaled", "events.rotated": "#/components/schemas/TypedEventStreamEnvelopeEventsRotated", + "execution.step_completed": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepCompleted", "execution.step_defined": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepDefined", + "execution.step_started": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepStarted", "execution.work_associated": "#/components/schemas/TypedEventStreamEnvelopeExecutionWorkAssociated", "extmsg.adapter_added": "#/components/schemas/TypedEventStreamEnvelopeExtmsgAdapterAdded", "extmsg.adapter_removed": "#/components/schemas/TypedEventStreamEnvelopeExtmsgAdapterRemoved", @@ -12339,9 +12341,15 @@ { "$ref": "#/components/schemas/TypedEventStreamEnvelopeEventsRotated" }, + { + "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepCompleted" + }, { "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepDefined" }, + { + "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepStarted" + }, { "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionWorkAssociated" }, @@ -13692,6 +13700,8 @@ "bead.dead_assignee_reopened", "execution.work_associated", "execution.step_defined", + "execution.step_started", + "execution.step_completed", "mail.sent", "mail.read", "mail.archived", @@ -14001,6 +14011,63 @@ "title": "TypedEventStreamEnvelope events.rotated", "type": "object" }, + "TypedEventStreamEnvelopeExecutionStepCompleted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_completed", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload" + ], + "title": "TypedEventStreamEnvelope execution.step_completed", + "type": "object" + }, "TypedEventStreamEnvelopeExecutionStepDefined": { "additionalProperties": false, "properties": { @@ -14058,6 +14125,63 @@ "title": "TypedEventStreamEnvelope execution.step_defined", "type": "object" }, + "TypedEventStreamEnvelopeExecutionStepStarted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_started", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload" + ], + "title": "TypedEventStreamEnvelope execution.step_started", + "type": "object" + }, "TypedEventStreamEnvelopeExecutionWorkAssociated": { "additionalProperties": false, "properties": { @@ -17790,7 +17914,9 @@ "emergency.acked": "#/components/schemas/TypedTaggedEventStreamEnvelopeEmergencyAcked", "emergency.signaled": "#/components/schemas/TypedTaggedEventStreamEnvelopeEmergencySignaled", "events.rotated": "#/components/schemas/TypedTaggedEventStreamEnvelopeEventsRotated", + "execution.step_completed": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepCompleted", "execution.step_defined": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepDefined", + "execution.step_started": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepStarted", "execution.work_associated": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionWorkAssociated", "extmsg.adapter_added": "#/components/schemas/TypedTaggedEventStreamEnvelopeExtmsgAdapterAdded", "extmsg.adapter_removed": "#/components/schemas/TypedTaggedEventStreamEnvelopeExtmsgAdapterRemoved", @@ -17929,9 +18055,15 @@ { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeEventsRotated" }, + { + "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepCompleted" + }, { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepDefined" }, + { + "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepStarted" + }, { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionWorkAssociated" }, @@ -19361,6 +19493,8 @@ "bead.dead_assignee_reopened", "execution.work_associated", "execution.step_defined", + "execution.step_started", + "execution.step_completed", "mail.sent", "mail.read", "mail.archived", @@ -19687,6 +19821,67 @@ "title": "TypedTaggedEventStreamEnvelope events.rotated", "type": "object" }, + "TypedTaggedEventStreamEnvelopeExecutionStepCompleted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "city": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_completed", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload", + "city" + ], + "title": "TypedTaggedEventStreamEnvelope execution.step_completed", + "type": "object" + }, "TypedTaggedEventStreamEnvelopeExecutionStepDefined": { "additionalProperties": false, "properties": { @@ -19748,6 +19943,67 @@ "title": "TypedTaggedEventStreamEnvelope execution.step_defined", "type": "object" }, + "TypedTaggedEventStreamEnvelopeExecutionStepStarted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "city": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_started", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload", + "city" + ], + "title": "TypedTaggedEventStreamEnvelope execution.step_started", + "type": "object" + }, "TypedTaggedEventStreamEnvelopeExecutionWorkAssociated": { "additionalProperties": false, "properties": { diff --git a/docs/tutorials/07-orders.md b/docs/tutorials/07-orders.md index 56aa4d0d89..c809d05e75 100644 --- a/docs/tutorials/07-orders.md +++ b/docs/tutorials/07-orders.md @@ -391,6 +391,18 @@ closed. Orders whose dispatch is safe to repeat (sweeps and feeders where a duplicate run is a no-op) can set `idempotent = true` to fail open instead: on a gate timeout they dispatch anyway rather than starve. +A third option exists for orders that consume **no bead work at all** — pure +probes and sweeps that track nothing. `no_work_gate = true` skips the open-work +gate *entirely*; the dispatcher never issues the store read, so a slow store +cannot time it out and skip the order. The canonical case is +`provider-health-probe`, a cooldown probe whose only job is to refresh a health +cache; under store contention its gate timed out every cycle and the cache went +stale (#2893). `no_work_gate` and `idempotent` are distinct: `idempotent` +*enters* the gate but fails open on timeout, while `no_work_gate` never enters +it. Use `no_work_gate` only when the order genuinely tracks no beads — it +disables single-flight protection, so the order must be self-idempotent or +interval-bounded to guard against overlapping re-runs. + ## Rig-scoped orders When a pack is applied to a rig, that pack's orders come along and run scoped to diff --git a/engdocs/design/session-model-unification.md b/engdocs/design/session-model-unification.md index 5a6922e8f6..d8faf6203e 100644 --- a/engdocs/design/session-model-unification.md +++ b/engdocs/design/session-model-unification.md @@ -655,6 +655,7 @@ matches the unified model: - `GC_TEMPLATE` = qualified backing agent-config identity - `GC_SESSION_ORIGIN` = `named`, `ephemeral`, or `manual` - `GC_AGENT` = temporary compatibility alias for the public handle only +- `BEADS_ACTOR` = exact ownership string the running session presents to `bd` New prompt and hook logic should key config semantics off `GC_TEMPLATE` and lifecycle semantics off `GC_SESSION_ORIGIN`, not off `GC_AGENT`. @@ -664,8 +665,8 @@ and lifecycle semantics off `GC_SESSION_ORIGIN`, not off `GC_AGENT`. | Origin | `configured_named_identity` | `alias` | `session_name` | `GC_ALIAS` | `GC_AGENT` | |---|---|---|---|---|---| | `named` | present; immutable fully qualified named identity | always equals `configured_named_identity` while config-managed | deterministic runtime handle derived from the named identity and workspace naming policy | same as `alias` | same as `alias` | -| `ephemeral` | absent | optional, mutable if non-conflicting | opaque runtime handle | alias if present | alias if present, otherwise `session_name` | -| `manual` | absent | optional, mutable if non-conflicting | opaque runtime handle | alias if present | alias if present, otherwise `session_name` | +| `ephemeral` | absent | optional, mutable if non-conflicting | opaque runtime handle | alias if present | alias if present; otherwise raw `session_name`, or bead ID when name metadata is absent | +| `manual` | absent | optional, mutable if non-conflicting | opaque runtime handle | alias if present | alias if present; otherwise raw `session_name`, or bead ID when name metadata is absent | Configured named sessions do not carry a second mutable runtime alias separate from their configured identity. @@ -685,12 +686,37 @@ Phase 1 `GC_AGENT` contract is exact: - `named`: identical to `GC_ALIAS`, which is the configured named identity -- `ephemeral` and `manual`: `GC_ALIAS` if present, otherwise - `GC_SESSION_NAME` +- `ephemeral` and `manual`: `GC_ALIAS` if present, otherwise raw persisted + `session_name`, falling back to the session bead ID when name metadata is absent No Phase 1 path may interpret `GC_AGENT` as backing config identity, factory target, or durable ownership token. +### Transitional ownership projection + +The canonical persistence target remains `assignee=` as +specified in [Ownership and Routing](#ownership-and-routing). Until that +migration reaches every ownership writer and prompt, GC-owned compatibility +paths must keep the stored assignee and the runtime actor byte-identical. They +select the current ownership string in this order: + +1. current `alias` +2. `configured_named_identity` for a recovered named session whose alias is + temporarily absent +3. raw persisted `session_name` +4. session bead ID when no name metadata exists + +`BEADS_ACTOR`, API assignment normalization, hook claims, and scripted claims +must all use that selector. `GC_AGENT` mirrors the selected value only for +compatibility; new ownership logic reads `BEADS_ACTOR` or the typed session +projection rather than treating `GC_AGENT` as a durable field. + +Runtime metadata updates do not rewrite the environment of an already-running +agent process. Deploying a change to this projection therefore requires those +sessions to restart before direct `bd` commands inherit the new actor. Metadata +synchronization keeps provider state coherent for subsequent launches; it is +not a live-process migration. + ## Materialization Rules ### Named Sessions diff --git a/engdocs/plans/vp-cixi.6-drop-open-work-gate-for-gateless-cooldown-probes.md b/engdocs/plans/vp-cixi.6-drop-open-work-gate-for-gateless-cooldown-probes.md new file mode 100644 index 0000000000..f518ca528c --- /dev/null +++ b/engdocs/plans/vp-cixi.6-drop-open-work-gate-for-gateless-cooldown-probes.md @@ -0,0 +1,178 @@ +# vp-cixi.6 — Drop the open-work gate for gate-less cooldown probes + +Bead: vp-cixi.6 (child of EPIC vp-cixi). Root cause (GAP D from vp-cixi.5): +`provider-health-probe` is a pure cooldown probe that tracks NO beads, yet the +dispatcher runs two open-work gates for it per tick (`hasOpenTracking` then +`hasOpenWork`), each issuing `bd list` / `bd query` reads against Dolt and +bounded by `orderGateTimeout` (8s). On store slowness the gate times out and +`gateFailClosed` SKIPS the order every cycle → the provider-health cache goes +stale → fail-closed provider health → failover can't pick claude2/anything. +Confirmed live: 60–90+min gaps between probe runs despite a 10m interval. + +A/B/C (PR #357) shipped a mitigation (hysteresis + wider TTL) that absorbs the +skips. This plan is the deeper fix in gc-core (gascity): let an order OPT OUT +of the open-work gates entirely, since they are meaningless for orders that +consume no bead work. Same class as the decision-sweep rig-enum starvation. + +## Approach + +Add an order-level opt-out flag `no_work_gate` (Go `Order.NoWorkGate`). When +`true`, the dispatcher skips BOTH open-work gates (`hasOpenTracking` and +`hasOpenWork`) for that order — no `gateOpenWorkBounded` call, no Dolt reads, +no fail-closed skip, no gate-timeout backoff. The order still respects its own +trigger (cooldown interval) and per-order exec timeout; single-flight for these +orders is naturally bounded by the cooldown interval + the synchronous +tracking-bead the dispatcher creates before launch (which still happens). + +Why a new flag, not reusing `Idempotent`: +- `Idempotent` changes semantics to fail-OPEN on timeout (may double-dispatch). + A gate-less probe should not even *enter* the gate — it must not depend on a + Dolt read completing inside 8s, and it should never emit + `order.gate_timeout_fail_open`. The two properties ("safe to re-run" vs + "consumes no bead work") are distinct; conflating them would make a probe's + dispatch contingent on store health, which is exactly the bug. + +**Layer split (2026-07-05 re-plan, after the executor flagged the cross-layer +blocker in T-003):** the gc-core mechanism — flag + decode + dispatcher +gate-skip + end-to-end regression — all ships from **gascity** (T-001/T-002, +done green; T-003 parse test + T-004 docs remain, both gascity-self-contained). +Activating the flag on the live probe is a **separate deployed-pack-layer +edit** (`packs/voxist-city/orders/provider-health-probe.toml`, which is NOT a +file tracked in gascity or any voxist rig repo — see S-1). Per the +one-bead-per-plan / plan-ends-at-the-boundary rule, that activation is sling +S-1, not a micro-task. The gc-core PR is valuable and mergeable on its own: +it ships the opt-out mechanism + tests; the pack flip turns it on for the one +order that needs it today. + +## GDPR data-flow impact + +No data-flow impact. The change alters *dispatch scheduling* (which gate +checks run for an order), not what data the order reads, processes, or +persists. `provider-health-probe` already runs unchanged; `NoWorkGate` only +removes the redundant open-work gate reads (which themselves only read bead +*status*, not personal data) from its dispatch path. No new PII is accessed, +stored, transmitted, or retained. No data subject, retention period, or +export path is affected. + +## MDR Class I traceability + +No-op. This change is entirely outside the voxmemo→voxist-api clinical +documentation pipeline (chain-of-evidence from microphone to exported +clinical note). It touches gc-core dispatch scheduling only; no clinical +recording, transcription, or documentation artifact is created, modified, or +re-routed. The heading is retained per the writing-plan discipline so an +auditor sees the explicit consideration. + +## Micro-tasks (TDD, red/green/refactor/commit-on-green) + +### T-001 — Order model: add `NoWorkGate` field + TOML decode + validation guard +- **acceptance**: `TestOrderNoWorkGateParsed` — an order TOML with + `no_work_gate = true` decodes to `Order.NoWorkGate == true`; default is + `false`. Also assert `Validate` accepts it (no extra constraint). +- **files**: `internal/orders/order.go` (struct field + `orderDecode` + + `normalized()`), test in `internal/orders/order_test.go`. +- commit: `feat(orders): T-001 add Order.NoWorkGate opt-out flag — green at TestOrderNoWorkGateParsed` + +### T-002 — Dispatcher: skip both gates when `NoWorkGate` +- **acceptance**: `TestOrderDispatchNoWorkGateSkipsGatesUnderStoreDelay` — + with `orderGateTimeout` shortened and a store whose gate queries sleep past + it, an order with `NoWorkGate: true` STILL dispatches (creates a tracking + bead) and records ZERO gate query calls; a plain order is skipped as before. +- **files**: `cmd/gc/order_dispatch.go` (guard the two `gateOpenWorkBounded` + call sites + the `gateBackoffActive` short-circuit so backoff is irrelevant + when the gate never runs). +- commit: `fix(dispatch): T-002 skip open-work gates for NoWorkGate orders — green at TestOrderDispatchNoWorkGateSkipsGatesUnderStoreDelay` + +### T-003 — Parse test: provider-health-probe-shaped order opts out (gascity-self-contained) +- **acceptance**: `TestProviderHealthProbeOrderOptsOutOfWorkGate` — a TOML + literal shaped like the shipped provider-health-probe order (cooldown + trigger, 10m interval, real `exec` + 120s timeout) WITH `no_work_gate = true` + parses via `orders.Parse` to `Order.NoWorkGate == true` and passes + `Validate`; the same TOML WITHOUT the flag parses to `false`. Mirrors the + `TestOrderNoWorkGateParsed` house style (inline TOML literal → `Parse`, + no cross-tree file reach). +- **files**: test only — `internal/orders/order_test.go`. No source change + (the field/decode landed in T-001). +- **why not edit the shipped pack here**: the live + `packs/voxist-city/orders/provider-health-probe.toml` is a *deployed + city pack-store artifact*, not a file tracked in the gascity repo or in any + voxist rig repo reachable from this session (voxist-platform/api/web have + zero matching tracked files; voxist-city itself is not a git repo; the only + local copy is `.pr337-fetch/`). Reaching across into that layer from a + gascity test would be machine-specific and break CI. The pack-flag flip is + filed as the cross-layer sling below (S-1) and is NOT a micro-task in this + plan — per the one-bead-per-plan / plan-ends-at-the-boundary rule. +- commit: `test(orders): T-003 provider-health-probe-shaped order opts out of work gate — green at TestProviderHealthProbeOrderOptsOutOfWorkGate` + +### T-004 — Docs: order-author guide note for `no_work_gate` +- **acceptance**: a docs note exists describing when to set `no_work_gate` + (pure probes/sweeps that track no beads) and the warning that it disables + single-flight protection, so the order must be self-idempotent or + interval-bounded. The note names provider-health-probe as the canonical + example and cross-references sling S-1 (the pack flip that activates it). +- **files**: `docs/tutorials/07-orders.md` (nearest order-author reference — + `docs/guides/orders.md` does not exist; the base-`Order` TOML fields are + documented in the orders tutorial's "Duplicate prevention" section, next to + the sibling `idempotent` flag, which is the correct conceptual neighborhood + for the third gate-behavior option). +- commit: `docs(orders): T-004 document no_work_gate opt-out` + +## Cross-layer slings (plan ends at the boundary) + +The gc-core mechanism (T-001/T-002) ships from gascity. Activating it for the +live probe requires flipping the flag on the deployed pack — a different layer +(pack store, not a git repo here). That is sling S-1, NOT a micro-task. + +### S-1 — Flip `no_work_gate = true` on the deployed provider-health-probe pack +- **owning layer**: deployed city pack store — + `packs/voxist-city/orders/provider-health-probe.toml` (the order TOML that + sits next to `packs/voxist-city/bin/provider-health-probe`; see vp-cixi.5 + GAP D for the path). This is a city/pack-layer config edit, not a rig-repo + code edit; the bead should be filed in whichever rig owns the deployed + pack tree and routed to that rig's executor. +- **change**: add `no_work_gate = true` to the `[order]` table (one line), + alongside the existing `trigger = "cooldown"` / `interval = "10m"` / + `timeout = "120s"`. +- **acceptance**: after deploy, `provider-health-probe` dispatches on its + 10m cooldown even when the Dolt store is slow enough to time out the + open-work gate for other orders (the #2893 starvation this whole bead + fixes). Verifiable in `supervisor.log`: no more + `open-work gate for provider-health-probe timed out ... skipping this order` + lines, and provider-health cache refresh gaps return to ~10m. +- **sling-ready bead text**: + ``` + Title: pack: set no_work_gate=true on provider-health-probe (activates vp-cixi.6) + Body: Flip `no_work_gate = true` on the [order] table of the deployed + packs/voxist-city/orders/provider-health-probe.toml. This activates the + gc-core NoWorkGate opt-out (vp-cixi.6, PR ) so the probe stops being + skipped every cycle when the Dolt store is slow (#2893 dispatch starvation + -> stale provider-health cache -> fail-closed health -> failover can't pick + claude2). Depends on vp-cixi.6 merging first (the flag is a no-op without + the gc-core mechanism). One-line config edit; verify via supervisor.log + (no more gate-timeout-skip lines for provider-health-probe; cache refresh + gaps back to ~10m). Same pack layer as the vc-flh.5 probe impl. + Labels: gc.pack, provider-health, failover. Blocks: none. Blocked-by: vp-cixi.6. + ``` + +## Status + +- [x] T-001 — Order model: add NoWorkGate field + TOML decode + validation guard ✅ green at 415429c91 +- [x] T-002 — Dispatcher: skip both gates when NoWorkGate ✅ green at TestOrderDispatchNoWorkGateSkipsGatesUnderStoreDelay (6612e768c) +- [x] T-003 — Parse test: provider-health-probe-shaped order opts out (gascity-self-contained) ✅ green at TestProviderHealthProbeOrderOptsOutOfWorkGate (bd0ff6b40) +- [x] T-004 — Docs: order-author guide note for `no_work_gate` ✅ green at docs(orders): T-004 document no_work_gate opt-out (45a3548fa) +- [ ] S-1 (sling, NOT a micro-task) — Flip `no_work_gate = true` on the deployed pack ← cross-layer, separate bead (file after PR merges) + +**Re-plan note (2026-07-05):** original T-003 reached across into the deployed +pack layer (a non-repo artifact) and was unexecutable from gascity. T-003 is +now a gascity-self-contained parse test (house style: inline TOML → `Parse`); +the pack-flag flip moved to sling S-1. T-001/T-002 are unchanged and green. +The gc-core PR (T-001/T-002/T-003/T-004) is mergeable independently of S-1. + +**Completion note (2026-07-05):** all four gc-core micro-tasks are green on +branch `gc/vp-cixi.6`. T-003 was a parse-only test (the field/decode landed in +T-001), so it went green on first run — no source change needed, matching the +re-planned "test only" scope. T-004 landed in `docs/tutorials/07-orders.md` +(no `docs/guides/orders.md` exists; the base-`Order` TOML fields live in the +orders tutorial, and the "Duplicate prevention" section is the correct home +next to the `idempotent` sibling). The pack activation (S-1) remains a +separate cross-layer bead to file once this PR merges. diff --git a/go.mod b/go.mod index f1a45347ca..84f941588f 100644 --- a/go.mod +++ b/go.mod @@ -9,34 +9,34 @@ require ( github.com/fsnotify/fsnotify v1.10.1 github.com/gastownhall/gascity-packs v0.3.1-0.20260617013242-33d3a430a67d github.com/go-jose/go-jose/v4 v4.1.4 - github.com/go-sql-driver/mysql v1.9.3 + github.com/go-sql-driver/mysql v1.10.0 github.com/golang-jwt/jwt/v5 v5.3.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 - github.com/invopop/jsonschema v0.13.0 + github.com/invopop/jsonschema v0.14.0 github.com/oapi-codegen/runtime v1.4.0 github.com/pb33f/libopenapi v0.36.1 github.com/pb33f/libopenapi-validator v0.13.4 github.com/rogpeppe/go-internal v1.14.1 github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 - github.com/shirou/gopsutil/v4 v4.26.3 + github.com/shirou/gopsutil/v4 v4.26.5 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/steveyegge/beads v1.1.1-0.20260704062855-e97839a2e1c0 github.com/stretchr/testify v1.11.1 - go.opentelemetry.io/otel v1.43.0 + go.opentelemetry.io/otel v1.44.0 go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0 go.opentelemetry.io/otel/log v0.19.0 - go.opentelemetry.io/otel/metric v1.43.0 - go.opentelemetry.io/otel/sdk v1.43.0 + go.opentelemetry.io/otel/metric v1.44.0 + go.opentelemetry.io/otel/sdk v1.44.0 go.opentelemetry.io/otel/sdk/log v0.19.0 - go.opentelemetry.io/otel/sdk/metric v1.43.0 + go.opentelemetry.io/otel/sdk/metric v1.44.0 golang.org/x/mod v0.37.0 - golang.org/x/sync v0.21.0 - golang.org/x/sys v0.46.0 - golang.org/x/term v0.44.0 + golang.org/x/sync v0.22.0 + golang.org/x/sys v0.47.0 + golang.org/x/term v0.45.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.35.2 k8s.io/apimachinery v0.35.2 @@ -54,7 +54,7 @@ require ( cloud.google.com/go/iam v1.5.2 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect cloud.google.com/go/storage v1.50.0 // indirect - filippo.io/edwards25519 v1.1.1 // indirect + filippo.io/edwards25519 v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect @@ -104,17 +104,17 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/denisbrodbeck/machineid v1.0.1 // indirect github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12 // indirect - github.com/dolthub/dolt/go v0.40.5-0.20260605230755-1bf533220ab0 // indirect - github.com/dolthub/driver/v2 v2.1.4 // indirect + github.com/dolthub/dolt/go v0.40.5-0.20260715172757-a6690826d767 // indirect + github.com/dolthub/driver/v2 v2.2.0 // indirect github.com/dolthub/eventsapi_schema v0.0.0-20260310172945-37a9265ade69 // indirect github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 // indirect github.com/dolthub/fslock v0.0.5 // indirect - github.com/dolthub/go-icu-regex v0.0.0-20260412212219-49724d547866 // indirect - github.com/dolthub/go-mysql-server v0.20.1-0.20260605175459-433dbaebc97f // indirect + github.com/dolthub/go-icu-regex v0.0.0-20260610153742-72563bc7ca83 // indirect + github.com/dolthub/go-mysql-server v0.20.1-0.20260713210757-6d01d00bbbf3 // indirect github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 // indirect github.com/dolthub/ishell v0.0.0-20260414231531-5f031e3e9037 // indirect github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 // indirect - github.com/dolthub/vitess v0.0.0-20260604210335-0893abc80542 // indirect + github.com/dolthub/vitess v0.0.0-20260624214226-81d034e0fde8 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/ebitengine/purego v0.10.0 // indirect github.com/edsrzf/mmap-go v1.2.0 // indirect @@ -145,7 +145,7 @@ require ( github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect github.com/googleapis/gax-go/v2 v2.14.2 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -156,12 +156,12 @@ require ( github.com/klauspost/compress v1.18.5 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/lestrrat-go/strftime v1.0.6 // indirect + github.com/lestrrat-go/strftime v1.2.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect github.com/mattn/go-runewidth v0.0.23 // indirect github.com/moby/spdystream v0.5.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -203,7 +203,6 @@ require ( github.com/tklauser/go-sysconf v0.3.16 // indirect github.com/tklauser/numcpus v0.11.0 // indirect github.com/vbauerster/mpb/v8 v8.7.2 // indirect - github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xitongsys/parquet-go v1.6.2 // indirect github.com/xitongsys/parquet-go-source v0.0.0-20240122235623-d6294584ab18 // indirect @@ -214,7 +213,7 @@ require ( go.opentelemetry.io/contrib/detectors/gcp v1.43.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect @@ -232,8 +231,8 @@ require ( golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/api v0.241.0 // indirect google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect google.golang.org/grpc v1.82.1 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect diff --git a/go.sum b/go.sum index c6720db3e7..988497378f 100644 --- a/go.sum +++ b/go.sum @@ -93,8 +93,8 @@ contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0Wk dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= -filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= +filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1 h1:LNhjNn8DerC8f9DHLz6lS0YYul/b602DUxDgGkd/Aik= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= @@ -382,28 +382,28 @@ github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12 h1:I github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12/go.mod h1:rN7X8BHwkjPcfMQQ2QTAq/xM3leUSGLfb+1Js7Y6TVo= github.com/dolthub/dolt-mcp v0.3.4 h1:AyG5cw+fNWXDHXujtQnqUPZrpWtPg6FN6yYtjv1pP44= github.com/dolthub/dolt-mcp v0.3.4/go.mod h1:bCZ7KHvDYs+M0e+ySgmGiNvLhcwsN7bbf5YCyillLrk= -github.com/dolthub/dolt/go v0.40.5-0.20260605230755-1bf533220ab0 h1:oPg5f5bYFy5x7Ws2qtVG7wiva96cIh9SFg7nrC4n7QA= -github.com/dolthub/dolt/go v0.40.5-0.20260605230755-1bf533220ab0/go.mod h1:XwB+rt1QwszYYQIqFzIh6GyI5wUCWsmcgmGC/noAEcc= -github.com/dolthub/driver/v2 v2.1.4 h1:0x3FoR9Aq75wd5sWSnWoaYKMusjYOsDn4zj2zl5hbQk= -github.com/dolthub/driver/v2 v2.1.4/go.mod h1:9banWL0wE+Xmu4+c7Ukukyrx+H6BiI668Ok7e/SZBwo= +github.com/dolthub/dolt/go v0.40.5-0.20260715172757-a6690826d767 h1:RSO4YZ5xuZ2EnHv813q2q+QpEqDW1ugjRepPXyDvb7s= +github.com/dolthub/dolt/go v0.40.5-0.20260715172757-a6690826d767/go.mod h1:DXkKITEIpR85Ta86AyjAXYeTULr/tRylidxxy95eraI= +github.com/dolthub/driver/v2 v2.2.0 h1:Qm9BhvvKNmeTDF6kZdDkdLe62CF1W6GrCA3ZDRx/tlk= +github.com/dolthub/driver/v2 v2.2.0/go.mod h1:Ngki9vM88/sqin1RKfUt/9Ex8DmoePtHgY7d4+YoolU= github.com/dolthub/eventsapi_schema v0.0.0-20260310172945-37a9265ade69 h1:JShhbqMw26nKx3pqqu/cFxOpzBkN+4elVhzuUfgDw2k= github.com/dolthub/eventsapi_schema v0.0.0-20260310172945-37a9265ade69/go.mod h1:SSLraQS/jGLYFgff3vuZ+JbVUct6vyEeMzjLBqWqoyM= github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 h1:u3PMzfF8RkKd3lB9pZ2bfn0qEG+1Gms9599cr0REMww= github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2/go.mod h1:mIEZOHnFx4ZMQeawhw9rhsj+0zwQj7adVsnBX7t+eKY= github.com/dolthub/fslock v0.0.5 h1:QoXhBhgY1oumHE26qyE7tgmXUT8qjJwxsIzo54O/B/k= github.com/dolthub/fslock v0.0.5/go.mod h1:sdofYYqE0D79zNZyB4/kmlnsQOVap1C2yByjGKSirEM= -github.com/dolthub/go-icu-regex v0.0.0-20260412212219-49724d547866 h1:U6gSf5I0e6h6GP1/5Sa7D2lWW1CWfcVPtY5wkyHq6jY= -github.com/dolthub/go-icu-regex v0.0.0-20260412212219-49724d547866/go.mod h1:F3cnm+vMRK1HaU6+rNqQrOCyR03HHhR1GWG2gnPOqaE= -github.com/dolthub/go-mysql-server v0.20.1-0.20260605175459-433dbaebc97f h1:PPoA77XT2bavse3t02jcPsSQOZ1vToN13EgiaYed9IE= -github.com/dolthub/go-mysql-server v0.20.1-0.20260605175459-433dbaebc97f/go.mod h1:A3nEC4RgBm9UzuQCGhQhJDQAiFMPsZU3NPKbGhEd8R4= +github.com/dolthub/go-icu-regex v0.0.0-20260610153742-72563bc7ca83 h1:FEMjCGEroDnY/BXyAffVZxUpXhP2GpoUJyyq5KaLn8c= +github.com/dolthub/go-icu-regex v0.0.0-20260610153742-72563bc7ca83/go.mod h1:F3cnm+vMRK1HaU6+rNqQrOCyR03HHhR1GWG2gnPOqaE= +github.com/dolthub/go-mysql-server v0.20.1-0.20260713210757-6d01d00bbbf3 h1:HdPnbDFCkxyEU1zDHVPcHq8aWFkar3fIz9I9Wz5cC0E= +github.com/dolthub/go-mysql-server v0.20.1-0.20260713210757-6d01d00bbbf3/go.mod h1:AnD2jKQZCf09sM2JhV/cTEtsoEhPNg6pVWjRCBox4Zw= github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 h1:OAsXLAPL4du6tfbBgK0xXHZkOlos63RdKYS3Sgw/dfI= github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63/go.mod h1:lV7lUeuDhH5thVGDCKXbatwKy2KW80L4rMT46n+Y2/Q= github.com/dolthub/ishell v0.0.0-20260414231531-5f031e3e9037 h1:oIW9HwuWrhxv+4HZxA+QQSKHLqWFyXZ2FmNjUYwkdiM= github.com/dolthub/ishell v0.0.0-20260414231531-5f031e3e9037/go.mod h1:ehexgi1mPxRTk0Mok/pADALuHbvATulTh6gzr7NzZto= github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 h1:bMGS25NWAGTEtT5tOBsCuCrlYnLRKpbJVJkDbrTRhwQ= github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71/go.mod h1:2/2zjLQ/JOOSbbSboojeg+cAwcRV0fDLzIiWch/lhqI= -github.com/dolthub/vitess v0.0.0-20260604210335-0893abc80542 h1:0A5Y1IP9ribdYzzWDZwN/NM+oxCfmYh7NuM2xIIrEag= -github.com/dolthub/vitess v0.0.0-20260604210335-0893abc80542/go.mod h1:dKAkzdfRkAudpc0g8JOQ0eiEjV83TYIFz/yNIEdcjXM= +github.com/dolthub/vitess v0.0.0-20260624214226-81d034e0fde8 h1:zmKLyRCTiNZnizO++sNXP1QW2bxLE2Y+WJAdu/hcu6s= +github.com/dolthub/vitess v0.0.0-20260624214226-81d034e0fde8/go.mod h1:5SVEJgAhw5nnQUFnGgKI1Svqes1Mw+zKUsalyxmOuG0= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -501,8 +501,8 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= -github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/go-sql-driver/mysql v1.10.0 h1:Q+1LV8DkHJvSYAdR83XzuhDaTykuDx0l6fkXxoWCWfw= +github.com/go-sql-driver/mysql v1.10.0/go.mod h1:M+cqaI7+xxXGG9swrdeUIoPG3Y3KCkF0pZej+SK+nWk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= @@ -658,8 +658,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs= github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok= github.com/hanwen/go-fuse/v2 v2.1.0/go.mod h1:oRyA5eK+pvJyv5otpO/DgccS8y/RvYMaO00GgRLGryc= github.com/hashicorp/go-uuid v0.0.0-20180228145832-27454136f036/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -673,8 +673,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= -github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= +github.com/invopop/jsonschema v0.14.0 h1:MHQqLhvpNUZfw+hM3AZDYK7jxO8FZoQeQM77g8iyZjg= +github.com/invopop/jsonschema v0.14.0/go.mod h1:ygm6C2EaVNMBDPpaPlnOA2pFAxBnxGjFlMZABxm9n2I= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -771,8 +771,8 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= -github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= -github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= +github.com/lestrrat-go/strftime v1.2.0 h1:8fAUYOeaJKCuLzNvUWBAo8t6I6hkFfodDTndEzJIun0= +github.com/lestrrat-go/strftime v1.2.0/go.mod h1:GtsIA/7ddIGJjEdfadUafEb1sbutvlvpMdPCMglykYo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -796,8 +796,8 @@ github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw= github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= @@ -926,8 +926,8 @@ github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCw github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= -github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= +github.com/shirou/gopsutil/v4 v4.26.5 h1:RPcBXkpz7kOj9PqGFQOlBPZHsyaPvPVQc098y9RmCNM= +github.com/shirou/gopsutil/v4 v4.26.5/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1005,8 +1005,6 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/vbauerster/mpb/v8 v8.7.2 h1:SMJtxhNho1MV3OuFgS1DAzhANN1Ejc5Ct+0iSaIkB14= github.com/vbauerster/mpb/v8 v8.7.2/go.mod h1:ZFnrjzspgDHoxYLGvxIruiNk73GNTPG4YHgVNpR10VY= -github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= -github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xitongsys/parquet-go v1.5.1/go.mod h1:xUxwM8ELydxh4edHGegYq1pA8NnMKDx0K/GyB0o2bww= @@ -1051,28 +1049,30 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0 h1:RuynHbfU8JUEw7DyONgkVYg2SVtsoF28y0LGIr69jgA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0/go.mod h1:qZF+/lBs71APw8mlnEZcqZHMzqrYrsFiJOv83lX1OGo= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/metric/x v0.66.0 h1:YkCrx1zLOChi9ZcZ6euupOcsgzbVlec7D/xoEU1+cTA= +go.opentelemetry.io/otel/metric/x v0.66.0/go.mod h1:d1+BDj9t96do0/1LoU1ayfCv79ZgNE41qbhBvnMOBZk= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= go.opentelemetry.io/otel/sdk/log/logtest v0.19.0 h1:BEbF7ZBB6qQloV/Ub1+3NQoOUnVtcGkU3XX4Ws3GQfk= go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= @@ -1275,8 +1275,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= -golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1360,8 +1360,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= -golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20260625142307-59b4966ccb57 h1:nwGZBCt+FnXUrGsj5vjzAsEmkcaFvd82BbOjECiFYZc= golang.org/x/telemetry v0.0.0-20260625142307-59b4966ccb57/go.mod h1:3AWMyWHS+caVoiEXpiq6+tzKA40J4vQT3MYr80ZtQpc= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1371,8 +1371,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= -golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= +golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1621,10 +1621,10 @@ google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2I google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78= google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk= -google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= -google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= diff --git a/internal/api/dashboardspa/dist/assets/Activity-ByhthQ6l.js b/internal/api/dashboardspa/dist/assets/Activity-ytxmdj4u.js similarity index 98% rename from internal/api/dashboardspa/dist/assets/Activity-ByhthQ6l.js rename to internal/api/dashboardspa/dist/assets/Activity-ytxmdj4u.js index 3b99f3f554..7af337c62b 100644 --- a/internal/api/dashboardspa/dist/assets/Activity-ByhthQ6l.js +++ b/internal/api/dashboardspa/dist/assets/Activity-ytxmdj4u.js @@ -1,2 +1,2 @@ -import{w as I,v as q,a as P,T as B,b as F,j as t,B as V,L as W,af as $,ag as D,a3 as A,K as v,S as R,Q as M}from"./index-DDS7Ehww.js";import{r as C,c as b}from"./routeHighlight-B30gQO2o.js";import{P as G}from"./PageHeader-nOBkk_AA.js";import{a as O,b as z}from"./time-BVuL_AnL.js";import{u as H}from"./useVisibleRefresh-C8_1beQq.js";const U=100,f="24h";async function K(e={}){const s=I("list supervisor events"),a=await q().listEvents(s,{limit:U,since:f,...e}),i=a.items??[];return i.sort((n,l)=>l.seq-n.seq),{...a,items:i,total:Number(a.total)}}const Q=[{mode:"all",label:"All"},{mode:"events",label:"Events"},{mode:"deploys",label:"Deploys"},{mode:"commits",label:"Commits"}],L=[{value:"1h",label:"Last hour"},{value:f,label:"Last 24 hours"},{value:"7d",label:"Last 7 days"}],J=[{value:"all",label:"All signals"},{value:"attention",label:"Attention"},{value:"watch",label:"Watch"},{value:"event",label:"Event"}];function Ne(){const e=P(),[s,a]=B(),i=de(s),n=d(i,"events"),l=n?x(s.get("type")):null,o=n?x(s.get("actor")):null,r=n?me(s):f,c=n?pe(s):"all",h=n?x(s.get("q")):null,_=["activity:bundle",M()??"no-city",i,l??"all",o??"all",r,c,h??""].join(":"),{data:u,loading:m,error:S,refresh:k}=F(_,()=>X(i,l,o,r,c,h));return H(k,3e4),t.jsxs("section",{children:[t.jsx(G,{title:"Activity",synopsis:ie(i,l),meta:t.jsxs(t.Fragment,{children:[S&&t.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:S}),t.jsx(V,{size:"sm",onClick:()=>{k()},disabled:m,children:m?"Refreshing":"Refresh"})]})}),t.jsx(Z,{active:i,eventType:l}),n&&t.jsx(ee,{eventType:l,eventActor:o,eventWindow:r,eventSignal:c,searchParams:s,setSearchParams:a,textFilter:h}),t.jsxs("div",{className:"mt-10 space-y-12",children:[d(i,"events")&&t.jsx(te,{events:u?.events??null,...u?.eventsError!==void 0?{error:u.eventsError}:{},filterActive:l!==null||o!==null||c!=="all"||h!==null,loading:m,attentionSeverity:g=>C(e,"activity",oe(g))}),d(i,"deploys")&&t.jsx(se,{deploys:u?.deploys??null,...u?.deploysError!==void 0?{error:u.deploysError}:{},loading:m,attentionSeverity:g=>C(e,"activity",ce(g))}),d(i,"commits")&&t.jsx(re,{commits:u?.commits??null,...u?.commitsError!==void 0?{error:u.commitsError}:{},loading:m})]})]})}async function X(e,s,a,i,n,l){const[o,r,c]=await Promise.allSettled([d(e,"events")?Y(s,a,i,n,l):Promise.resolve(null),d(e,"deploys")?A.listBuilds():Promise.resolve(null),d(e,"commits")?A.listCommits("recent-all"):Promise.resolve(null)]);return{commits:j(c),...c.status==="rejected"?{commitsError:v(c.reason,"git commits unavailable")}:{},deploys:j(r),...r.status==="rejected"?{deploysError:v(r.reason,"deploy history unavailable")}:{},events:j(o),...o.status==="rejected"?{eventsError:v(o.reason,"event history unavailable")}:{}}}async function Y(e,s,a,i,n){const l=await K({since:a,...e===null?{}:{type:e},...s===null?{}:{actor:s}}),o=n?.toLowerCase()??"",r=l.items.filter(c=>e!==null&&c.type!==e||s!==null&&c.actor!==s||i!=="all"&&$(c)!==i?!1:o.length===0?!0:xe(c).includes(o));return{...l,items:r,total:r.length}}function j(e){return e.status==="fulfilled"?e.value:null}function Z({active:e,eventType:s}){return t.jsx("nav",{"aria-label":"Activity modes",children:t.jsx("ul",{className:"flex flex-wrap gap-2",children:Q.map(({mode:a,label:i})=>{const n=e===a;return t.jsx("li",{children:t.jsx(W,{to:ue(a,s),"aria-current":n?"page":void 0,className:["inline-flex items-center rounded-sm border px-2.5 py-1 text-label uppercase tracking-wider transition-colors duration-150 ease-out-quart focus-mark",n?"border-fg text-fg":"border-rule text-fg-muted hover:text-fg hover:bg-surface-tint"].join(" "),children:i})},a)})})})}function ee({eventActor:e,eventSignal:s,eventType:a,eventWindow:i,searchParams:n,setSearchParams:l,textFilter:o}){return t.jsxs("div",{className:"mt-6 flex flex-wrap items-end gap-4",children:[t.jsxs("label",{className:"grid gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Event window",t.jsx("select",{"aria-label":"Event window",value:i,onChange:r=>p(l,n,"since",r.currentTarget.value,f),className:"min-w-36 rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg focus-mark",children:L.map(r=>t.jsx("option",{value:r.value,children:r.label},r.value))})]}),t.jsxs("label",{className:"grid gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Event type",t.jsx("input",{"aria-label":"Event type",value:a??"",onChange:r=>p(l,n,"type",r.currentTarget.value),placeholder:"session.crashed",className:"min-w-44 rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg placeholder:text-fg-faint focus-mark"})]}),t.jsxs("label",{className:"grid gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Event actor",t.jsx("input",{"aria-label":"Event actor",value:e??"",onChange:r=>p(l,n,"actor",r.currentTarget.value),placeholder:"supervisor",className:"min-w-40 rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg placeholder:text-fg-faint focus-mark"})]}),t.jsxs("label",{className:"grid gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Signal severity",t.jsx("select",{"aria-label":"Signal severity",value:s,onChange:r=>p(l,n,"signal",r.currentTarget.value,"all"),className:"min-w-36 rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg focus-mark",children:J.map(r=>t.jsx("option",{value:r.value,children:r.label},r.value))})]}),t.jsxs("label",{className:"grid min-w-56 flex-1 gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Search activity",t.jsx("input",{"aria-label":"Search activity",value:o??"",onChange:r=>p(l,n,"q",r.currentTarget.value),placeholder:"actor, subject, or message",className:"rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg placeholder:text-fg-faint focus-mark"})]})]})}function te({error:e,events:s,filterActive:a,loading:i,attentionSeverity:n}){const l=s?.items??[],o=fe(s);return t.jsxs(y,{title:"Supervisor events",meta:s===null?null:`${s.total} events`,children:[e!==void 0&&t.jsxs("p",{className:"text-body text-accent",role:"alert",children:["Event history unavailable: ",e,"."]}),s?.partial===!0&&t.jsxs("p",{className:"text-body text-warn",children:["Event history incomplete",o.length>0?`: ${o.join("; ")}`:"."]}),t.jsxs(N,{label:"Supervisor events",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-rule text-label uppercase tracking-wider text-fg-muted",children:[t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Time"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Signal"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Type"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Subject"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Detail"})]})}),t.jsx("tbody",{children:l.length===0?t.jsx(w,{colSpan:5,children:i?"Reading supervisor events.":e!==void 0?"Event history unavailable.":a?"No supervisor events match these filters.":"No supervisor events in this window."}):l.map((r,c)=>t.jsxs("tr",{...b(n(r)),className:`border-b border-rule ${b(n(r)).className??""}`,children:[t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:t.jsx(E,{ts:r.ts})}),t.jsx("td",{className:"py-3 pr-6 align-baseline",children:t.jsx(le,{signal:$(r)})}),t.jsx("td",{className:"py-3 pr-6 align-baseline font-medium text-fg",children:r.type}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:r.subject??"·"}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:D(r)})]},`${r.seq}:${r.type}:${c}`))})]})]})}function se({deploys:e,error:s,loading:a,attentionSeverity:i}){const n=e?.items??[];return t.jsxs(y,{title:"Deploy history",meta:e?.failed_marker===!0?"failed marker present":e?.source??null,children:[s!==void 0&&t.jsxs("p",{className:"text-body text-accent",role:"alert",children:["Deploy history unavailable: ",s,"."]}),t.jsxs(N,{label:"Deploy history",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-rule text-label uppercase tracking-wider text-fg-muted",children:[t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Time"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Status"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Detail"})]})}),t.jsx("tbody",{children:n.length===0?t.jsx(w,{colSpan:3,children:a?"Reading deploy history.":"No deploy records in this window."}):n.map(l=>t.jsxs("tr",{...b(i(l)),className:`border-b border-rule ${b(i(l)).className??""}`,children:[t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:t.jsx(E,{ts:l.at})}),t.jsx("td",{className:"py-3 pr-6 align-baseline",children:t.jsx(ne,{deploy:l})}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:l.detail})]},`${l.at}:${l.detail}`))})]})]})}function re({commits:e,error:s,loading:a}){const i=e?.items??[];return t.jsxs(y,{title:"Git commits",meta:e===null?null:e.view,children:[s!==void 0&&t.jsxs("p",{className:"text-body text-accent",role:"alert",children:["Git commits unavailable: ",s,"."]}),t.jsxs(N,{label:"Git commits",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-rule text-label uppercase tracking-wider text-fg-muted",children:[t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Time"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Commit"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Author"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Subject"})]})}),t.jsx("tbody",{children:i.length===0?t.jsx(w,{colSpan:4,children:a?"Reading git commits.":"No commits in this window."}):i.map(n=>t.jsx(ae,{commit:n},n.sha))})]})]})}function ae({commit:e}){return t.jsxs("tr",{className:"border-b border-rule",children:[t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:t.jsx(E,{ts:e.date})}),t.jsx("td",{className:"py-3 pr-6 align-baseline font-medium text-fg",children:e.short_sha}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:e.author}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:e.subject})]})}function y({children:e,meta:s,title:a}){return t.jsxs("section",{"aria-labelledby":T(a),className:"space-y-4",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[t.jsx("h2",{id:T(a),className:"text-headline font-semibold tracking-tight text-fg",children:a}),s!==null&&t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:s})]}),e]})}function N({children:e,label:s}){return t.jsx("div",{className:"overflow-x-auto",children:t.jsx("table",{"aria-label":s,className:"w-full text-body tnum",children:e})})}function w({children:e,colSpan:s}){return t.jsx("tr",{children:t.jsx("td",{colSpan:s,className:"py-10 text-center text-fg-muted italic",children:e})})}function E({ts:e}){return t.jsx("span",{title:z(e),children:O(e)})}function le({signal:e}){const s=e==="attention"?"stuck":e==="watch"?"warn":"neutral";return t.jsx(R,{tone:s,label:e})}function ne({deploy:e}){const s=e.status==="ok"?"ok":e.status==="failed"?"stuck":e.status==="in-progress"?"warn":"neutral";return t.jsx(R,{tone:s,label:e.status})}function ie(e,s){return e==="events"&&s!==null?`Supervisor events filtered to ${s}.`:e==="events"?"Supervisor event history from the active city.":e==="deploys"?"Deploy history from dashboard-local project logs.":e==="commits"?"Recent git commits from the local project checkout.":"Supervisor events, deploy history, and recent project commits."}function oe(e){return`event:${String(e.seq)}:${e.type}`}function ce(e){return e.status==="failed"||e.status==="in-progress"?`deploy:${e.at}:${e.status}`:`deploy:${e.at}`}function ue(e,s){if(e==="all")return"/activity";const a=new URLSearchParams;return a.set("mode",e),e==="events"&&s!==null&&a.set("type",s),`/activity?${a.toString()}`}function d(e,s){return e==="all"||e===s}function de(e){const s=e.get("mode");return s==="events"||s==="deploys"||s==="commits"?s:"all"}function x(e){if(e===null)return null;const s=e.trim();return s.length===0?null:s}function me(e){const s=x(e.get("since"));return s!==null&&L.some(a=>a.value===s)?s:f}function pe(e){const s=x(e.get("signal"));return s==="attention"||s==="watch"||s==="event"?s:"all"}function p(e,s,a,i,n){const l=new URLSearchParams(s),o=i.trim();o.length===0||o===n?l.delete(a):l.set(a,o),e(l)}function xe(e){return[e.type,e.actor,e.subject,e.message,D(e)].filter(s=>typeof s=="string").join(` +import{w as I,v as q,a as P,T as B,b as F,j as t,B as V,L as W,af as $,ag as D,a3 as A,K as v,S as R,Q as M}from"./index-BDHAaQRP.js";import{r as C,c as b}from"./routeHighlight-B30gQO2o.js";import{P as G}from"./PageHeader-BW5bf722.js";import{a as O,b as z}from"./time-BVuL_AnL.js";import{u as H}from"./useVisibleRefresh-B7rFi4L5.js";const U=100,f="24h";async function K(e={}){const s=I("list supervisor events"),a=await q().listEvents(s,{limit:U,since:f,...e}),i=a.items??[];return i.sort((n,l)=>l.seq-n.seq),{...a,items:i,total:Number(a.total)}}const Q=[{mode:"all",label:"All"},{mode:"events",label:"Events"},{mode:"deploys",label:"Deploys"},{mode:"commits",label:"Commits"}],L=[{value:"1h",label:"Last hour"},{value:f,label:"Last 24 hours"},{value:"7d",label:"Last 7 days"}],J=[{value:"all",label:"All signals"},{value:"attention",label:"Attention"},{value:"watch",label:"Watch"},{value:"event",label:"Event"}];function Ne(){const e=P(),[s,a]=B(),i=de(s),n=d(i,"events"),l=n?x(s.get("type")):null,o=n?x(s.get("actor")):null,r=n?me(s):f,c=n?pe(s):"all",h=n?x(s.get("q")):null,_=["activity:bundle",M()??"no-city",i,l??"all",o??"all",r,c,h??""].join(":"),{data:u,loading:m,error:S,refresh:k}=F(_,()=>X(i,l,o,r,c,h));return H(k,3e4),t.jsxs("section",{children:[t.jsx(G,{title:"Activity",synopsis:ie(i,l),meta:t.jsxs(t.Fragment,{children:[S&&t.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:S}),t.jsx(V,{size:"sm",onClick:()=>{k()},disabled:m,children:m?"Refreshing":"Refresh"})]})}),t.jsx(Z,{active:i,eventType:l}),n&&t.jsx(ee,{eventType:l,eventActor:o,eventWindow:r,eventSignal:c,searchParams:s,setSearchParams:a,textFilter:h}),t.jsxs("div",{className:"mt-10 space-y-12",children:[d(i,"events")&&t.jsx(te,{events:u?.events??null,...u?.eventsError!==void 0?{error:u.eventsError}:{},filterActive:l!==null||o!==null||c!=="all"||h!==null,loading:m,attentionSeverity:g=>C(e,"activity",oe(g))}),d(i,"deploys")&&t.jsx(se,{deploys:u?.deploys??null,...u?.deploysError!==void 0?{error:u.deploysError}:{},loading:m,attentionSeverity:g=>C(e,"activity",ce(g))}),d(i,"commits")&&t.jsx(re,{commits:u?.commits??null,...u?.commitsError!==void 0?{error:u.commitsError}:{},loading:m})]})]})}async function X(e,s,a,i,n,l){const[o,r,c]=await Promise.allSettled([d(e,"events")?Y(s,a,i,n,l):Promise.resolve(null),d(e,"deploys")?A.listBuilds():Promise.resolve(null),d(e,"commits")?A.listCommits("recent-all"):Promise.resolve(null)]);return{commits:j(c),...c.status==="rejected"?{commitsError:v(c.reason,"git commits unavailable")}:{},deploys:j(r),...r.status==="rejected"?{deploysError:v(r.reason,"deploy history unavailable")}:{},events:j(o),...o.status==="rejected"?{eventsError:v(o.reason,"event history unavailable")}:{}}}async function Y(e,s,a,i,n){const l=await K({since:a,...e===null?{}:{type:e},...s===null?{}:{actor:s}}),o=n?.toLowerCase()??"",r=l.items.filter(c=>e!==null&&c.type!==e||s!==null&&c.actor!==s||i!=="all"&&$(c)!==i?!1:o.length===0?!0:xe(c).includes(o));return{...l,items:r,total:r.length}}function j(e){return e.status==="fulfilled"?e.value:null}function Z({active:e,eventType:s}){return t.jsx("nav",{"aria-label":"Activity modes",children:t.jsx("ul",{className:"flex flex-wrap gap-2",children:Q.map(({mode:a,label:i})=>{const n=e===a;return t.jsx("li",{children:t.jsx(W,{to:ue(a,s),"aria-current":n?"page":void 0,className:["inline-flex items-center rounded-sm border px-2.5 py-1 text-label uppercase tracking-wider transition-colors duration-150 ease-out-quart focus-mark",n?"border-fg text-fg":"border-rule text-fg-muted hover:text-fg hover:bg-surface-tint"].join(" "),children:i})},a)})})})}function ee({eventActor:e,eventSignal:s,eventType:a,eventWindow:i,searchParams:n,setSearchParams:l,textFilter:o}){return t.jsxs("div",{className:"mt-6 flex flex-wrap items-end gap-4",children:[t.jsxs("label",{className:"grid gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Event window",t.jsx("select",{"aria-label":"Event window",value:i,onChange:r=>p(l,n,"since",r.currentTarget.value,f),className:"min-w-36 rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg focus-mark",children:L.map(r=>t.jsx("option",{value:r.value,children:r.label},r.value))})]}),t.jsxs("label",{className:"grid gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Event type",t.jsx("input",{"aria-label":"Event type",value:a??"",onChange:r=>p(l,n,"type",r.currentTarget.value),placeholder:"session.crashed",className:"min-w-44 rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg placeholder:text-fg-faint focus-mark"})]}),t.jsxs("label",{className:"grid gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Event actor",t.jsx("input",{"aria-label":"Event actor",value:e??"",onChange:r=>p(l,n,"actor",r.currentTarget.value),placeholder:"supervisor",className:"min-w-40 rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg placeholder:text-fg-faint focus-mark"})]}),t.jsxs("label",{className:"grid gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Signal severity",t.jsx("select",{"aria-label":"Signal severity",value:s,onChange:r=>p(l,n,"signal",r.currentTarget.value,"all"),className:"min-w-36 rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg focus-mark",children:J.map(r=>t.jsx("option",{value:r.value,children:r.label},r.value))})]}),t.jsxs("label",{className:"grid min-w-56 flex-1 gap-1 text-label uppercase tracking-wider text-fg-muted",children:["Search activity",t.jsx("input",{"aria-label":"Search activity",value:o??"",onChange:r=>p(l,n,"q",r.currentTarget.value),placeholder:"actor, subject, or message",className:"rounded-sm border border-rule bg-surface px-2 py-1 text-body normal-case tracking-normal text-fg placeholder:text-fg-faint focus-mark"})]})]})}function te({error:e,events:s,filterActive:a,loading:i,attentionSeverity:n}){const l=s?.items??[],o=fe(s);return t.jsxs(y,{title:"Supervisor events",meta:s===null?null:`${s.total} events`,children:[e!==void 0&&t.jsxs("p",{className:"text-body text-accent",role:"alert",children:["Event history unavailable: ",e,"."]}),s?.partial===!0&&t.jsxs("p",{className:"text-body text-warn",children:["Event history incomplete",o.length>0?`: ${o.join("; ")}`:"."]}),t.jsxs(N,{label:"Supervisor events",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-rule text-label uppercase tracking-wider text-fg-muted",children:[t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Time"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Signal"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Type"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Subject"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Detail"})]})}),t.jsx("tbody",{children:l.length===0?t.jsx(w,{colSpan:5,children:i?"Reading supervisor events.":e!==void 0?"Event history unavailable.":a?"No supervisor events match these filters.":"No supervisor events in this window."}):l.map((r,c)=>t.jsxs("tr",{...b(n(r)),className:`border-b border-rule ${b(n(r)).className??""}`,children:[t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:t.jsx(E,{ts:r.ts})}),t.jsx("td",{className:"py-3 pr-6 align-baseline",children:t.jsx(le,{signal:$(r)})}),t.jsx("td",{className:"py-3 pr-6 align-baseline font-medium text-fg",children:r.type}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:r.subject??"·"}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:D(r)})]},`${r.seq}:${r.type}:${c}`))})]})]})}function se({deploys:e,error:s,loading:a,attentionSeverity:i}){const n=e?.items??[];return t.jsxs(y,{title:"Deploy history",meta:e?.failed_marker===!0?"failed marker present":e?.source??null,children:[s!==void 0&&t.jsxs("p",{className:"text-body text-accent",role:"alert",children:["Deploy history unavailable: ",s,"."]}),t.jsxs(N,{label:"Deploy history",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-rule text-label uppercase tracking-wider text-fg-muted",children:[t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Time"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Status"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Detail"})]})}),t.jsx("tbody",{children:n.length===0?t.jsx(w,{colSpan:3,children:a?"Reading deploy history.":"No deploy records in this window."}):n.map(l=>t.jsxs("tr",{...b(i(l)),className:`border-b border-rule ${b(i(l)).className??""}`,children:[t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:t.jsx(E,{ts:l.at})}),t.jsx("td",{className:"py-3 pr-6 align-baseline",children:t.jsx(ne,{deploy:l})}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:l.detail})]},`${l.at}:${l.detail}`))})]})]})}function re({commits:e,error:s,loading:a}){const i=e?.items??[];return t.jsxs(y,{title:"Git commits",meta:e===null?null:e.view,children:[s!==void 0&&t.jsxs("p",{className:"text-body text-accent",role:"alert",children:["Git commits unavailable: ",s,"."]}),t.jsxs(N,{label:"Git commits",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-rule text-label uppercase tracking-wider text-fg-muted",children:[t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Time"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Commit"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Author"}),t.jsx("th",{scope:"col",className:"pb-3 pr-6 text-left font-medium",children:"Subject"})]})}),t.jsx("tbody",{children:i.length===0?t.jsx(w,{colSpan:4,children:a?"Reading git commits.":"No commits in this window."}):i.map(n=>t.jsx(ae,{commit:n},n.sha))})]})]})}function ae({commit:e}){return t.jsxs("tr",{className:"border-b border-rule",children:[t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:t.jsx(E,{ts:e.date})}),t.jsx("td",{className:"py-3 pr-6 align-baseline font-medium text-fg",children:e.short_sha}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:e.author}),t.jsx("td",{className:"py-3 pr-6 align-baseline text-fg-muted",children:e.subject})]})}function y({children:e,meta:s,title:a}){return t.jsxs("section",{"aria-labelledby":T(a),className:"space-y-4",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[t.jsx("h2",{id:T(a),className:"text-headline font-semibold tracking-tight text-fg",children:a}),s!==null&&t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:s})]}),e]})}function N({children:e,label:s}){return t.jsx("div",{className:"overflow-x-auto",children:t.jsx("table",{"aria-label":s,className:"w-full text-body tnum",children:e})})}function w({children:e,colSpan:s}){return t.jsx("tr",{children:t.jsx("td",{colSpan:s,className:"py-10 text-center text-fg-muted italic",children:e})})}function E({ts:e}){return t.jsx("span",{title:z(e),children:O(e)})}function le({signal:e}){const s=e==="attention"?"stuck":e==="watch"?"warn":"neutral";return t.jsx(R,{tone:s,label:e})}function ne({deploy:e}){const s=e.status==="ok"?"ok":e.status==="failed"?"stuck":e.status==="in-progress"?"warn":"neutral";return t.jsx(R,{tone:s,label:e.status})}function ie(e,s){return e==="events"&&s!==null?`Supervisor events filtered to ${s}.`:e==="events"?"Supervisor event history from the active city.":e==="deploys"?"Deploy history from dashboard-local project logs.":e==="commits"?"Recent git commits from the local project checkout.":"Supervisor events, deploy history, and recent project commits."}function oe(e){return`event:${String(e.seq)}:${e.type}`}function ce(e){return e.status==="failed"||e.status==="in-progress"?`deploy:${e.at}:${e.status}`:`deploy:${e.at}`}function ue(e,s){if(e==="all")return"/activity";const a=new URLSearchParams;return a.set("mode",e),e==="events"&&s!==null&&a.set("type",s),`/activity?${a.toString()}`}function d(e,s){return e==="all"||e===s}function de(e){const s=e.get("mode");return s==="events"||s==="deploys"||s==="commits"?s:"all"}function x(e){if(e===null)return null;const s=e.trim();return s.length===0?null:s}function me(e){const s=x(e.get("since"));return s!==null&&L.some(a=>a.value===s)?s:f}function pe(e){const s=x(e.get("signal"));return s==="attention"||s==="watch"||s==="event"?s:"all"}function p(e,s,a,i,n){const l=new URLSearchParams(s),o=i.trim();o.length===0||o===n?l.delete(a):l.set(a,o),e(l)}function xe(e){return[e.type,e.actor,e.subject,e.message,D(e)].filter(s=>typeof s=="string").join(` `).toLowerCase()}function fe(e){const s=e?.partial_errors;return Array.isArray(s)?s.filter(a=>typeof a=="string"&&a.length>0):[]}function T(e){return`activity-${e.toLowerCase().replace(/[^a-z0-9]+/g,"-")}`}export{Ne as ActivityPage}; diff --git a/internal/api/dashboardspa/dist/assets/AgentDetail-LPnb-I_r.js b/internal/api/dashboardspa/dist/assets/AgentDetail-D04RKQJE.js similarity index 98% rename from internal/api/dashboardspa/dist/assets/AgentDetail-LPnb-I_r.js rename to internal/api/dashboardspa/dist/assets/AgentDetail-D04RKQJE.js index cc85c3c744..afd5bab108 100644 --- a/internal/api/dashboardspa/dist/assets/AgentDetail-LPnb-I_r.js +++ b/internal/api/dashboardspa/dist/assets/AgentDetail-D04RKQJE.js @@ -1,4 +1,4 @@ -import{p as Z,j as a,r as g,q as ve,t as ee,v as Se,w as Ee,x as Ae,y as $e,z as Ce,A as q,C as z,D as Re,S as ue,E as Le,F as Be,H as Ie,I as qe,u as Me,l as Te,J as Fe,K as te,f as Pe,M as De,B as se,L as ne,s as Oe,G as re}from"./index-DDS7Ehww.js";import{u as We,R as He,B as Ve}from"./BeadDetailModal-DpGateYl.js";import{P as V}from"./PageHeader-nOBkk_AA.js";import{f as G,a as Ue}from"./time-BVuL_AnL.js";import{P as fe}from"./constants-CQJOeNM1.js";import{L as ze,s as Ge,T as Je,a as Ke}from"./LiveSessionPeek-F4FmVdxt.js";import{e as Xe}from"./context-window-Cu9zl36t.js";import"./format-fte2CeYD.js";import"./Field-BEMyWxxD.js";function ae(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Qe(t){if(!ae(t)||typeof t.request_id!="string"||t.request_id.length===0||typeof t.kind!="string"||t.kind.length===0)return null;const e={request_id:t.request_id,kind:t.kind};if(typeof t.prompt=="string"&&(e.prompt=t.prompt),Array.isArray(t.options)&&t.options.every(n=>typeof n=="string")&&(e.options=t.options),ae(t.metadata)){const n=Object.entries(t.metadata).filter(s=>typeof s[1]=="string");n.length>0&&(e.metadata=Object.fromEntries(n))}return e}function Ye(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:null}function r(t,e,n){n===void 0||n===""||t.push(`${e}: ${n}`)}function h(t,e,n){n!==void 0&&t.push(`${e}: ${String(n)}`)}function ie(t,e,n){n!==void 0&&t.push(`${e}: ${String(n)}`)}function F(t,e){e!==void 0&&t.push(`exit ${String(e)}`)}function U(t,e){e.truncated===!0&&t.push("truncated"),"interrupted"in e&&e.interrupted===!0&&t.push("interrupted")}function E(t,e,n){if(n==null||n.length===0)return;const s=n.filter(i=>i!=="");s.length!==0&&t.push(`${e}: ${s.join(", ")}`)}function Ze(t,e){if(!(e==null||e.length===0)){t.push("uploaded files:");for(const n of e){const s=n.original_name??"",i=n.size??"",o=n.mime_type??"",c=n.file_path??"",m=n.preview_url??"",x=[i,o].filter(j=>j!=="").join(", "),y=m!==""?` preview: ${m}`:"";t.push(`- ${s}${x!==""?` (${x})`:""}${c!==""?`: ${c}`:""}${y}`)}}}function et(t,e){if(e==null||e.length===0)return;const n=e.map(s=>s.text??"").filter(s=>s!=="");if(n.length!==0){t.push("selections:");for(const s of n)t.push(`- ${s}`)}}function J(t,e){e==null||e.length===0||(t.push("steps:"),e.forEach((n,s)=>{const i=n.step??"",o=n.status??"",c=[o!==""?`[${o}]`:"",i!==""?i:`step ${s+1}`].filter(m=>m!=="");t.push(`- ${c.join(" ")}`)}))}function oe(t,e,n){if(!(n==null||n.length===0)){t.push(`${e}:`);for(const s of n){const i=pe(s);i!==""&&t.push(`- ${i}`)}}}function tt(t,e){e==null||e.length===0||(t.push("result items:"),e.forEach((n,s)=>{const i=n.title??"",o=n.url??"",c=n.snippet??"",x=[i!==""?i:`result ${s+1}`,o,c].filter(y=>y!=="");t.push(`- ${x.join(" | ")}`)}))}function st(t,e){e==null||e.length===0||(t.push("questions:"),e.forEach((n,s)=>{const i=n.question??"",o=n.header??"",c=n.multi_select===!0?"multi-select":"",m=i!==""?i:`question ${s+1}`,x=[o,m,c].filter(j=>j!=="");t.push(`- ${x.join(" | ")}`);const y=n.options;if(y!=null&&y.length>0){const j=y.map(k=>{const p=k.label??"",d=k.description??"";return[p,d].filter(f=>f!=="").join(" | ")}).filter(k=>k!=="");j.length>0&&t.push(` options: ${j.join("; ")}`)}}))}function D(t,e,n){n==null||n.length===0||(t.push(`${e}:`),n.forEach((s,i)=>{const o=s.status??"",c=s.content??"",m=s.active_form??"",x=s.priority??"",y=[o!==""?`[${o}]`:"",c!==""?c:`todo ${i+1}`,x!==""?`priority ${x}`:"",m!==""?`(${m})`:""].filter(j=>j!=="");t.push(`- ${y.join(" ")}`)}))}function nt(t,e){e!==void 0&&(r(t,"error category",e.category),r(t,"error",e.message),r(t,"user reason",e.user_reason))}function R(t){if(t==null)return"";if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return String(t)}}function pe(t){const e=Ye(t);if(e===null)return R(t);const n=typeof e.name=="string"?e.name:"argument",s=typeof e.value=="string"?e.value:R(e.value);return`${n}: ${s}`}function rt(t){switch((t??"").toLowerCase()){case"assistant":case"agent":return"assistant";case"system":return"system";case"result":return"result";default:return"user"}}function at(t){return t.startsWith("@@")?"hunk":t.startsWith("diff --git")||t.startsWith("index ")||t.startsWith("*** ")||t.startsWith("---")||t.startsWith("+++")?"file":t.startsWith("+")?"add":t.startsWith("-")?"del":"context"}function it(t){const e=t.type==="interaction"||t.type==="unknown"?t.interaction:void 0,n=e?.kind??"interaction",s=e?.state??"",i=e?.prompt??"",o=e?.request_id??"",c=e?.action??"",m=e?.options?.join(", ")??"";return[n,s,o,c,i,m].filter(Boolean).join(" ")}function ot(t){const e=[];return r(e,"kind",t.kind),r(e,"request",t.request_id),r(e,"prompt",t.prompt),E(e,"options",t.options===void 0?void 0:[...t.options]),e}function me(t){const e=[];return r(e,"prompt",t.text),E(e,"opened files",t.opened_files),Ze(e,t.uploaded_files),et(e,t.selections),e}function ge(t){const e=[];return r(e,"kind",t.kind),r(e,"category",t.category),r(e,"code",t.code),r(e,"message",t.message),e}function lt(t){const e=[];r(e,"stream",t.transcript_stream_id),r(e,"provider session",t.provider_session_id),r(e,"conversation",t.logical_conversation_id),r(e,"gc session",t.gc_session_id),r(e,"generation",t.generation.id),r(e,"observed",t.generation.observed_at),r(e,"cursor",t.cursor.after_entry_id),r(e,"continuity",t.continuity.status),h(e,"compactions",t.continuity.compaction_count),t.continuity.has_branches===!0&&e.push("branches: yes"),r(e,"note",t.continuity.note),r(e,"activity",t.tail_state.activity),r(e,"last entry",t.tail_state.last_entry_id),E(e,"open tools",t.tail_state.open_tool_call_ids),E(e,"pending",t.tail_state.pending_interaction_ids),t.tail_state.degraded===!0&&e.push("degraded: yes"),r(e,"degraded reason",t.tail_state.degraded_reason);for(const n of t.diagnostics??[]){const s=[];r(s,"code",n.code),h(s,"count",n.count),r(s,"message",n.message),s.length>0&&e.push(`diagnostic: ${s.join(", ")}`)}return e}function dt(t){const e=[];return t.type!=="image"&&t.type!=="unknown"||(r(e,"file",t.file_path),r(e,"url",t.image_url),r(e,"mime",t.mime_type)),e}function ct(t){const e=[];switch(r(e,"kind",t.kind),t.kind){case"command":r(e,"command",t.command),P(e,t.arguments);break;case"stdin":r(e,"task",t.task_id),r(e,"linked command",t.linked_command),r(e,"text",t.text);break;case"code":r(e,"language",t.language),r(e,"code",t.code);break;case"patch":r(e,"file",t.file_path),r(e,"language",t.language),r(e,"patch",t.patch);break;case"write":r(e,"file",t.file_path),r(e,"language",t.language),r(e,"text",t.text);break;case"glob":case"search":r(e,"file",t.file_path),t.kind==="search"&&r(e,"command",t.command),r(e,"query",t.query),r(e,"pattern",t.pattern),P(e,t.arguments);break;case"fetch":r(e,"url",t.url),r(e,"prompt",t.prompt);break;case"file":r(e,"file",t.file_path),r(e,"language",t.language),r(e,"command",t.command);break;case"todo":D(e,"todos",t.todos);break;case"plan":r(e,"plan",t.plan),r(e,"explanation",t.explanation),J(e,t.steps);break;case"question":r(e,"question",t.question),E(e,"options",t.options);break;case"task":r(e,"prompt",t.prompt),r(e,"task",t.task_id),r(e,"task type",t.task_type),r(e,"task status",t.task_status),r(e,"description",t.description);break;case"text":r(e,"text",t.text);break;case"arguments":P(e,t.arguments);break;case"unknown":r(e,"file",t.file_path),r(e,"language",t.language),r(e,"url",t.url),r(e,"prompt",t.prompt),r(e,"task",t.task_id),r(e,"task type",t.task_type),r(e,"task status",t.task_status),r(e,"description",t.description),r(e,"question",t.question),E(e,"options",t.options),r(e,"command",t.command),r(e,"linked command",t.linked_command),r(e,"code",t.code),r(e,"query",t.query),r(e,"pattern",t.pattern),r(e,"plan",t.plan),r(e,"explanation",t.explanation),J(e,t.steps),r(e,"text",t.text),r(e,"patch",t.patch),D(e,"todos",t.todos),P(e,t.arguments);break}return e.length===0&&e.push(R(t)),e}function P(t,e){e==null||e.length===0||t.push(...e.map(n=>pe(n)))}function ut(t){const e=t.type==="tool_result"||t.type==="unknown"?t.structured:void 0;if(e===void 0){const i=t.type==="tool_result"||t.type==="unknown"?t.content:void 0;return typeof i=="string"?{kind:"result",body:i,diff:""}:i!==void 0?{kind:"result",body:R(i),diff:""}:{kind:"result",body:"",diff:""}}const n=e.kind,s=[];if(r(s,"kind",n),r(s,"file","file_path"in e?e.file_path:void 0),r(s,"language","language"in e?e.language:void 0),nt(s,e.error),e.kind==="bash")return r(s,"command",e.command),r(s,"task",e.task_id),r(s,"task status",e.task_status),r(s,"stdout",e.stdout),r(s,"stderr",e.stderr),h(s,"stdout lines",e.stdout_lines),h(s,"stderr lines",e.stderr_lines),r(s,"timestamp",e.timestamp),F(s,e.exit_code),U(s,e),{kind:n,body:N(s),diff:""};if(e.kind==="python")return r(s,"code",e.code),r(s,"stdout",e.stdout),r(s,"stderr",e.stderr),F(s,e.exit_code),U(s,e),{kind:n,body:N(s),diff:""};if(e.kind==="stdin")return r(s,"task",e.task_id),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""};if(e.kind==="edit"){const i=(e.patch??"")||Z(e.patch_hunks);return r(s,"old",e.old_string),r(s,"new",e.new_string),r(s,"original file",e.original_file),ie(s,"replace all",e.replace_all),ie(s,"user modified",e.user_modified),r(s,"content",e.content),{kind:n,body:N(s),diff:i}}if(e.kind==="read")return r(s,"content",e.content),h(s,"start",e.start_line),h(s,"lines",e.num_lines),h(s,"total",e.total_lines),{kind:n,body:N(s),diff:""};if(e.kind==="write"){const i=(e.patch??"")||Z(e.patch_hunks);return r(s,"content",e.content),r(s,"text",e.text),h(s,"start",e.start_line),h(s,"lines",e.num_lines),h(s,"total",e.total_lines),{kind:n,body:N(s),diff:i}}return e.kind==="fetch"?(r(s,"url",e.url),h(s,"status",e.status_code),r(s,"status text",e.status_text),h(s,"bytes",e.bytes),h(s,"duration ms",e.duration_ms),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):e.kind==="todo"?(r(s,"content",e.content),D(s,"old todos",e.old_todos),D(s,"new todos",e.new_todos),{kind:n,body:N(s),diff:""}):e.kind==="plan"?(r(s,"plan",e.plan),r(s,"explanation",e.explanation),J(s,e.steps),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):e.kind==="question"?(r(s,"question",e.question),st(s,e.questions),E(s,"options",e.options),r(s,"answer",e.answer),oe(s,"answers",e.answers),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):e.kind==="task"?(r(s,"task",e.task_id),r(s,"task type",e.task_type),r(s,"task status",e.task_status),r(s,"description",e.description),h(s,"total duration ms",e.total_duration_ms),h(s,"total tokens",e.total_tokens),h(s,"total tool calls",e.total_tool_use_count),r(s,"output",e.output),r(s,"stdout",e.stdout),r(s,"stderr",e.stderr),F(s,e.exit_code),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):e.kind==="grep"||e.kind==="search"?(e.filenames!==void 0&&e.filenames!==null&&e.filenames.length>0&&r(s,"files",e.filenames.join(", ")),r(s,"query",e.query),r(s,"mode",e.mode),oe(s,"counts",e.counts),tt(s,e.result_items),r(s,"content",e.content),h(s,"files",e.num_files),h(s,"results",e.num_results),h(s,"duration ms",e.duration_ms),h(s,"applied limit",e.applied_limit),h(s,"lines",e.num_lines),{kind:n,body:N(s),diff:""}):e.kind==="glob"?(e.filenames!==void 0&&e.filenames!==null&&e.filenames.length>0&&r(s,"files",e.filenames.join(", ")),r(s,"content",e.content),h(s,"files",e.num_files),h(s,"duration ms",e.duration_ms),h(s,"lines",e.num_lines),U(s,e),{kind:n,body:N(s),diff:""}):e.kind==="text"?(r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):(r(s,"content",e.content),r(s,"text",e.text),r(s,"stdout",e.stdout),r(s,"stderr",e.stderr),F(s,e.exit_code),s.length===1&&s.push(R(e)),{kind:n,body:N(s),diff:""})}function N(t){return t.filter(Boolean).join(` +import{p as Z,j as a,r as g,q as ve,t as ee,v as Se,w as Ee,x as Ae,y as $e,z as Ce,A as q,C as z,D as Re,S as ue,E as Le,F as Be,H as Ie,I as qe,u as Me,l as Te,J as Fe,K as te,f as Pe,M as De,B as se,L as ne,s as Oe,G as re}from"./index-BDHAaQRP.js";import{u as We,R as He,B as Ve}from"./BeadDetailModal-B7DCLOq5.js";import{P as V}from"./PageHeader-BW5bf722.js";import{f as G,a as Ue}from"./time-BVuL_AnL.js";import{P as fe}from"./constants-D5DlRFFg.js";import{L as ze,s as Ge,T as Je,a as Ke}from"./LiveSessionPeek-VUsvyqKB.js";import{e as Xe}from"./context-window-Cu9zl36t.js";import"./format-fte2CeYD.js";import"./Field-BSdtNgao.js";function ae(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Qe(t){if(!ae(t)||typeof t.request_id!="string"||t.request_id.length===0||typeof t.kind!="string"||t.kind.length===0)return null;const e={request_id:t.request_id,kind:t.kind};if(typeof t.prompt=="string"&&(e.prompt=t.prompt),Array.isArray(t.options)&&t.options.every(n=>typeof n=="string")&&(e.options=t.options),ae(t.metadata)){const n=Object.entries(t.metadata).filter(s=>typeof s[1]=="string");n.length>0&&(e.metadata=Object.fromEntries(n))}return e}function Ye(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:null}function r(t,e,n){n===void 0||n===""||t.push(`${e}: ${n}`)}function h(t,e,n){n!==void 0&&t.push(`${e}: ${String(n)}`)}function ie(t,e,n){n!==void 0&&t.push(`${e}: ${String(n)}`)}function F(t,e){e!==void 0&&t.push(`exit ${String(e)}`)}function U(t,e){e.truncated===!0&&t.push("truncated"),"interrupted"in e&&e.interrupted===!0&&t.push("interrupted")}function E(t,e,n){if(n==null||n.length===0)return;const s=n.filter(i=>i!=="");s.length!==0&&t.push(`${e}: ${s.join(", ")}`)}function Ze(t,e){if(!(e==null||e.length===0)){t.push("uploaded files:");for(const n of e){const s=n.original_name??"",i=n.size??"",o=n.mime_type??"",c=n.file_path??"",m=n.preview_url??"",x=[i,o].filter(j=>j!=="").join(", "),y=m!==""?` preview: ${m}`:"";t.push(`- ${s}${x!==""?` (${x})`:""}${c!==""?`: ${c}`:""}${y}`)}}}function et(t,e){if(e==null||e.length===0)return;const n=e.map(s=>s.text??"").filter(s=>s!=="");if(n.length!==0){t.push("selections:");for(const s of n)t.push(`- ${s}`)}}function J(t,e){e==null||e.length===0||(t.push("steps:"),e.forEach((n,s)=>{const i=n.step??"",o=n.status??"",c=[o!==""?`[${o}]`:"",i!==""?i:`step ${s+1}`].filter(m=>m!=="");t.push(`- ${c.join(" ")}`)}))}function oe(t,e,n){if(!(n==null||n.length===0)){t.push(`${e}:`);for(const s of n){const i=pe(s);i!==""&&t.push(`- ${i}`)}}}function tt(t,e){e==null||e.length===0||(t.push("result items:"),e.forEach((n,s)=>{const i=n.title??"",o=n.url??"",c=n.snippet??"",x=[i!==""?i:`result ${s+1}`,o,c].filter(y=>y!=="");t.push(`- ${x.join(" | ")}`)}))}function st(t,e){e==null||e.length===0||(t.push("questions:"),e.forEach((n,s)=>{const i=n.question??"",o=n.header??"",c=n.multi_select===!0?"multi-select":"",m=i!==""?i:`question ${s+1}`,x=[o,m,c].filter(j=>j!=="");t.push(`- ${x.join(" | ")}`);const y=n.options;if(y!=null&&y.length>0){const j=y.map(k=>{const p=k.label??"",d=k.description??"";return[p,d].filter(f=>f!=="").join(" | ")}).filter(k=>k!=="");j.length>0&&t.push(` options: ${j.join("; ")}`)}}))}function D(t,e,n){n==null||n.length===0||(t.push(`${e}:`),n.forEach((s,i)=>{const o=s.status??"",c=s.content??"",m=s.active_form??"",x=s.priority??"",y=[o!==""?`[${o}]`:"",c!==""?c:`todo ${i+1}`,x!==""?`priority ${x}`:"",m!==""?`(${m})`:""].filter(j=>j!=="");t.push(`- ${y.join(" ")}`)}))}function nt(t,e){e!==void 0&&(r(t,"error category",e.category),r(t,"error",e.message),r(t,"user reason",e.user_reason))}function R(t){if(t==null)return"";if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return String(t)}}function pe(t){const e=Ye(t);if(e===null)return R(t);const n=typeof e.name=="string"?e.name:"argument",s=typeof e.value=="string"?e.value:R(e.value);return`${n}: ${s}`}function rt(t){switch((t??"").toLowerCase()){case"assistant":case"agent":return"assistant";case"system":return"system";case"result":return"result";default:return"user"}}function at(t){return t.startsWith("@@")?"hunk":t.startsWith("diff --git")||t.startsWith("index ")||t.startsWith("*** ")||t.startsWith("---")||t.startsWith("+++")?"file":t.startsWith("+")?"add":t.startsWith("-")?"del":"context"}function it(t){const e=t.type==="interaction"||t.type==="unknown"?t.interaction:void 0,n=e?.kind??"interaction",s=e?.state??"",i=e?.prompt??"",o=e?.request_id??"",c=e?.action??"",m=e?.options?.join(", ")??"";return[n,s,o,c,i,m].filter(Boolean).join(" ")}function ot(t){const e=[];return r(e,"kind",t.kind),r(e,"request",t.request_id),r(e,"prompt",t.prompt),E(e,"options",t.options===void 0?void 0:[...t.options]),e}function me(t){const e=[];return r(e,"prompt",t.text),E(e,"opened files",t.opened_files),Ze(e,t.uploaded_files),et(e,t.selections),e}function ge(t){const e=[];return r(e,"kind",t.kind),r(e,"category",t.category),r(e,"code",t.code),r(e,"message",t.message),e}function lt(t){const e=[];r(e,"stream",t.transcript_stream_id),r(e,"provider session",t.provider_session_id),r(e,"conversation",t.logical_conversation_id),r(e,"gc session",t.gc_session_id),r(e,"generation",t.generation.id),r(e,"observed",t.generation.observed_at),r(e,"cursor",t.cursor.after_entry_id),r(e,"continuity",t.continuity.status),h(e,"compactions",t.continuity.compaction_count),t.continuity.has_branches===!0&&e.push("branches: yes"),r(e,"note",t.continuity.note),r(e,"activity",t.tail_state.activity),r(e,"last entry",t.tail_state.last_entry_id),E(e,"open tools",t.tail_state.open_tool_call_ids),E(e,"pending",t.tail_state.pending_interaction_ids),t.tail_state.degraded===!0&&e.push("degraded: yes"),r(e,"degraded reason",t.tail_state.degraded_reason);for(const n of t.diagnostics??[]){const s=[];r(s,"code",n.code),h(s,"count",n.count),r(s,"message",n.message),s.length>0&&e.push(`diagnostic: ${s.join(", ")}`)}return e}function dt(t){const e=[];return t.type!=="image"&&t.type!=="unknown"||(r(e,"file",t.file_path),r(e,"url",t.image_url),r(e,"mime",t.mime_type)),e}function ct(t){const e=[];switch(r(e,"kind",t.kind),t.kind){case"command":r(e,"command",t.command),P(e,t.arguments);break;case"stdin":r(e,"task",t.task_id),r(e,"linked command",t.linked_command),r(e,"text",t.text);break;case"code":r(e,"language",t.language),r(e,"code",t.code);break;case"patch":r(e,"file",t.file_path),r(e,"language",t.language),r(e,"patch",t.patch);break;case"write":r(e,"file",t.file_path),r(e,"language",t.language),r(e,"text",t.text);break;case"glob":case"search":r(e,"file",t.file_path),t.kind==="search"&&r(e,"command",t.command),r(e,"query",t.query),r(e,"pattern",t.pattern),P(e,t.arguments);break;case"fetch":r(e,"url",t.url),r(e,"prompt",t.prompt);break;case"file":r(e,"file",t.file_path),r(e,"language",t.language),r(e,"command",t.command);break;case"todo":D(e,"todos",t.todos);break;case"plan":r(e,"plan",t.plan),r(e,"explanation",t.explanation),J(e,t.steps);break;case"question":r(e,"question",t.question),E(e,"options",t.options);break;case"task":r(e,"prompt",t.prompt),r(e,"task",t.task_id),r(e,"task type",t.task_type),r(e,"task status",t.task_status),r(e,"description",t.description);break;case"text":r(e,"text",t.text);break;case"arguments":P(e,t.arguments);break;case"unknown":r(e,"file",t.file_path),r(e,"language",t.language),r(e,"url",t.url),r(e,"prompt",t.prompt),r(e,"task",t.task_id),r(e,"task type",t.task_type),r(e,"task status",t.task_status),r(e,"description",t.description),r(e,"question",t.question),E(e,"options",t.options),r(e,"command",t.command),r(e,"linked command",t.linked_command),r(e,"code",t.code),r(e,"query",t.query),r(e,"pattern",t.pattern),r(e,"plan",t.plan),r(e,"explanation",t.explanation),J(e,t.steps),r(e,"text",t.text),r(e,"patch",t.patch),D(e,"todos",t.todos),P(e,t.arguments);break}return e.length===0&&e.push(R(t)),e}function P(t,e){e==null||e.length===0||t.push(...e.map(n=>pe(n)))}function ut(t){const e=t.type==="tool_result"||t.type==="unknown"?t.structured:void 0;if(e===void 0){const i=t.type==="tool_result"||t.type==="unknown"?t.content:void 0;return typeof i=="string"?{kind:"result",body:i,diff:""}:i!==void 0?{kind:"result",body:R(i),diff:""}:{kind:"result",body:"",diff:""}}const n=e.kind,s=[];if(r(s,"kind",n),r(s,"file","file_path"in e?e.file_path:void 0),r(s,"language","language"in e?e.language:void 0),nt(s,e.error),e.kind==="bash")return r(s,"command",e.command),r(s,"task",e.task_id),r(s,"task status",e.task_status),r(s,"stdout",e.stdout),r(s,"stderr",e.stderr),h(s,"stdout lines",e.stdout_lines),h(s,"stderr lines",e.stderr_lines),r(s,"timestamp",e.timestamp),F(s,e.exit_code),U(s,e),{kind:n,body:N(s),diff:""};if(e.kind==="python")return r(s,"code",e.code),r(s,"stdout",e.stdout),r(s,"stderr",e.stderr),F(s,e.exit_code),U(s,e),{kind:n,body:N(s),diff:""};if(e.kind==="stdin")return r(s,"task",e.task_id),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""};if(e.kind==="edit"){const i=(e.patch??"")||Z(e.patch_hunks);return r(s,"old",e.old_string),r(s,"new",e.new_string),r(s,"original file",e.original_file),ie(s,"replace all",e.replace_all),ie(s,"user modified",e.user_modified),r(s,"content",e.content),{kind:n,body:N(s),diff:i}}if(e.kind==="read")return r(s,"content",e.content),h(s,"start",e.start_line),h(s,"lines",e.num_lines),h(s,"total",e.total_lines),{kind:n,body:N(s),diff:""};if(e.kind==="write"){const i=(e.patch??"")||Z(e.patch_hunks);return r(s,"content",e.content),r(s,"text",e.text),h(s,"start",e.start_line),h(s,"lines",e.num_lines),h(s,"total",e.total_lines),{kind:n,body:N(s),diff:i}}return e.kind==="fetch"?(r(s,"url",e.url),h(s,"status",e.status_code),r(s,"status text",e.status_text),h(s,"bytes",e.bytes),h(s,"duration ms",e.duration_ms),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):e.kind==="todo"?(r(s,"content",e.content),D(s,"old todos",e.old_todos),D(s,"new todos",e.new_todos),{kind:n,body:N(s),diff:""}):e.kind==="plan"?(r(s,"plan",e.plan),r(s,"explanation",e.explanation),J(s,e.steps),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):e.kind==="question"?(r(s,"question",e.question),st(s,e.questions),E(s,"options",e.options),r(s,"answer",e.answer),oe(s,"answers",e.answers),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):e.kind==="task"?(r(s,"task",e.task_id),r(s,"task type",e.task_type),r(s,"task status",e.task_status),r(s,"description",e.description),h(s,"total duration ms",e.total_duration_ms),h(s,"total tokens",e.total_tokens),h(s,"total tool calls",e.total_tool_use_count),r(s,"output",e.output),r(s,"stdout",e.stdout),r(s,"stderr",e.stderr),F(s,e.exit_code),r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):e.kind==="grep"||e.kind==="search"?(e.filenames!==void 0&&e.filenames!==null&&e.filenames.length>0&&r(s,"files",e.filenames.join(", ")),r(s,"query",e.query),r(s,"mode",e.mode),oe(s,"counts",e.counts),tt(s,e.result_items),r(s,"content",e.content),h(s,"files",e.num_files),h(s,"results",e.num_results),h(s,"duration ms",e.duration_ms),h(s,"applied limit",e.applied_limit),h(s,"lines",e.num_lines),{kind:n,body:N(s),diff:""}):e.kind==="glob"?(e.filenames!==void 0&&e.filenames!==null&&e.filenames.length>0&&r(s,"files",e.filenames.join(", ")),r(s,"content",e.content),h(s,"files",e.num_files),h(s,"duration ms",e.duration_ms),h(s,"lines",e.num_lines),U(s,e),{kind:n,body:N(s),diff:""}):e.kind==="text"?(r(s,"content",e.content),r(s,"text",e.text),{kind:n,body:N(s),diff:""}):(r(s,"content",e.content),r(s,"text",e.text),r(s,"stdout",e.stdout),r(s,"stderr",e.stderr),F(s,e.exit_code),s.length===1&&s.push(R(e)),{kind:n,body:N(s),diff:""})}function N(t){return t.filter(Boolean).join(` `)}function ft({beads:t,error:e,loading:n,onSelect:s}){return a.jsxs("section",{className:"mb-12",children:[a.jsxs("header",{className:"flex items-baseline justify-between mb-4",children:[a.jsx("h2",{className:"text-label uppercase tracking-wider text-fg-faint",children:"Beads assigned"}),a.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:n?"·":t.length})]}),e!==null?a.jsx("p",{className:"text-body text-accent",role:"alert",children:e}):n?a.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading beads."}):t.length===0?a.jsx("p",{className:"text-body text-fg-muted italic",children:"No beads assigned to this agent."}):a.jsx("ul",{className:"space-y-2",children:t.map(i=>a.jsxs("li",{className:"flex items-baseline gap-3 min-w-0",children:[a.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum shrink-0",children:i.id}),a.jsx("button",{type:"button",onClick:()=>s(i),className:"text-body text-fg hover:text-accent truncate min-w-0 text-left focus-mark",title:`Open ${i.id}`,children:i.title}),a.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint shrink-0",children:i.status})]},i.id))})]})}function pt({messages:t,loading:e,error:n,now:s}){return a.jsxs("section",{className:"mt-12",children:[a.jsxs("header",{className:"flex items-baseline justify-between mb-4",children:[a.jsx("h2",{className:"text-label uppercase tracking-wider text-fg-faint",children:"Chat thread"}),a.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:e?"·":t.length})]}),a.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint mb-4",children:a.jsxs("span",{className:"text-accent",children:["▲ ",fe]})}),e?a.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading messages."}):n!==null?a.jsx("p",{className:"text-body text-accent",role:"alert",children:n}):t.length===0?a.jsx("p",{className:"text-body text-fg-muted italic",children:"No messages between operator and this agent."}):a.jsx("ul",{className:"space-y-6",children:t.map(i=>a.jsxs("li",{className:"space-y-2 pb-4 border-b border-rule last:border-0",children:[a.jsxs("header",{className:"flex items-baseline justify-between gap-3",children:[a.jsxs("div",{className:"text-label uppercase tracking-wider text-fg-muted truncate",children:[a.jsx("span",{className:"text-fg font-medium",children:i.from}),a.jsx("span",{className:"mx-1.5 text-fg-faint",children:"→"}),a.jsx("span",{children:i.to})]}),a.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum shrink-0",children:G(i.created_at,s)})]}),i.subject&&a.jsx("p",{className:"text-body font-medium text-fg",children:i.subject}),a.jsx("pre",{className:"text-body whitespace-pre-wrap leading-relaxed text-fg overflow-x-auto",children:i.body})]},i.id))})]})}const le="Malformed structured session frame.";function mt(t,e){const[n,s]=g.useState({status:"idle",stream:{status:"idle"}}),i=g.useRef(!1);return g.useEffect(()=>{if(i.current=!1,!t){s({status:"idle",stream:{status:"idle"}});return}let o=!1,c=null;const m=e&&typeof EventSource<"u";s({status:"loading",stream:{status:m?"connecting":"idle"}});const x=()=>{i.current||(i.current=!0,de("parse structured frame",t,le)),s(p=>p.status==="ready"?{...p,stream:{status:"degraded",error:le}}:p)},y=p=>{s(d=>d.status==="ready"?{status:"ready",result:{...d.result,items:ht(d.result.items,p)},stream:{status:"open"}}:d)},j=p=>p.map(d=>({kind:"message",message:d})),k=(p,d)=>{const f=ee(d);return{provider:d.provider,template:d.template,history:d.history,items:d.operation==="upsert"?gt(p.items,f):xt(p.items,f),activity:d.history.tail_state.activity}};return ve(t).then(p=>{if(!o){if(p===null){s({status:"unavailable",stream:{status:"idle"}});return}s({status:"ready",result:{provider:p.provider,template:p.template,history:p.history,items:j(ee(p)),activity:p.history.tail_state.activity},stream:{status:m?"connecting":"idle"}}),m&&(c=new EventSource(Se().sessionStreamUrl(Ee("open structured session stream"),t,p.history.cursor.resume_token,"structured"),{withCredentials:!0}),c.onopen=()=>{o||s(d=>d.status==="ready"?{...d,result:{...d.result,items:d.result.items.filter(f=>f.kind!=="pending")},stream:{status:"open"}}:d)},c.addEventListener("structured",d=>{if(o)return;const f=B(d.data);if(f===null||!Ae(f))return x();s(_=>_.status==="ready"?{status:"ready",result:k(_.result,f),stream:{status:"open"}}:_)}),c.addEventListener("activity",d=>{if(o)return;const f=B(d.data);if(f===null||!$e(f))return x();const _=f.activity;s(b=>b.status==="ready"?{status:"ready",result:{...b.result,activity:_},stream:{status:"open"}}:b)}),c.addEventListener("pending",d=>{if(o)return;const f=B(d.data),_=f===null?null:Qe(f);if(_===null)return x();y(_)}),c.addEventListener("pending_cleared",d=>{if(o)return;const f=B(d.data),_=yt(f);if(_===null)return x();s(b=>b.status==="ready"?{status:"ready",result:{...b.result,items:b.result.items.filter(w=>w.kind!=="pending"||w.pending.request_id!==_)},stream:{status:"open"}}:b)}),c.addEventListener("heartbeat",d=>{if(o)return;const f=B(d.data);if(f===null||!Ce(f))return x();s(_=>_.status==="ready"&&(_.stream.status==="connecting"||_.stream.status==="closed")?{..._,stream:{status:"open"}}:_)}),c.onmessage=()=>{o||x()},c.onerror=()=>{if(o)return;const d=c?.readyState===EventSource.CLOSED?"closed":"connecting";s(f=>f.status==="ready"?{...f,stream:{status:d}}:f)})}},p=>{o||(de("load structured transcript",t,p),s({status:"failed",error:q(p)||"Failed to load session.",stream:{status:"idle"}}))}),()=>{o=!0,c?.close()}},[t,e]),n}function gt(t,e){const n=new Map(e.map(o=>[o.id,o])),s=new Set,i=t.map(o=>{if(o.kind==="pending")return o;s.add(o.message.id);const c=n.get(o.message.id);return c===void 0?o:{kind:"message",message:c}});for(const o of e)s.has(o.id)||(i.push({kind:"message",message:n.get(o.id)??o}),s.add(o.id));return i}function xt(t,e){return[...e.map(n=>({kind:"message",message:n})),...t.filter(n=>n.kind==="pending")]}function ht(t,e){return[...t.filter(n=>n.kind!=="pending"),{kind:"pending",pending:e}]}function B(t){try{return JSON.parse(t)}catch{return null}}function yt(t){if(typeof t!="object"||t===null||Array.isArray(t))return null;const e=t.request_id;return typeof e=="string"&&e!==""?e:null}function de(t,e,n){z({component:"structured-session-stream",operation:t,message:`${e}: ${q(n)}`})}const _t={add:"text-ok",del:"text-warn",file:"text-fg-faint",hunk:"text-fg-muted",context:"text-fg"};function jt({text:t}){const e=t.replace(/\r\n/g,` `).split(` `);return a.jsx("pre",{className:"text-body whitespace-pre-wrap leading-relaxed overflow-x-auto",children:e.map((n,s)=>a.jsxs(g.Fragment,{children:[a.jsx("span",{className:_t[at(n)],children:n}),s=0;o--){const l=n.charAt(o);if(l!=="-"&&l!=="_"&&l!=="/")continue;const c=n.slice(o+1);if(c&&/^(?:gc|td|th|[a-z]{4})-[a-z0-9]{1,32}$/.test(c))return{role:n.slice(0,o),sessionId:c}}return{role:n}}const We="in_progress";function De(s){return Ie(_e(s).label)}function Fe(s){const n=O(s.template??"");return n.length>0?n:O(s.session_name??s.id)}function Z(s){const n=s.session.last_active?Date.parse(s.session.last_active):NaN;return Number.isFinite(n)?n:0}function Ue(s,n){const o=new Map;for(const r of n){if(r.status!==We)continue;const i=r.assignee?.trim();if(!i)continue;const{sessionId:m}=ze(i);m&&!o.has(m)&&o.set(m,r)}const l=[];for(const r of s){if(!$e(r))continue;const i=o.get(r.id);l.push({session:r,rig:De(r),worker:Fe(r),...i?{bead:i}:{}})}l.sort((r,i)=>Z(i)-Z(r));const c=new Map;for(const r of l)c.set(r.rig,(c.get(r.rig)??0)+1);const u=Array.from(c,([r,i])=>({rig:r,count:i})).sort((r,i)=>i.count-r.count||r.rig.localeCompare(i.rig));return{workers:l,byRig:u,total:l.length}}function Ve(s){if(s.total===0)return"No workers active right now.";const n=s.total===1?"worker":"workers",o=s.byRig.map(l=>`${l.rig} (${l.count})`).join(", ");return`${s.total} ${n} active across ${o}.`}function Ye({worker:s,accent:n,onPeek:o}){const l=te(),{session:c,rig:u,bead:r}=s,i=n?T(c.state):"neutral";return e.jsx("li",{className:"px-2 py-2 -mx-2 rounded-sm transition-colors duration-150 ease-out-quart hover:bg-surface-tint/60",children:e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0 text-body text-fg",children:[e.jsxs("button",{type:"button",onClick:()=>o(c.id),className:"group text-left cursor-pointer focus-mark",title:`Open ${u} · ${s.worker} transcript`,children:[e.jsx("span",{className:"font-medium group-hover:text-accent",children:u}),e.jsxs("span",{className:"text-fg-faint","aria-hidden":"true",children:[" ","·"," "]}),e.jsx("span",{className:"text-fg-muted group-hover:text-accent",children:s.worker})]}),r&&e.jsxs(I,{to:`/beads?bead=${encodeURIComponent(r.id)}`,className:"hover:text-accent focus-mark",title:`Open ${r.id}`,children:[e.jsxs("span",{className:"text-fg-faint","aria-hidden":"true",children:[" ","→"," "]}),e.jsx("span",{className:"tnum text-fg-muted",children:r.id}),e.jsxs("span",{className:"text-fg-muted",children:[": ",r.title]})]})]}),e.jsxs("div",{className:"flex items-baseline gap-3 shrink-0",children:[e.jsx($,{tone:i,label:c.state}),e.jsx("span",{className:"tnum text-fg-muted w-10 text-right",children:ae(c.last_active,l)}),e.jsx(y,{size:"sm",tone:"quiet",onClick:()=>o(c.id),children:"Peek"})]})]})})}function Ge(s){return s.running===!0||s.state==="active"||s.state==="running"}function He({beads:s,sessions:n,sessionsLoading:o,sessionsError:l}){const c=d.useMemo(()=>Ue(n,s),[n,s]),u=d.useMemo(()=>Ve(c),[c]),[r,i]=d.useState(null),m=d.useMemo(()=>r?c.workers.find(f=>f.session.id===r)??null:null,[c.workers,r]),k=d.useMemo(()=>c.workers.findIndex(f=>T(f.session.state)==="stuck"),[c.workers]),p=n.length===0,w=l!==null&&p,N=o&&p,_=w||N?"—":c.total;return e.jsxs("section",{className:"mb-10","aria-label":"Workers active",children:[e.jsxs("header",{className:"flex items-baseline justify-between border-b border-rule pb-2 mb-4",children:[e.jsx("h2",{className:"text-headline text-fg",children:"Workers active"}),e.jsx("span",{className:"text-label tnum text-fg-muted",children:_})]}),w?e.jsx("p",{className:"text-body text-fg-muted",role:"status",children:"Worker status unavailable."}):N?e.jsx("p",{className:"text-body text-fg-muted",role:"status",children:"Checking worker status…"}):c.total===0?e.jsx("p",{className:"text-body text-fg-muted",children:"No workers active right now."}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-body text-fg-muted mb-4",children:u}),e.jsx("ul",{className:"space-y-1",children:c.workers.map((f,C)=>e.jsx(Ye,{worker:f,accent:C===k,onPeek:i},f.session.id))})]}),e.jsx(ne,{open:m!==null,onClose:()=>i(null),title:m?`${m.rig} · ${m.worker}`:"Transcript",caption:m?.bead?e.jsxs(I,{to:`/beads?bead=${encodeURIComponent(m.bead.id)}`,className:"text-fg-muted hover:text-accent focus-mark",title:`Open ${m.bead.id}`,children:[e.jsx("span",{className:"tnum",children:m.bead.id}),e.jsxs("span",{children:[": ",m.bead.title]})]}):"Live transcript from the supervisor's session stream.",widthClass:"max-w-5xl",children:e.jsx(ie,{sessionId:r,stream:m?Ge(m.session):!1,showBadge:!0,showCaption:!0})})]})}function ee(s){return s.session?.name??s.name}function Ke(s){return!s.suspended&&(s.state==="active"||s.state==="running"||s.running===!0)}function Xe(s,n){return Ke(s)||n==="attention"}function P(s){const n=O(s.name);return se(s)?n:`${E(s).label} · ${n}`}const Je=s=>[s.name,s.display_name,s.pool,s.rig,s.provider,s.model].filter(n=>typeof n=="string"&&n.length>0);function ft(){const s=fe(),{data:n,loading:o,error:l,refresh:c}=R("agents",Be),u=R("sessions",xe),r=R("beads:in-flight",()=>he()),i=d.useMemo(()=>n?.items??[],[n]),m=d.useMemo(()=>(u.data?.items??[]).map(t=>t.id).sort(),[u.data]),k=d.useMemo(()=>i.map(t=>t.name).sort(),[i]),p=R(`agent-pending:${k.join(",")}:${m.join(",")}`,()=>be(i,u.data?.items??[])),w=d.useMemo(()=>{const t=new Map;for(const a of u.data?.items??[])a.session_name&&t.set(a.session_name,a.id);return t},[u.data]),N=d.useMemo(()=>{const t=new Map;for(const a of p.data??[])t.set(a.agentName,a);return t},[p.data]),_=d.useMemo(()=>{const t=(p.data??[]).map(g=>({agentName:g.agentName,...g.pending.prompt===void 0?{}:{prompt:g.pending.prompt}})),a=new Map(i.map(g=>[g.name,g]));return ve(i,t).flatMap(g=>{const b=a.get(g.name);return b===void 0?[]:[{need:g,label:P(b),slug:ee(b)}]})},[i,p.data]),f=te(),[C,oe]=d.useState(!0),[M,re]=d.useState(""),[v,B]=d.useState(""),[S,q]=d.useState(null),[z,W]=d.useState(null),[D,F]=d.useState(null),[j,U]=d.useState(null),x=d.useMemo(()=>S===null?null:i.find(t=>t.name===S)??null,[i,S]),V=d.useMemo(()=>{const t=x?.session?.name;return t?w.get(t)??null:null},[x,w]),le=je([K.session,K.bead,"agent."],()=>{c(),r.refresh(),u.refresh()}),ce=d.useMemo(()=>st(i),[i]),h=Ne(),L=d.useCallback(async(t,a)=>{if(!h){U({sessionId:t.sessionId,action:a}),W(null),F(null);try{await ye(t.sessionId,{action:a,request_id:t.pending.request_id}),W(`responded to ${t.agentName}`),await p.refresh()}catch(g){F(g instanceof Error?g.message:"response failed")}finally{U(null)}}},[p,h]),A=d.useMemo(()=>Array.from(new Set(i.filter(t=>!se(t)).map(t=>E(t).label))).sort((t,a)=>t.localeCompare(a)),[i]);d.useEffect(()=>{v!==""&&!A.includes(v)&&B("")},[A,v]);const Y=d.useMemo(()=>{const t=M.trim().toLowerCase();return i.filter(a=>{if(v!==""&&E(a).label!==v)return!1;const g=J(s,"agents",a.name);return C&&!Xe(a,g)?!1:t.length===0?!0:Je(a).some(b=>b.toLowerCase().includes(t))})},[i,v,C,M,s]),de=d.useMemo(()=>t=>Re(J(s,"agents",t.name)),[s]),G=l!==null&&i.length===0,ue=G?"Agent roster unavailable.":i.length===0?"No agents configured.":"No agents match the current search or filter.",me=d.useMemo(()=>[{key:"name",label:"Agent",sortable:!0,sortValue:t=>P(t),render:t=>{const a=Me(t),g=t.display_name&&t.display_name!==t.name?t.display_name:t.provider??t.model??"",b=!t.session,ge=b?`${t.name} — configured but not running; detail will show no live session`:`Open drilldown for ${t.name}`,pe=b?"text-fg-muted":"text-fg";return e.jsxs("div",{className:"min-w-0",children:[e.jsx(I,{to:`/agents/${encodeURIComponent(ee(t))}`,className:`block ${pe} truncate hover:text-accent focus-mark ${a?"font-normal italic":"font-medium"}`,title:ge,children:P(t)}),g&&e.jsx("div",{className:"text-label uppercase tracking-wider text-fg-faint mt-1 truncate",children:g})]})}},{key:"state",label:"State",sortable:!0,sortValue:t=>t.state,render:t=>e.jsx($,{tone:T(t.state),label:t.state,...t.session?.attached?{trailing:"att"}:{},...t.unavailable_reason?{title:`unavailable: ${t.unavailable_reason}`}:{}}),className:"w-32"},{key:"activity",label:"Activity",sortable:!0,sortValue:t=>t.activity??"",render:t=>{const a=N.get(t.name);return a!==void 0?e.jsxs("div",{className:"min-w-0",children:[e.jsx($,{tone:"stuck",label:"needs you"}),e.jsx("p",{className:"mt-1 truncate text-fg-muted",title:a.pending.prompt,children:a.pending.prompt??a.pending.kind})]}):e.jsx("span",{className:"text-fg-muted",children:t.activity??(t.running?"running":"·")})},className:"w-28"},{key:"context",label:"Context",sortable:!0,sortValue:t=>X(t)??-1,align:"right",render:t=>{const a=X(t);if(typeof a!="number")return e.jsx("span",{className:"text-fg-faint",children:"·"});const g=typeof t.context_pct=="number"&&t.context_pct!==a?`gc reports ${t.context_pct}% against ${t.context_window??"?"}-token window; scaled to model's true window`:void 0;return e.jsxs("span",{title:g,className:`tnum ${a>=95?"text-accent font-medium":a>=80?"text-warn font-medium":"text-fg-muted"}`,children:[a,"%"]})},className:"w-24"},{key:"last_active",label:"Last active",sortable:!0,sortValue:t=>t.session?.last_activity??"",render:t=>{const a=t.session?.last_activity;return a?e.jsx("span",{className:"tnum text-fg-muted",children:ae(a,f)}):e.jsx("span",{className:"text-fg-faint tnum",children:"·"})},className:"w-32"},{key:"actions",label:"",render:t=>{if(!t.session)return null;const a=N.get(t.name);return e.jsxs("div",{className:"flex justify-end gap-2",children:[a!==void 0&&e.jsxs(e.Fragment,{children:[h&&e.jsx(ke,{}),e.jsx(y,{size:"sm",tone:"quiet",title:h?H:void 0,disabled:h||j?.sessionId===a.sessionId,onClick:()=>{L(a,"approve")},children:j?.sessionId===a.sessionId&&j.action==="approve"?"Approving":"Approve"}),e.jsx(y,{size:"sm",tone:"quiet",title:h?H:void 0,disabled:h||j?.sessionId===a.sessionId,onClick:()=>{L(a,"deny")},children:j?.sessionId===a.sessionId&&j.action==="deny"?"Denying":"Deny"}),e.jsx(Ze,{command:we(t.name)})]}),e.jsx(y,{size:"sm",tone:"quiet",onClick:()=>q(t.name),children:"Peek"})]})},align:"right",className:"w-80"}],[L,f,N,h,j]);return e.jsxs("section",{children:[e.jsx(Pe,{title:"Agents",synopsis:G?"Agent roster unavailable.":ce,meta:e.jsxs(e.Fragment,{children:[e.jsx(Oe,{state:le}),l&&e.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:l}),e.jsx(Ee,{show:n?.partial===!0,label:"roster partial",title:n?.partial_errors?.join(` +import{r as d,s as T,j as e,L as I,u as te,S as $,B as y,a as fe,b as R,l as xe,c as he,d as be,e as ve,f as je,g as Ne,h as ye,R as ke,i as H,k as we,G as K,m as Ce,n as Se,o as Ae}from"./index-BDHAaQRP.js";import{e as X}from"./context-window-Cu9zl36t.js";import{r as J,a as Re}from"./routeHighlight-B30gQO2o.js";import{i as $e,c as O,a as Ie,s as _e,b as se,d as E,e as Me,L as Le}from"./projectOf-mIrvrzQE.js";import{M as ne}from"./constants-D5DlRFFg.js";import{P as Pe}from"./PageHeader-BW5bf722.js";import{S as Oe,P as Ee}from"./SseIndicator-Dw8_ai2P.js";import{f as ae}from"./time-BVuL_AnL.js";import{L as ie,i as Q}from"./LiveSessionPeek-VUsvyqKB.js";import{T as Te}from"./Table-COJvPKIS.js";import{l as Be}from"./agentReads-BYWP7eVX.js";import"./format-fte2CeYD.js";function qe(s){const n=s.indexOf("-");if(n<=0)return!1;const o=s.slice(0,n),l=s.slice(n+1);return!l||!/^[a-z0-9]+$/.test(l)||!(o==="gc"||o==="td"||o==="th"||/^[a-z]{4}$/.test(o))?!1:/[0-9]/.test(l)}function ze(s){const n=s.trim();if(qe(n))return{role:n,sessionId:n};for(let o=n.length-1;o>=0;o--){const l=n.charAt(o);if(l!=="-"&&l!=="_"&&l!=="/")continue;const c=n.slice(o+1);if(c&&/^(?:gc|td|th|[a-z]{4})-[a-z0-9]{1,32}$/.test(c))return{role:n.slice(0,o),sessionId:c}}return{role:n}}const We="in_progress";function De(s){return Ie(_e(s).label)}function Fe(s){const n=O(s.template??"");return n.length>0?n:O(s.session_name??s.id)}function Z(s){const n=s.session.last_active?Date.parse(s.session.last_active):NaN;return Number.isFinite(n)?n:0}function Ue(s,n){const o=new Map;for(const r of n){if(r.status!==We)continue;const i=r.assignee?.trim();if(!i)continue;const{sessionId:m}=ze(i);m&&!o.has(m)&&o.set(m,r)}const l=[];for(const r of s){if(!$e(r))continue;const i=o.get(r.id);l.push({session:r,rig:De(r),worker:Fe(r),...i?{bead:i}:{}})}l.sort((r,i)=>Z(i)-Z(r));const c=new Map;for(const r of l)c.set(r.rig,(c.get(r.rig)??0)+1);const u=Array.from(c,([r,i])=>({rig:r,count:i})).sort((r,i)=>i.count-r.count||r.rig.localeCompare(i.rig));return{workers:l,byRig:u,total:l.length}}function Ve(s){if(s.total===0)return"No workers active right now.";const n=s.total===1?"worker":"workers",o=s.byRig.map(l=>`${l.rig} (${l.count})`).join(", ");return`${s.total} ${n} active across ${o}.`}function Ye({worker:s,accent:n,onPeek:o}){const l=te(),{session:c,rig:u,bead:r}=s,i=n?T(c.state):"neutral";return e.jsx("li",{className:"px-2 py-2 -mx-2 rounded-sm transition-colors duration-150 ease-out-quart hover:bg-surface-tint/60",children:e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0 text-body text-fg",children:[e.jsxs("button",{type:"button",onClick:()=>o(c.id),className:"group text-left cursor-pointer focus-mark",title:`Open ${u} · ${s.worker} transcript`,children:[e.jsx("span",{className:"font-medium group-hover:text-accent",children:u}),e.jsxs("span",{className:"text-fg-faint","aria-hidden":"true",children:[" ","·"," "]}),e.jsx("span",{className:"text-fg-muted group-hover:text-accent",children:s.worker})]}),r&&e.jsxs(I,{to:`/beads?bead=${encodeURIComponent(r.id)}`,className:"hover:text-accent focus-mark",title:`Open ${r.id}`,children:[e.jsxs("span",{className:"text-fg-faint","aria-hidden":"true",children:[" ","→"," "]}),e.jsx("span",{className:"tnum text-fg-muted",children:r.id}),e.jsxs("span",{className:"text-fg-muted",children:[": ",r.title]})]})]}),e.jsxs("div",{className:"flex items-baseline gap-3 shrink-0",children:[e.jsx($,{tone:i,label:c.state}),e.jsx("span",{className:"tnum text-fg-muted w-10 text-right",children:ae(c.last_active,l)}),e.jsx(y,{size:"sm",tone:"quiet",onClick:()=>o(c.id),children:"Peek"})]})]})})}function Ge(s){return s.running===!0||s.state==="active"||s.state==="running"}function He({beads:s,sessions:n,sessionsLoading:o,sessionsError:l}){const c=d.useMemo(()=>Ue(n,s),[n,s]),u=d.useMemo(()=>Ve(c),[c]),[r,i]=d.useState(null),m=d.useMemo(()=>r?c.workers.find(f=>f.session.id===r)??null:null,[c.workers,r]),k=d.useMemo(()=>c.workers.findIndex(f=>T(f.session.state)==="stuck"),[c.workers]),p=n.length===0,w=l!==null&&p,N=o&&p,_=w||N?"—":c.total;return e.jsxs("section",{className:"mb-10","aria-label":"Workers active",children:[e.jsxs("header",{className:"flex items-baseline justify-between border-b border-rule pb-2 mb-4",children:[e.jsx("h2",{className:"text-headline text-fg",children:"Workers active"}),e.jsx("span",{className:"text-label tnum text-fg-muted",children:_})]}),w?e.jsx("p",{className:"text-body text-fg-muted",role:"status",children:"Worker status unavailable."}):N?e.jsx("p",{className:"text-body text-fg-muted",role:"status",children:"Checking worker status…"}):c.total===0?e.jsx("p",{className:"text-body text-fg-muted",children:"No workers active right now."}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-body text-fg-muted mb-4",children:u}),e.jsx("ul",{className:"space-y-1",children:c.workers.map((f,C)=>e.jsx(Ye,{worker:f,accent:C===k,onPeek:i},f.session.id))})]}),e.jsx(ne,{open:m!==null,onClose:()=>i(null),title:m?`${m.rig} · ${m.worker}`:"Transcript",caption:m?.bead?e.jsxs(I,{to:`/beads?bead=${encodeURIComponent(m.bead.id)}`,className:"text-fg-muted hover:text-accent focus-mark",title:`Open ${m.bead.id}`,children:[e.jsx("span",{className:"tnum",children:m.bead.id}),e.jsxs("span",{children:[": ",m.bead.title]})]}):"Live transcript from the supervisor's session stream.",widthClass:"max-w-5xl",children:e.jsx(ie,{sessionId:r,stream:m?Ge(m.session):!1,showBadge:!0,showCaption:!0})})]})}function ee(s){return s.session?.name??s.name}function Ke(s){return!s.suspended&&(s.state==="active"||s.state==="running"||s.running===!0)}function Xe(s,n){return Ke(s)||n==="attention"}function P(s){const n=O(s.name);return se(s)?n:`${E(s).label} · ${n}`}const Je=s=>[s.name,s.display_name,s.pool,s.rig,s.provider,s.model].filter(n=>typeof n=="string"&&n.length>0);function ft(){const s=fe(),{data:n,loading:o,error:l,refresh:c}=R("agents",Be),u=R("sessions",xe),r=R("beads:in-flight",()=>he()),i=d.useMemo(()=>n?.items??[],[n]),m=d.useMemo(()=>(u.data?.items??[]).map(t=>t.id).sort(),[u.data]),k=d.useMemo(()=>i.map(t=>t.name).sort(),[i]),p=R(`agent-pending:${k.join(",")}:${m.join(",")}`,()=>be(i,u.data?.items??[])),w=d.useMemo(()=>{const t=new Map;for(const a of u.data?.items??[])a.session_name&&t.set(a.session_name,a.id);return t},[u.data]),N=d.useMemo(()=>{const t=new Map;for(const a of p.data??[])t.set(a.agentName,a);return t},[p.data]),_=d.useMemo(()=>{const t=(p.data??[]).map(g=>({agentName:g.agentName,...g.pending.prompt===void 0?{}:{prompt:g.pending.prompt}})),a=new Map(i.map(g=>[g.name,g]));return ve(i,t).flatMap(g=>{const b=a.get(g.name);return b===void 0?[]:[{need:g,label:P(b),slug:ee(b)}]})},[i,p.data]),f=te(),[C,oe]=d.useState(!0),[M,re]=d.useState(""),[v,B]=d.useState(""),[S,q]=d.useState(null),[z,W]=d.useState(null),[D,F]=d.useState(null),[j,U]=d.useState(null),x=d.useMemo(()=>S===null?null:i.find(t=>t.name===S)??null,[i,S]),V=d.useMemo(()=>{const t=x?.session?.name;return t?w.get(t)??null:null},[x,w]),le=je([K.session,K.bead,"agent."],()=>{c(),r.refresh(),u.refresh()}),ce=d.useMemo(()=>st(i),[i]),h=Ne(),L=d.useCallback(async(t,a)=>{if(!h){U({sessionId:t.sessionId,action:a}),W(null),F(null);try{await ye(t.sessionId,{action:a,request_id:t.pending.request_id}),W(`responded to ${t.agentName}`),await p.refresh()}catch(g){F(g instanceof Error?g.message:"response failed")}finally{U(null)}}},[p,h]),A=d.useMemo(()=>Array.from(new Set(i.filter(t=>!se(t)).map(t=>E(t).label))).sort((t,a)=>t.localeCompare(a)),[i]);d.useEffect(()=>{v!==""&&!A.includes(v)&&B("")},[A,v]);const Y=d.useMemo(()=>{const t=M.trim().toLowerCase();return i.filter(a=>{if(v!==""&&E(a).label!==v)return!1;const g=J(s,"agents",a.name);return C&&!Xe(a,g)?!1:t.length===0?!0:Je(a).some(b=>b.toLowerCase().includes(t))})},[i,v,C,M,s]),de=d.useMemo(()=>t=>Re(J(s,"agents",t.name)),[s]),G=l!==null&&i.length===0,ue=G?"Agent roster unavailable.":i.length===0?"No agents configured.":"No agents match the current search or filter.",me=d.useMemo(()=>[{key:"name",label:"Agent",sortable:!0,sortValue:t=>P(t),render:t=>{const a=Me(t),g=t.display_name&&t.display_name!==t.name?t.display_name:t.provider??t.model??"",b=!t.session,ge=b?`${t.name} — configured but not running; detail will show no live session`:`Open drilldown for ${t.name}`,pe=b?"text-fg-muted":"text-fg";return e.jsxs("div",{className:"min-w-0",children:[e.jsx(I,{to:`/agents/${encodeURIComponent(ee(t))}`,className:`block ${pe} truncate hover:text-accent focus-mark ${a?"font-normal italic":"font-medium"}`,title:ge,children:P(t)}),g&&e.jsx("div",{className:"text-label uppercase tracking-wider text-fg-faint mt-1 truncate",children:g})]})}},{key:"state",label:"State",sortable:!0,sortValue:t=>t.state,render:t=>e.jsx($,{tone:T(t.state),label:t.state,...t.session?.attached?{trailing:"att"}:{},...t.unavailable_reason?{title:`unavailable: ${t.unavailable_reason}`}:{}}),className:"w-32"},{key:"activity",label:"Activity",sortable:!0,sortValue:t=>t.activity??"",render:t=>{const a=N.get(t.name);return a!==void 0?e.jsxs("div",{className:"min-w-0",children:[e.jsx($,{tone:"stuck",label:"needs you"}),e.jsx("p",{className:"mt-1 truncate text-fg-muted",title:a.pending.prompt,children:a.pending.prompt??a.pending.kind})]}):e.jsx("span",{className:"text-fg-muted",children:t.activity??(t.running?"running":"·")})},className:"w-28"},{key:"context",label:"Context",sortable:!0,sortValue:t=>X(t)??-1,align:"right",render:t=>{const a=X(t);if(typeof a!="number")return e.jsx("span",{className:"text-fg-faint",children:"·"});const g=typeof t.context_pct=="number"&&t.context_pct!==a?`gc reports ${t.context_pct}% against ${t.context_window??"?"}-token window; scaled to model's true window`:void 0;return e.jsxs("span",{title:g,className:`tnum ${a>=95?"text-accent font-medium":a>=80?"text-warn font-medium":"text-fg-muted"}`,children:[a,"%"]})},className:"w-24"},{key:"last_active",label:"Last active",sortable:!0,sortValue:t=>t.session?.last_activity??"",render:t=>{const a=t.session?.last_activity;return a?e.jsx("span",{className:"tnum text-fg-muted",children:ae(a,f)}):e.jsx("span",{className:"text-fg-faint tnum",children:"·"})},className:"w-32"},{key:"actions",label:"",render:t=>{if(!t.session)return null;const a=N.get(t.name);return e.jsxs("div",{className:"flex justify-end gap-2",children:[a!==void 0&&e.jsxs(e.Fragment,{children:[h&&e.jsx(ke,{}),e.jsx(y,{size:"sm",tone:"quiet",title:h?H:void 0,disabled:h||j?.sessionId===a.sessionId,onClick:()=>{L(a,"approve")},children:j?.sessionId===a.sessionId&&j.action==="approve"?"Approving":"Approve"}),e.jsx(y,{size:"sm",tone:"quiet",title:h?H:void 0,disabled:h||j?.sessionId===a.sessionId,onClick:()=>{L(a,"deny")},children:j?.sessionId===a.sessionId&&j.action==="deny"?"Denying":"Deny"}),e.jsx(Ze,{command:we(t.name)})]}),e.jsx(y,{size:"sm",tone:"quiet",onClick:()=>q(t.name),children:"Peek"})]})},align:"right",className:"w-80"}],[L,f,N,h,j]);return e.jsxs("section",{children:[e.jsx(Pe,{title:"Agents",synopsis:G?"Agent roster unavailable.":ce,meta:e.jsxs(e.Fragment,{children:[e.jsx(Oe,{state:le}),l&&e.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:l}),e.jsx(Ee,{show:n?.partial===!0,label:"roster partial",title:n?.partial_errors?.join(` `)??"one or more agent backends unavailable"}),e.jsx(y,{size:"sm",onClick:()=>{c()},disabled:o,children:o?"Refreshing":"Refresh"})]})}),e.jsx(Qe,{rows:_}),e.jsx(He,{beads:r.data?.items??[],sessions:u.data?.items??[],sessionsLoading:u.loading,sessionsError:u.error}),e.jsxs("header",{className:"flex items-baseline justify-between border-b border-rule pb-2 mb-4",children:[e.jsx("h2",{className:"text-headline text-fg",children:"Available agents"}),e.jsx("span",{className:"text-label tnum text-fg-muted",children:i.length})]}),e.jsxs("div",{className:"mb-6 space-y-3",children:[e.jsx(Le,{value:M,onChange:re,placeholder:"Search agents by alias, rig, pool, provider",matchCount:Y.length,totalCount:i.length,ariaLabel:"Search agents"}),e.jsxs("div",{className:"flex items-baseline gap-6",children:[e.jsxs("label",{className:"inline-flex items-baseline gap-2 text-label uppercase tracking-wider text-fg-muted cursor-pointer hover:text-fg transition-colors duration-150 ease-out-quart",children:[e.jsx("input",{type:"checkbox",checked:C,onChange:t=>oe(t.target.checked),style:{accentColor:"oklch(var(--fg-muted))"},className:"translate-y-[2px]"}),e.jsx("span",{children:"running"})]}),A.length>1&&e.jsxs("label",{className:"inline-flex items-baseline gap-2 text-label uppercase tracking-wider text-fg-muted",children:[e.jsx("span",{children:"rig"}),e.jsxs("select",{value:v,onChange:t=>B(t.target.value),"aria-label":"Rig filter",className:"text-label uppercase tracking-wider text-fg-muted bg-transparent border-0 focus-mark cursor-pointer hover:text-fg transition-colors duration-150 ease-out-quart",children:[e.jsx("option",{value:"",children:"all rigs"}),A.map(t=>e.jsx("option",{value:t,children:t},t))]})]})]})]}),z&&e.jsx("div",{className:"mb-4 text-body text-fg-muted",role:"status",children:z}),D&&e.jsx("div",{className:"mb-4 text-body text-accent",role:"alert",children:D}),e.jsx(Te,{rows:Y,columns:me,rowKey:t=>t.name,rowProps:de,empty:ue,initialSort:{key:"last_active",dir:"desc"}}),e.jsx(ne,{open:S!==null,onClose:()=>q(null),title:x?.name??S??"Transcript",caption:x&&x.session&&!V?u.loading?"Resolving session…":`No live session matches "${x.session.name}".`:Q(x)?"Live transcript from the supervisor's session stream.":"Snapshot from the supervisor's transcript API.",widthClass:"max-w-5xl",children:e.jsx(ie,{sessionId:V,stream:Q(x),showBadge:!0,showCaption:!0})})]})}function Qe({rows:s}){return s.length===0?null:e.jsxs("section",{"aria-label":"Agents needing you",className:"mb-10",children:[e.jsxs("h2",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:["Needs you (",s.length,")"]}),e.jsx("ol",{className:"mt-3 divide-y divide-rule",children:s.map(({need:n,label:o,slug:l})=>e.jsxs("li",{className:"py-3",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx(I,{to:`/agents/${encodeURIComponent(l)}`,className:"focus-mark block min-w-0 truncate text-title text-fg hover:text-accent",children:o}),e.jsx($,{tone:Se(n.reason),label:Ce(n.reason)})]}),e.jsx("p",{className:"mt-1 text-body text-fg leading-snug",children:n.detail}),e.jsx("p",{className:"mt-0.5 text-body text-fg-muted leading-snug",children:Ae(n.action)})]},n.name))})]})}function Ze({command:s}){const[n,o]=d.useState("idle"),l=n==="copied"?"Copied":n==="failed"?"Copy failed":"Copy attach";return e.jsx(y,{size:"sm",tone:"quiet",title:s,onClick:()=>{et(s,o)},children:l})}async function et(s,n){try{await navigator.clipboard.writeText(s),n("copied")}catch{n("failed")}}function tt(s){if(s.suspended)return"suspended";switch(s.state){case"active":case"running":return"active";case"detached":return"detached";case"rate-limited":case"rate_limited":case"waiting":return"rate-limited";case"failed":case"closed":case"errored":case"stuck":return"stuck";default:return"idle"}}function st(s){if(s.length===0)return"No agents configured.";const n=new Map;for(const k of s){const p=tt(k);n.set(p,(n.get(p)??0)+1)}const o=[],l=n.get("active")??0,c=n.get("idle")??0,u=n.get("detached")??0,r=n.get("rate-limited")??0,i=n.get("stuck")??0,m=n.get("suspended")??0;return l>0&&o.push(`${l} active`),c>0&&o.push(`${c} idle`),u>0&&o.push(`${u} detached`),r>0&&o.push(`${r} rate-limited`),i>0&&o.push(`${i} stuck`),m>0&&o.push(`${m} suspended`),o.join(", ")+"."}export{ft as AgentsPage,P as agentRowLabel,st as buildAgentSynopsis,Ke as isRunningAgent,Xe as isVisibleUnderRunning,T as stateTone}; diff --git a/internal/api/dashboardspa/dist/assets/BeadDetailModal-DpGateYl.js b/internal/api/dashboardspa/dist/assets/BeadDetailModal-B7DCLOq5.js similarity index 99% rename from internal/api/dashboardspa/dist/assets/BeadDetailModal-DpGateYl.js rename to internal/api/dashboardspa/dist/assets/BeadDetailModal-B7DCLOq5.js index 4c4a7fe013..430b81f2bd 100644 --- a/internal/api/dashboardspa/dist/assets/BeadDetailModal-DpGateYl.js +++ b/internal/api/dashboardspa/dist/assets/BeadDetailModal-B7DCLOq5.js @@ -1 +1 @@ -import{r as h,u as K,a8 as H,a9 as O,w as V,v as E,aa as q,K as W,j as n,S as Y,ab as Z,L as X,B as J}from"./index-DDS7Ehww.js";import{f as Q}from"./format-fte2CeYD.js";import{F as x}from"./Field-BEMyWxxD.js";import{a as P,L as ee}from"./LiveSessionPeek-F4FmVdxt.js";import{M as U}from"./constants-CQJOeNM1.js";import{f as D}from"./time-BVuL_AnL.js";function te(e,t){if(e.length===0||t.length===0)return null;const s=t.filter(r=>r.state==="active");return F(e,s)??F(e,t)}function F(e,t){for(const s of t)if(se(s,e))return s;return null}function se(e,t){return e.alias===t||e.pool===t||e.alias!==void 0&&A(e.alias,["/","."])===t||e.session_name!==void 0&&A(e.session_name,["__","--"])===t}function A(e,t){let s=-1,r=0;for(const i of t){const l=e.lastIndexOf(i);l>s&&(s=l,r=i.length)}return s<0?e:e.slice(s+r)}const ne=/^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;function re(e,t,s){return`${e}:${s}:${t}`}function b(e,t,s){e?.(t,s)}const ie=/^pr\/(\d{1,9})$/,le=/^issue\/(\d{1,9})$/;function oe(e){const t=e.trim();if(t.length===0)return{ok:!1,error:"empty ref"};const s=ie.exec(t);if(s?.[1])return{ok:!0,type:"github_pr",value:s[1]};const r=le.exec(t);return r?.[1]?{ok:!0,type:"github_issue",value:r[1]}:ne.test(t)?{ok:!0,type:"bead",value:t}:{ok:!1,error:"unrecognised ref"}}function M(e){if(typeof e!="string")return null;const t=e.trim();return/^https?:\/\//i.test(t)?t:null}function v(e,t,s){return re(e,t,s)}function ae(e){return{key:v("bead",e.id,e.scope),type:"bead",ref:e.id}}function _(e,t){const s=e.stats.get(t);if(s)return s;const r={relation:t,resolved:0,unresolved:0,nCandidates:0};return e.stats.set(t,r),r}function y(e,t){e.nodesByKey.has(t.key)||(e.nodesByKey.set(t.key,t),e.view.nodes.push(t))}function w(e,t,s,r,i,l){e.view.edges.push({from:t,to:s,relation:r,provenance:i,resolved:l})}function N(e,t,s,r,i){const l=ae(s);y(e,{...l,title:s.title,status:s.status,url:null,fetchedAt:i,unresolved:!1}),w(e,t,l.key,r,"supervisor",!0),_(e,r).resolved+=1,b(e.recorder,r,"resolved")}function ue(e,t){return{focus:e,nodes:[],edges:[],stats:[],partial:!1,generatedAt:t,asOf:null}}function $(e,t){return e===null?t:t===null||Date.parse(e)<=Date.parse(t)?e:t}function ce(e,t,s={}){const i=(s.now??(()=>new Date))().toISOString(),l=s.supervisorFetchedAt??null,u=s.githubFetchedAt??null,a=de(e,t),o=ue(a.focus,i);o.partial=s.partial??!1;const c={view:o,nodesByKey:new Map,stats:new Map,recorder:s.recorder??(()=>{})};if(y(c,a.focusNode),!a.focusResolved)return o.partial=!0,L(c,l,u),o;const f=a.focusNode.key;if(a.beadFocus)for(const m of a.beads)pe(c,m,f,e,l,u);else for(const m of a.beads)N(c,f,m,"bead",l);return L(c,l,u),o}function de(e,t){if(t.type==="github_pr"||t.type==="github_issue"){const u=t.type==="github_pr"?"github_pr":"github_issue",a=t.type==="github_pr"?`pr/${t.value}`:`issue/${t.value}`,c=(t.type==="github_pr"?e.beadsForPr.get(t.value)??[]:e.beadsForIssue.get(t.value)??[]).map(m=>e.beads.get(m)).filter(m=>m!==void 0),f={key:v(u,t.value,"github"),type:u,ref:a};return{focus:f,focusNode:{...f,title:null,status:null,url:null,fetchedAt:null,unresolved:c.length===0,...c.length>1?{candidateCount:c.length}:{}},beads:c,focusResolved:c.length>0,beadFocus:!1}}const s=e.beads.get(t.value)??e.allBeads.get(t.value);if(s!==void 0){const u=fe(s);return{focus:u,focusNode:{...u,title:s.title,status:s.status,url:null,fetchedAt:null,unresolved:!1},beads:s.superseded?[]:[s],focusResolved:!0,beadFocus:!0}}const r=e.beadsForSession.get(t.value)??[],i=e.sessions.has(t.value);if(r.length>0||i){const u={key:v("session",t.value,"session"),type:"session",ref:t.value},a=r.map(c=>e.beads.get(c)).filter(c=>c!==void 0),o=i||a.length>0;return{focus:u,focusNode:{...u,title:e.sessions.get(t.value)?.title??null,status:e.sessions.get(t.value)?.state??null,url:null,fetchedAt:null,unresolved:!o},beads:a,focusResolved:o,beadFocus:!1}}const l={key:v("bead",t.value,"unknown"),type:"bead",ref:t.value};return{focus:l,focusNode:{...l,title:null,status:null,url:null,fetchedAt:null,unresolved:!0},beads:[],focusResolved:!1,beadFocus:!0}}function fe(e){return{key:v("bead",e.id,e.scope),type:"bead",ref:e.id}}function pe(e,t,s,r,i,l){if(t.parentBeadId){const a=r.beads.get(t.parentBeadId);a?N(e,s,a,"parent",i):me(e,s,t.parentBeadId,"parent")}const u=(r.childrenOf.get(t.id)??[]).filter(a=>a!==t.id);for(const a of u){const o=r.beads.get(a);o&&N(e,s,o,"child",i)}if(t.moleculeId){const a=(r.membersOfMolecule.get(t.moleculeId)??[]).filter(o=>o!==t.id&&o!==t.moleculeId);if(t.moleculeId!==t.id){const o=r.beads.get(t.moleculeId);o&&N(e,s,o,"molecule",i)}for(const o of a){const c=r.beads.get(o);c&&N(e,s,c,"molecule",i)}}if(t.prNumber&&B(e,s,"github_pr",`pr/${t.prNumber}`,t.prNumber,M(t.prUrl),"pr","supervisor",l),t.issueNumber&&B(e,s,"github_issue",`issue/${t.issueNumber}`,t.issueNumber,M(t.issueUrl),"issue","supervisor",l),t.sessionId){const a=r.sessions.get(t.sessionId),o={key:v("session",t.sessionId,"session"),type:"session",ref:t.sessionId};a?(y(e,{...o,title:a.title??a.alias??t.sessionName??null,status:a.state??null,url:null,fetchedAt:i,unresolved:!1}),w(e,s,o.key,"session","supervisor",!0),_(e,"session").resolved+=1,b(e.recorder,"session","resolved")):(y(e,{...o,title:t.sessionName??null,status:null,url:null,fetchedAt:i,unresolved:!0}),w(e,s,o.key,"session","supervisor",!1),_(e,"session").unresolved+=1,b(e.recorder,"session","unresolved"))}}function B(e,t,s,r,i,l,u,a,o){const c=v(s,i,"github");y(e,{key:c,type:s,ref:r,title:null,status:null,url:l,fetchedAt:o,unresolved:!0}),w(e,t,c,u,a,!1),_(e,u).unresolved+=1,b(e.recorder,u,"unresolved")}function me(e,t,s,r){const i=v("bead",s,"unknown");y(e,{key:i,type:"bead",ref:s,title:null,status:null,url:null,fetchedAt:null,unresolved:!0}),w(e,t,i,r,"supervisor",!1),_(e,r).unresolved+=1,b(e.recorder,r,"unresolved")}function L(e,t,s){e.view.stats=[...e.stats.values()].sort((i,l)=>i.relation.localeCompare(l.relation));let r=null;for(const i of e.view.nodes)r=$(r,i.fetchedAt);e.view.asOf=r??$(t,s)}function p(e,t){const s=e.metadata?.[t];if(typeof s=="string"){const r=s.trim();return r.length>0?r:void 0}if(typeof s=="number"&&Number.isFinite(s))return String(s)}function he(e,t){const s=e.metadata?.[t];if(typeof s=="number"&&Number.isInteger(s)&&s>=0)return s;if(typeof s=="string"&&/^\d+$/.test(s.trim()))return Number.parseInt(s.trim(),10)}const ge=["gc.scope_ref","scope_ref","scope_id"],xe=["gc.scope_kind","scope_kind"];function ve(e,t){let s;for(const i of ge){const l=p(e,i);if(l!==void 0){s=l;break}}let r;for(const i of xe){const l=p(e,i);if(l!==void 0){r=l;break}}return s===void 0?`city:${t}`:`${r??"rig"}:${s}`}const ye=/^github-pr:[^/]+\/[^/]+\/(\d+)$/,je=/\/(?:pull\/)?(\d+)(?:[/?#]|$)/;function Ne(e){const t=p(e,"evidence.pr_url"),s=p(e,"evidence.pr_number"),r=p(e,"evidence.artifact_path"),i=p(e,"pr_review.pr_number"),l=p(e,"pr_review.pr_url"),u=r?.match(ye),a=t?.match(je),o=s??u?.[1]??a?.[1]??i??void 0,c=t??l??void 0,f={};return o!==void 0&&(f.prNumber=o),c!==void 0&&(f.prUrl=c),f}function be(e,t){const{prNumber:s,prUrl:r}=Ne(e),i={id:e.id,title:e.title,status:e.status,scope:ve(e,t),superseded:!1},l={parentBeadId:p(e,"gc.parent_bead_id"),rootBeadId:p(e,"gc.root_bead_id"),moleculeId:p(e,"molecule_id"),prNumber:s,prUrl:r,issueNumber:p(e,"bugflow.github_issue_number")??p(e,"design_review.github_issue_number"),issueUrl:p(e,"bugflow.github_issue_url")??p(e,"design_review.github_issue_url"),sessionId:p(e,"session_id"),sessionName:p(e,"session_name"),stepId:p(e,"gc.step_id"),attempt:he(e,"gc.attempt")};for(const[u,a]of Object.entries(l))a!==void 0&&Object.assign(i,{[u]:a});return i}function T(e){return`${e.moleculeId}\0${e.stepId}`}function _e(e){const t=new Map;for(const s of e){if(s.moleculeId===void 0||s.stepId===void 0||s.attempt===void 0)continue;const r=T(s),i=t.get(r);(i===void 0||s.attempt>i)&&t.set(r,s.attempt)}for(const s of e){if(s.moleculeId===void 0||s.stepId===void 0||s.attempt===void 0)continue;const r=t.get(T(s));r!==void 0&&s.attemptbe(d,s));_e(r);const i=new Map,l=new Map,u=new Map,a=new Map,o=new Map,c=new Map,f=new Map;for(const d of r)i.set(d.id,d),!d.superseded&&(l.set(d.id,d),d.parentBeadId&&j(u,d.parentBeadId,d.id),d.moleculeId&&j(a,d.moleculeId,d.id),d.prNumber&&j(o,d.prNumber,d.id),d.issueNumber&&j(c,d.issueNumber,d.id),d.sessionId&&j(f,d.sessionId,d.id));const m=new Map;for(const d of t)m.set(d.id,d);return{beads:l,allBeads:i,childrenOf:u,membersOfMolecule:a,beadsForPr:o,beadsForIssue:c,beadsForSession:f,sessions:m}}function ke(e,t,s=null){const[r,i]=h.useState(s),[l,u]=h.useState(!1),[a,o]=h.useState(null),[c,f]=h.useState(!1),m=K();return h.useEffect(()=>{if(!e||!t)return;if(s&&s.id===t&&s.description!==void 0){i(s),o(null),f(!1);return}i(s?.id===t?s:null),u(!0),o(null),f(!1);let d=!1;return(async()=>{try{const g=await H(t);d||i(g)}catch(g){if(d)return;g instanceof O&&g.status===404?f(!0):o(Se(g))}finally{d||u(!1)}})(),()=>{d=!0}},[e,t,s]),{bead:r,loading:l,error:a,notFound:c,now:m}}function Se(e){return e instanceof O?e.status===void 0?e.message:`${e.status} ${e.message}`:e instanceof Error?e.message:"fetch failed"}function Ie(e){return e.partial===!0||(e.partial_errors?.length??0)>0||(e.next_cursor?.length??0)>0}function Re(e,t){return Ie(e)||typeof e.total=="number"&&e.total>t}const Ee=1e3;async function Fe(e){const t=oe(e);if(!t.ok)throw new Error(t.error);const s=V("load supervisor entity links"),r=new Date().toISOString(),i=await E().listBeads(s,{limit:Ee}),l=Ae(i.items??[]);let u=Re(i,l.length),a=[];try{const c=await E().listSessions(s);a=q(c),u||=$e(c)}catch{u=!0}const o=we(l,a,s);return ce(o,t,{partial:u,supervisorFetchedAt:r,githubFetchedAt:null})}function Ae(e){return e.map(Me)}function Me(e){const t={id:e.id,title:e.title,status:e.status,issue_type:e.issue_type,priority:e.priority??null,created_at:e.created_at};return e.description!==void 0&&(t.description=e.description),e.assignee!==void 0&&(t.assignee=e.assignee),Array.isArray(e.labels)&&(t.labels=e.labels),e.metadata!==void 0&&(t.metadata=e.metadata),e.ref!==void 0&&(t.ref=e.ref),e.parent!==void 0&&(t.parent=e.parent),e.from!==void 0&&(t.from=e.from),e.ephemeral!==void 0&&(t.ephemeral=e.ephemeral),e.needs!==void 0&&(t.needs=e.needs),e.dependencies!==void 0&&(t.dependencies=e.dependencies),e.updated_at!==void 0&&(t.updated_at=e.updated_at),t}function $e(e){return e.partial===!0||(e.partial_errors?.length??0)>0}function Be(e){const[t,s]=h.useState(null),[r,i]=h.useState(!1),[l,u]=h.useState(null);return h.useEffect(()=>{if(e===null||e.length===0){s(null),u(null),i(!1);return}let a=!1;return i(!0),u(null),(async()=>{try{const o=await Fe(e);a||s(o)}catch(o){if(a)return;u(W(o,"related entities failed")),s(null)}finally{a||i(!1)}})(),()=>{a=!0}},[e]),{view:t,loading:r,error:l}}function Le(e){const t=e.metadata;if(!t)return{};const s={};return t["gc.kind"]&&(s.kind=t["gc.kind"]),t["gc.source_bead_id"]&&(s.originBeadId=t["gc.source_bead_id"]),t["gc.formula_contract"]&&(s.formulaContract=t["gc.formula_contract"]),t["gc.run_target"]?s.runTarget=t["gc.run_target"]:t["gc.routed_to"]&&(s.runTarget=t["gc.routed_to"]),s}function Te(e,t){return t.kind==="run"?"template":e.issue_type==="molecule"?"wisp":"work"}function Ce({bead:e}){const t=Le(e),s=Te(e,t);return n.jsxs("div",{className:"space-y-8",children:[s==="template"&&n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Formula template"}),n.jsxs("p",{className:"text-body text-fg-muted max-w-prose",children:["This bead is a recipe, not actionable work. Every"," ",e.ref?n.jsx("code",{className:"text-fg-muted",children:e.ref}):"wisp"," instance is instantiated from this template. The ",n.jsx("span",{className:"text-fg-muted",children:"in_progress"})," ","status is the gc-system convention for ",'"',"available for instantiation",'"'," — do not act on it, nudge it, or close it."]})]}),s==="wisp"&&n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Formula instance"}),n.jsxs("p",{className:"text-body text-fg-muted max-w-prose",children:["One run of the"," ",e.title?n.jsx("code",{className:"text-fg-muted",children:e.title}):"formula"," recipe."]})]}),n.jsxs("dl",{className:"grid grid-cols-2 sm:grid-cols-4 gap-x-8 gap-y-5",children:[n.jsx(x,{label:"Status",children:n.jsx(Y,{tone:Z(e.status),label:e.status})}),n.jsx(x,{label:"Type",children:e.issue_type}),n.jsx(x,{label:"Assignee",children:e.assignee||"·"}),n.jsx(x,{label:"Created",children:n.jsx("span",{className:"tnum",children:Q(e.created_at)})})]}),s==="template"&&(t.formulaContract||t.originBeadId||t.runTarget)&&n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Template origin"}),n.jsx("p",{className:"text-body text-fg-muted max-w-prose mb-4",children:"Where this formula came from, kept for traceability. The origin bead and target may be stale; the formula itself is now used wherever the pool dispatches it."}),n.jsxs("dl",{className:"grid grid-cols-2 sm:grid-cols-3 gap-x-8 gap-y-3",children:[t.formulaContract&&n.jsx(x,{label:"Contract",children:n.jsx("code",{className:"text-fg-muted",children:t.formulaContract})}),e.ref&&n.jsx(x,{label:"Ref",children:n.jsx("code",{className:"text-fg-muted",children:e.ref})}),t.originBeadId&&n.jsx(x,{label:"Origin bead",children:n.jsx("code",{className:"text-fg-muted",children:t.originBeadId})}),t.runTarget&&n.jsx(x,{label:"Origin target",children:n.jsx("span",{className:"text-fg-muted truncate",title:t.runTarget,children:t.runTarget})})]})]}),Array.isArray(e.labels)&&e.labels.length>0&&n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Labels"}),n.jsx("div",{className:"flex flex-wrap gap-x-3 gap-y-1",children:e.labels.map(r=>n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:r},r))})]}),n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:s==="template"?"Recipe":"Description"}),e.description&&e.description.length>0?n.jsx("pre",{className:"text-body whitespace-pre-wrap leading-relaxed text-fg font-sans",children:e.description}):n.jsx("p",{className:"text-body text-fg-muted italic",children:"No description."})]})]})}function Oe({node:e,onOpenBead:t}){const{deps:s,blocks:r}=e,i=s.length>0||r.length>0;return n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Dependencies"}),i?n.jsxs("div",{className:"space-y-6",children:[s.length>0&&n.jsxs("div",{children:[n.jsxs("p",{className:"text-label uppercase tracking-wider text-fg-muted mb-2",children:["Needs ",n.jsx("span",{className:"tnum",children:s.length})]}),n.jsx("ul",{className:"space-y-1",children:s.map(l=>n.jsx(C,{relation:l.kind==="needs"?null:l.kind,targetId:l.id,targetTitle:l.bead?.title??null,...l.bead&&t?{onOpenBead:t}:{}},`needs-${l.id}`))})]}),r.length>0&&n.jsxs("div",{children:[n.jsxs("p",{className:"text-label uppercase tracking-wider text-fg-muted mb-2",children:["Blocks ",n.jsx("span",{className:"tnum",children:r.length})]}),n.jsx("ul",{className:"space-y-1",children:r.map(l=>n.jsx(C,{relation:null,targetId:l.id,targetTitle:l.title,...t?{onOpenBead:t}:{}},`blocks-${l.id}`))})]})]}):n.jsx("p",{className:"text-body text-fg-muted italic",children:"No dependencies."})]})}function C({relation:e,targetId:t,targetTitle:s,onOpenBead:r}){const i=n.jsxs(n.Fragment,{children:[e&&n.jsxs("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:[e," "]}),n.jsx("span",{className:"tnum text-fg-muted",children:t}),s&&n.jsxs("span",{className:"text-fg",children:[" · ",s]})]});return n.jsx("li",{className:"text-body leading-snug",children:r?n.jsx("button",{type:"button",onClick:()=>r(t),className:"text-left text-fg-muted hover:text-fg focus-mark rounded-sm",title:`Open ${t}`,children:i}):n.jsxs("span",{title:"Outside the fetched window",children:[i," ",n.jsx("span",{className:"text-warn text-label uppercase tracking-wider",children:"unresolved"})]})})}function Pe({open:e,onClose:t,session:s,beadTitle:r}){const i=P(s);return n.jsx(U,{open:e,onClose:t,title:r,caption:s===null?"No live session resolved for this bead.":i?"Live transcript from the supervisor's session stream.":"Snapshot from the supervisor's transcript API.",widthClass:"max-w-5xl",children:n.jsx(ee,{sessionId:s?.id??null,stream:i,showBadge:!0,showCaption:!0})})}const Ue=6,De=3600*1e3,ze=3,Ge=["bead","formula_run","session","github_pr","github_issue","order_run"],Ke={bead:"Beads",session:"Sessions",github_pr:"Pull requests",github_issue:"Issues",formula_run:"Formula runs",order_run:"Order runs"};function He({view:e,loading:t,error:s,now:r,onOpenBead:i}){const[l,u]=h.useState(!1),a=h.useMemo(()=>Je(e),[e]),o=h.useMemo(()=>Xe(e),[e]),c=o.unresolved>=ze;return n.jsxs("section",{className:"mt-12",children:[n.jsxs("header",{className:"flex items-baseline justify-between mb-4 gap-3",children:[n.jsx("h2",{className:"text-label uppercase tracking-wider text-fg-faint",children:"Related"}),n.jsxs("div",{className:"flex items-baseline gap-3 min-w-0",children:[e&&e.asOf&&n.jsxs("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum shrink-0",children:["as of ",D(e.asOf,r)]}),n.jsx(Ve,{loading:t,counts:o,showMark:c})]})]}),s!==null?n.jsx("p",{className:"text-body text-accent",role:"alert",children:s}):t&&e===null?n.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading related entities."}):e===null||a.length===0?n.jsx("p",{className:"text-body text-fg-muted italic",children:"No related entities."}):n.jsxs(n.Fragment,{children:[e.partial&&n.jsx("p",{className:"text-label uppercase tracking-wider text-warn mb-4",role:"status",children:"Partial: some sources did not load. Links may be incomplete."}),n.jsx("button",{type:"button",onClick:()=>u(f=>!f),className:"text-label uppercase tracking-wider text-fg-faint hover:text-fg focus-mark mb-4","aria-expanded":l,children:l?"Hide detail":"Show detail"}),l&&n.jsx("div",{className:"space-y-8",children:a.map(f=>n.jsx(qe,{type:f.type,rows:f.rows,now:r,...i!==void 0?{onOpenBead:i}:{}},f.type))})]})]})}function Ve({loading:e,counts:t,showMark:s}){if(e)return n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:"·"});const r=[];t.resolved>0&&r.push(`${t.resolved} resolved`),t.unresolved>0&&r.push(`${t.unresolved} unresolved`),t.candidates>0&&r.push(`${t.candidates} candidates`);const i=r.length>0?r.join(", "):"none";return n.jsxs("span",{className:`text-label uppercase tracking-wider tnum truncate ${s?"text-accent":"text-fg-faint"}`,children:[s&&n.jsx("span",{"aria-hidden":!0,children:"■ "}),i]})}function qe({type:e,rows:t,now:s,onOpenBead:r}){const i=t.slice(0,Ue),l=t.length-i.length;return n.jsxs("div",{children:[n.jsxs("header",{className:"flex items-baseline justify-between mb-2",children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint",children:Ke[e]}),n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:t.length})]}),n.jsx("ul",{className:"space-y-2",children:i.map(u=>n.jsx(We,{row:u,now:s,...r!==void 0?{onOpenBead:r}:{}},`${u.relation}\0${u.node.key}`))}),l>0&&n.jsxs("p",{className:"text-label uppercase tracking-wider text-fg-faint mt-2",children:["+ ",l," more"]})]})}function We({row:e,now:t,onOpenBead:s}){const{node:r,relation:i}=e,l=Qe(r.fetchedAt,t),u=r.title??r.ref,a=r.unresolved||l;return n.jsxs("li",{className:"flex items-baseline gap-3 min-w-0",children:[n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint shrink-0 w-20 truncate",children:i}),n.jsx("span",{className:"min-w-0 flex-1 truncate",children:n.jsx(Ye,{node:r,label:u,dimmed:a,...s!==void 0?{onOpenBead:s}:{}})}),n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum shrink-0",children:r.unresolved?Ze(r):r.fetchedAt?D(r.fetchedAt,t):r.status??"·"})]})}function Ye({node:e,label:t,dimmed:s,onOpenBead:r}){const i=`text-body text-left truncate min-w-0 focus-mark ${s?"text-fg-muted":"text-fg hover:text-accent"}`;return e.type==="bead"&&!e.unresolved&&r?n.jsx("button",{type:"button",onClick:()=>r(e.ref),className:i,title:`Open ${e.ref}`,children:t}):e.type==="session"&&!e.unresolved?n.jsx(X,{to:`/agents/${encodeURIComponent(e.ref)}`,className:i,children:t}):e.url?n.jsxs("a",{href:e.url,target:"_blank",rel:"noreferrer noopener",className:i,title:e.url,children:[t," ",n.jsx("span",{"aria-hidden":!0,children:"↗"})]}):n.jsx("span",{className:i,children:t})}function Ze(e){return e.candidateCount!==void 0&&e.candidateCount>1?`${e.candidateCount} candidates`:"unresolved"}function Xe(e){const t={resolved:0,unresolved:0,candidates:0};if(e===null)return t;for(const s of e.nodes)s.key!==e.focus.key&&(s.candidateCount!==void 0&&s.candidateCount>1?t.candidates+=1:s.unresolved?t.unresolved+=1:t.resolved+=1);return t}function Je(e){if(e===null)return[];const t=new Map;for(const i of e.nodes)t.set(i.key,i);const s=new Map;for(const i of e.edges){if(i.from!==e.focus.key)continue;const l=t.get(i.to);if(l===void 0)continue;const u=s.get(l.type)??[];u.push({node:l,relation:i.relation}),s.set(l.type,u)}const r=[];for(const i of Ge){const l=s.get(i);l&&l.length>0&&(l.sort((u,a)=>Number(u.node.unresolved)-Number(a.node.unresolved)),r.push({type:i,rows:l}))}return r}function Qe(e,t){if(e===null)return!1;const s=Date.parse(e);return Number.isFinite(s)?t-s>De:!1}function lt({open:e,onClose:t,beadId:s,initialBead:r=null,onOpenBead:i,depNode:l=null,sessions:u,renderActions:a}){const{bead:o,loading:c,error:f,notFound:m,now:d}=ke(e,s,r),g=Be(e?s:null),[z,k]=h.useState(!1),S=o&&u&&o.assignee&&o.assignee.length>0?te(o.assignee,u):null,I=P(S),R=o?a?.(o):void 0,G=R||I?n.jsxs(n.Fragment,{children:[R,I&&n.jsx(J,{size:"sm",tone:"quiet",onClick:()=>k(!0),children:"View live run"})]}):void 0;return n.jsxs(n.Fragment,{children:[n.jsx(U,{open:e,onClose:t,title:o?.title??s??"Bead",caption:o?n.jsxs("span",{children:[n.jsx("code",{className:"text-fg-muted",children:o.id})," · ",o.issue_type," · P",o.priority==null?"—":o.priority]}):s?n.jsx("code",{className:"text-fg-muted",children:s}):void 0,widthClass:"max-w-3xl",footer:G,children:m?n.jsxs("div",{className:"space-y-2",children:[n.jsx("p",{className:"text-fg-muted",children:"This decision was resolved or removed."}),n.jsx("p",{className:"text-fg-faint text-sm",children:"The bead it pointed to is no longer in the supervisor — it was likely closed or pruned since this link was surfaced."})]}):f?n.jsx("p",{className:"text-accent",role:"alert",children:f}):c&&o===null?n.jsx("p",{className:"text-fg-muted italic",children:"Fetching bead."}):o===null?n.jsx("p",{className:"text-fg-muted italic",children:"No bead."}):n.jsxs("div",{className:"space-y-8",children:[n.jsx(Ce,{bead:o}),l&&n.jsx(Oe,{node:l,...i!==void 0?{onOpenBead:i}:{}}),n.jsx(He,{view:g.view,loading:g.loading,error:g.error,now:d,...i!==void 0?{onOpenBead:i}:{}})]})}),o&&n.jsx(Pe,{open:z,onClose:()=>k(!1),session:S,beadTitle:o.title})]})}export{lt as B,He as R,Be as u}; +import{r as h,u as K,a8 as H,a9 as O,w as V,v as E,aa as q,K as W,j as n,S as Y,ab as Z,L as X,B as J}from"./index-BDHAaQRP.js";import{f as Q}from"./format-fte2CeYD.js";import{F as x}from"./Field-BSdtNgao.js";import{a as P,L as ee}from"./LiveSessionPeek-VUsvyqKB.js";import{M as U}from"./constants-D5DlRFFg.js";import{f as D}from"./time-BVuL_AnL.js";function te(e,t){if(e.length===0||t.length===0)return null;const s=t.filter(r=>r.state==="active");return F(e,s)??F(e,t)}function F(e,t){for(const s of t)if(se(s,e))return s;return null}function se(e,t){return e.alias===t||e.pool===t||e.alias!==void 0&&A(e.alias,["/","."])===t||e.session_name!==void 0&&A(e.session_name,["__","--"])===t}function A(e,t){let s=-1,r=0;for(const i of t){const l=e.lastIndexOf(i);l>s&&(s=l,r=i.length)}return s<0?e:e.slice(s+r)}const ne=/^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;function re(e,t,s){return`${e}:${s}:${t}`}function b(e,t,s){e?.(t,s)}const ie=/^pr\/(\d{1,9})$/,le=/^issue\/(\d{1,9})$/;function oe(e){const t=e.trim();if(t.length===0)return{ok:!1,error:"empty ref"};const s=ie.exec(t);if(s?.[1])return{ok:!0,type:"github_pr",value:s[1]};const r=le.exec(t);return r?.[1]?{ok:!0,type:"github_issue",value:r[1]}:ne.test(t)?{ok:!0,type:"bead",value:t}:{ok:!1,error:"unrecognised ref"}}function M(e){if(typeof e!="string")return null;const t=e.trim();return/^https?:\/\//i.test(t)?t:null}function v(e,t,s){return re(e,t,s)}function ae(e){return{key:v("bead",e.id,e.scope),type:"bead",ref:e.id}}function _(e,t){const s=e.stats.get(t);if(s)return s;const r={relation:t,resolved:0,unresolved:0,nCandidates:0};return e.stats.set(t,r),r}function y(e,t){e.nodesByKey.has(t.key)||(e.nodesByKey.set(t.key,t),e.view.nodes.push(t))}function w(e,t,s,r,i,l){e.view.edges.push({from:t,to:s,relation:r,provenance:i,resolved:l})}function N(e,t,s,r,i){const l=ae(s);y(e,{...l,title:s.title,status:s.status,url:null,fetchedAt:i,unresolved:!1}),w(e,t,l.key,r,"supervisor",!0),_(e,r).resolved+=1,b(e.recorder,r,"resolved")}function ue(e,t){return{focus:e,nodes:[],edges:[],stats:[],partial:!1,generatedAt:t,asOf:null}}function $(e,t){return e===null?t:t===null||Date.parse(e)<=Date.parse(t)?e:t}function ce(e,t,s={}){const i=(s.now??(()=>new Date))().toISOString(),l=s.supervisorFetchedAt??null,u=s.githubFetchedAt??null,a=de(e,t),o=ue(a.focus,i);o.partial=s.partial??!1;const c={view:o,nodesByKey:new Map,stats:new Map,recorder:s.recorder??(()=>{})};if(y(c,a.focusNode),!a.focusResolved)return o.partial=!0,L(c,l,u),o;const f=a.focusNode.key;if(a.beadFocus)for(const m of a.beads)pe(c,m,f,e,l,u);else for(const m of a.beads)N(c,f,m,"bead",l);return L(c,l,u),o}function de(e,t){if(t.type==="github_pr"||t.type==="github_issue"){const u=t.type==="github_pr"?"github_pr":"github_issue",a=t.type==="github_pr"?`pr/${t.value}`:`issue/${t.value}`,c=(t.type==="github_pr"?e.beadsForPr.get(t.value)??[]:e.beadsForIssue.get(t.value)??[]).map(m=>e.beads.get(m)).filter(m=>m!==void 0),f={key:v(u,t.value,"github"),type:u,ref:a};return{focus:f,focusNode:{...f,title:null,status:null,url:null,fetchedAt:null,unresolved:c.length===0,...c.length>1?{candidateCount:c.length}:{}},beads:c,focusResolved:c.length>0,beadFocus:!1}}const s=e.beads.get(t.value)??e.allBeads.get(t.value);if(s!==void 0){const u=fe(s);return{focus:u,focusNode:{...u,title:s.title,status:s.status,url:null,fetchedAt:null,unresolved:!1},beads:s.superseded?[]:[s],focusResolved:!0,beadFocus:!0}}const r=e.beadsForSession.get(t.value)??[],i=e.sessions.has(t.value);if(r.length>0||i){const u={key:v("session",t.value,"session"),type:"session",ref:t.value},a=r.map(c=>e.beads.get(c)).filter(c=>c!==void 0),o=i||a.length>0;return{focus:u,focusNode:{...u,title:e.sessions.get(t.value)?.title??null,status:e.sessions.get(t.value)?.state??null,url:null,fetchedAt:null,unresolved:!o},beads:a,focusResolved:o,beadFocus:!1}}const l={key:v("bead",t.value,"unknown"),type:"bead",ref:t.value};return{focus:l,focusNode:{...l,title:null,status:null,url:null,fetchedAt:null,unresolved:!0},beads:[],focusResolved:!1,beadFocus:!0}}function fe(e){return{key:v("bead",e.id,e.scope),type:"bead",ref:e.id}}function pe(e,t,s,r,i,l){if(t.parentBeadId){const a=r.beads.get(t.parentBeadId);a?N(e,s,a,"parent",i):me(e,s,t.parentBeadId,"parent")}const u=(r.childrenOf.get(t.id)??[]).filter(a=>a!==t.id);for(const a of u){const o=r.beads.get(a);o&&N(e,s,o,"child",i)}if(t.moleculeId){const a=(r.membersOfMolecule.get(t.moleculeId)??[]).filter(o=>o!==t.id&&o!==t.moleculeId);if(t.moleculeId!==t.id){const o=r.beads.get(t.moleculeId);o&&N(e,s,o,"molecule",i)}for(const o of a){const c=r.beads.get(o);c&&N(e,s,c,"molecule",i)}}if(t.prNumber&&B(e,s,"github_pr",`pr/${t.prNumber}`,t.prNumber,M(t.prUrl),"pr","supervisor",l),t.issueNumber&&B(e,s,"github_issue",`issue/${t.issueNumber}`,t.issueNumber,M(t.issueUrl),"issue","supervisor",l),t.sessionId){const a=r.sessions.get(t.sessionId),o={key:v("session",t.sessionId,"session"),type:"session",ref:t.sessionId};a?(y(e,{...o,title:a.title??a.alias??t.sessionName??null,status:a.state??null,url:null,fetchedAt:i,unresolved:!1}),w(e,s,o.key,"session","supervisor",!0),_(e,"session").resolved+=1,b(e.recorder,"session","resolved")):(y(e,{...o,title:t.sessionName??null,status:null,url:null,fetchedAt:i,unresolved:!0}),w(e,s,o.key,"session","supervisor",!1),_(e,"session").unresolved+=1,b(e.recorder,"session","unresolved"))}}function B(e,t,s,r,i,l,u,a,o){const c=v(s,i,"github");y(e,{key:c,type:s,ref:r,title:null,status:null,url:l,fetchedAt:o,unresolved:!0}),w(e,t,c,u,a,!1),_(e,u).unresolved+=1,b(e.recorder,u,"unresolved")}function me(e,t,s,r){const i=v("bead",s,"unknown");y(e,{key:i,type:"bead",ref:s,title:null,status:null,url:null,fetchedAt:null,unresolved:!0}),w(e,t,i,r,"supervisor",!1),_(e,r).unresolved+=1,b(e.recorder,r,"unresolved")}function L(e,t,s){e.view.stats=[...e.stats.values()].sort((i,l)=>i.relation.localeCompare(l.relation));let r=null;for(const i of e.view.nodes)r=$(r,i.fetchedAt);e.view.asOf=r??$(t,s)}function p(e,t){const s=e.metadata?.[t];if(typeof s=="string"){const r=s.trim();return r.length>0?r:void 0}if(typeof s=="number"&&Number.isFinite(s))return String(s)}function he(e,t){const s=e.metadata?.[t];if(typeof s=="number"&&Number.isInteger(s)&&s>=0)return s;if(typeof s=="string"&&/^\d+$/.test(s.trim()))return Number.parseInt(s.trim(),10)}const ge=["gc.scope_ref","scope_ref","scope_id"],xe=["gc.scope_kind","scope_kind"];function ve(e,t){let s;for(const i of ge){const l=p(e,i);if(l!==void 0){s=l;break}}let r;for(const i of xe){const l=p(e,i);if(l!==void 0){r=l;break}}return s===void 0?`city:${t}`:`${r??"rig"}:${s}`}const ye=/^github-pr:[^/]+\/[^/]+\/(\d+)$/,je=/\/(?:pull\/)?(\d+)(?:[/?#]|$)/;function Ne(e){const t=p(e,"evidence.pr_url"),s=p(e,"evidence.pr_number"),r=p(e,"evidence.artifact_path"),i=p(e,"pr_review.pr_number"),l=p(e,"pr_review.pr_url"),u=r?.match(ye),a=t?.match(je),o=s??u?.[1]??a?.[1]??i??void 0,c=t??l??void 0,f={};return o!==void 0&&(f.prNumber=o),c!==void 0&&(f.prUrl=c),f}function be(e,t){const{prNumber:s,prUrl:r}=Ne(e),i={id:e.id,title:e.title,status:e.status,scope:ve(e,t),superseded:!1},l={parentBeadId:p(e,"gc.parent_bead_id"),rootBeadId:p(e,"gc.root_bead_id"),moleculeId:p(e,"molecule_id"),prNumber:s,prUrl:r,issueNumber:p(e,"bugflow.github_issue_number")??p(e,"design_review.github_issue_number"),issueUrl:p(e,"bugflow.github_issue_url")??p(e,"design_review.github_issue_url"),sessionId:p(e,"session_id"),sessionName:p(e,"session_name"),stepId:p(e,"gc.step_id"),attempt:he(e,"gc.attempt")};for(const[u,a]of Object.entries(l))a!==void 0&&Object.assign(i,{[u]:a});return i}function T(e){return`${e.moleculeId}\0${e.stepId}`}function _e(e){const t=new Map;for(const s of e){if(s.moleculeId===void 0||s.stepId===void 0||s.attempt===void 0)continue;const r=T(s),i=t.get(r);(i===void 0||s.attempt>i)&&t.set(r,s.attempt)}for(const s of e){if(s.moleculeId===void 0||s.stepId===void 0||s.attempt===void 0)continue;const r=t.get(T(s));r!==void 0&&s.attemptbe(d,s));_e(r);const i=new Map,l=new Map,u=new Map,a=new Map,o=new Map,c=new Map,f=new Map;for(const d of r)i.set(d.id,d),!d.superseded&&(l.set(d.id,d),d.parentBeadId&&j(u,d.parentBeadId,d.id),d.moleculeId&&j(a,d.moleculeId,d.id),d.prNumber&&j(o,d.prNumber,d.id),d.issueNumber&&j(c,d.issueNumber,d.id),d.sessionId&&j(f,d.sessionId,d.id));const m=new Map;for(const d of t)m.set(d.id,d);return{beads:l,allBeads:i,childrenOf:u,membersOfMolecule:a,beadsForPr:o,beadsForIssue:c,beadsForSession:f,sessions:m}}function ke(e,t,s=null){const[r,i]=h.useState(s),[l,u]=h.useState(!1),[a,o]=h.useState(null),[c,f]=h.useState(!1),m=K();return h.useEffect(()=>{if(!e||!t)return;if(s&&s.id===t&&s.description!==void 0){i(s),o(null),f(!1);return}i(s?.id===t?s:null),u(!0),o(null),f(!1);let d=!1;return(async()=>{try{const g=await H(t);d||i(g)}catch(g){if(d)return;g instanceof O&&g.status===404?f(!0):o(Se(g))}finally{d||u(!1)}})(),()=>{d=!0}},[e,t,s]),{bead:r,loading:l,error:a,notFound:c,now:m}}function Se(e){return e instanceof O?e.status===void 0?e.message:`${e.status} ${e.message}`:e instanceof Error?e.message:"fetch failed"}function Ie(e){return e.partial===!0||(e.partial_errors?.length??0)>0||(e.next_cursor?.length??0)>0}function Re(e,t){return Ie(e)||typeof e.total=="number"&&e.total>t}const Ee=1e3;async function Fe(e){const t=oe(e);if(!t.ok)throw new Error(t.error);const s=V("load supervisor entity links"),r=new Date().toISOString(),i=await E().listBeads(s,{limit:Ee}),l=Ae(i.items??[]);let u=Re(i,l.length),a=[];try{const c=await E().listSessions(s);a=q(c),u||=$e(c)}catch{u=!0}const o=we(l,a,s);return ce(o,t,{partial:u,supervisorFetchedAt:r,githubFetchedAt:null})}function Ae(e){return e.map(Me)}function Me(e){const t={id:e.id,title:e.title,status:e.status,issue_type:e.issue_type,priority:e.priority??null,created_at:e.created_at};return e.description!==void 0&&(t.description=e.description),e.assignee!==void 0&&(t.assignee=e.assignee),Array.isArray(e.labels)&&(t.labels=e.labels),e.metadata!==void 0&&(t.metadata=e.metadata),e.ref!==void 0&&(t.ref=e.ref),e.parent!==void 0&&(t.parent=e.parent),e.from!==void 0&&(t.from=e.from),e.ephemeral!==void 0&&(t.ephemeral=e.ephemeral),e.needs!==void 0&&(t.needs=e.needs),e.dependencies!==void 0&&(t.dependencies=e.dependencies),e.updated_at!==void 0&&(t.updated_at=e.updated_at),t}function $e(e){return e.partial===!0||(e.partial_errors?.length??0)>0}function Be(e){const[t,s]=h.useState(null),[r,i]=h.useState(!1),[l,u]=h.useState(null);return h.useEffect(()=>{if(e===null||e.length===0){s(null),u(null),i(!1);return}let a=!1;return i(!0),u(null),(async()=>{try{const o=await Fe(e);a||s(o)}catch(o){if(a)return;u(W(o,"related entities failed")),s(null)}finally{a||i(!1)}})(),()=>{a=!0}},[e]),{view:t,loading:r,error:l}}function Le(e){const t=e.metadata;if(!t)return{};const s={};return t["gc.kind"]&&(s.kind=t["gc.kind"]),t["gc.source_bead_id"]&&(s.originBeadId=t["gc.source_bead_id"]),t["gc.formula_contract"]&&(s.formulaContract=t["gc.formula_contract"]),t["gc.run_target"]?s.runTarget=t["gc.run_target"]:t["gc.routed_to"]&&(s.runTarget=t["gc.routed_to"]),s}function Te(e,t){return t.kind==="run"?"template":e.issue_type==="molecule"?"wisp":"work"}function Ce({bead:e}){const t=Le(e),s=Te(e,t);return n.jsxs("div",{className:"space-y-8",children:[s==="template"&&n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Formula template"}),n.jsxs("p",{className:"text-body text-fg-muted max-w-prose",children:["This bead is a recipe, not actionable work. Every"," ",e.ref?n.jsx("code",{className:"text-fg-muted",children:e.ref}):"wisp"," instance is instantiated from this template. The ",n.jsx("span",{className:"text-fg-muted",children:"in_progress"})," ","status is the gc-system convention for ",'"',"available for instantiation",'"'," — do not act on it, nudge it, or close it."]})]}),s==="wisp"&&n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Formula instance"}),n.jsxs("p",{className:"text-body text-fg-muted max-w-prose",children:["One run of the"," ",e.title?n.jsx("code",{className:"text-fg-muted",children:e.title}):"formula"," recipe."]})]}),n.jsxs("dl",{className:"grid grid-cols-2 sm:grid-cols-4 gap-x-8 gap-y-5",children:[n.jsx(x,{label:"Status",children:n.jsx(Y,{tone:Z(e.status),label:e.status})}),n.jsx(x,{label:"Type",children:e.issue_type}),n.jsx(x,{label:"Assignee",children:e.assignee||"·"}),n.jsx(x,{label:"Created",children:n.jsx("span",{className:"tnum",children:Q(e.created_at)})})]}),s==="template"&&(t.formulaContract||t.originBeadId||t.runTarget)&&n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Template origin"}),n.jsx("p",{className:"text-body text-fg-muted max-w-prose mb-4",children:"Where this formula came from, kept for traceability. The origin bead and target may be stale; the formula itself is now used wherever the pool dispatches it."}),n.jsxs("dl",{className:"grid grid-cols-2 sm:grid-cols-3 gap-x-8 gap-y-3",children:[t.formulaContract&&n.jsx(x,{label:"Contract",children:n.jsx("code",{className:"text-fg-muted",children:t.formulaContract})}),e.ref&&n.jsx(x,{label:"Ref",children:n.jsx("code",{className:"text-fg-muted",children:e.ref})}),t.originBeadId&&n.jsx(x,{label:"Origin bead",children:n.jsx("code",{className:"text-fg-muted",children:t.originBeadId})}),t.runTarget&&n.jsx(x,{label:"Origin target",children:n.jsx("span",{className:"text-fg-muted truncate",title:t.runTarget,children:t.runTarget})})]})]}),Array.isArray(e.labels)&&e.labels.length>0&&n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Labels"}),n.jsx("div",{className:"flex flex-wrap gap-x-3 gap-y-1",children:e.labels.map(r=>n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:r},r))})]}),n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:s==="template"?"Recipe":"Description"}),e.description&&e.description.length>0?n.jsx("pre",{className:"text-body whitespace-pre-wrap leading-relaxed text-fg font-sans",children:e.description}):n.jsx("p",{className:"text-body text-fg-muted italic",children:"No description."})]})]})}function Oe({node:e,onOpenBead:t}){const{deps:s,blocks:r}=e,i=s.length>0||r.length>0;return n.jsxs("section",{children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint mb-3",children:"Dependencies"}),i?n.jsxs("div",{className:"space-y-6",children:[s.length>0&&n.jsxs("div",{children:[n.jsxs("p",{className:"text-label uppercase tracking-wider text-fg-muted mb-2",children:["Needs ",n.jsx("span",{className:"tnum",children:s.length})]}),n.jsx("ul",{className:"space-y-1",children:s.map(l=>n.jsx(C,{relation:l.kind==="needs"?null:l.kind,targetId:l.id,targetTitle:l.bead?.title??null,...l.bead&&t?{onOpenBead:t}:{}},`needs-${l.id}`))})]}),r.length>0&&n.jsxs("div",{children:[n.jsxs("p",{className:"text-label uppercase tracking-wider text-fg-muted mb-2",children:["Blocks ",n.jsx("span",{className:"tnum",children:r.length})]}),n.jsx("ul",{className:"space-y-1",children:r.map(l=>n.jsx(C,{relation:null,targetId:l.id,targetTitle:l.title,...t?{onOpenBead:t}:{}},`blocks-${l.id}`))})]})]}):n.jsx("p",{className:"text-body text-fg-muted italic",children:"No dependencies."})]})}function C({relation:e,targetId:t,targetTitle:s,onOpenBead:r}){const i=n.jsxs(n.Fragment,{children:[e&&n.jsxs("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:[e," "]}),n.jsx("span",{className:"tnum text-fg-muted",children:t}),s&&n.jsxs("span",{className:"text-fg",children:[" · ",s]})]});return n.jsx("li",{className:"text-body leading-snug",children:r?n.jsx("button",{type:"button",onClick:()=>r(t),className:"text-left text-fg-muted hover:text-fg focus-mark rounded-sm",title:`Open ${t}`,children:i}):n.jsxs("span",{title:"Outside the fetched window",children:[i," ",n.jsx("span",{className:"text-warn text-label uppercase tracking-wider",children:"unresolved"})]})})}function Pe({open:e,onClose:t,session:s,beadTitle:r}){const i=P(s);return n.jsx(U,{open:e,onClose:t,title:r,caption:s===null?"No live session resolved for this bead.":i?"Live transcript from the supervisor's session stream.":"Snapshot from the supervisor's transcript API.",widthClass:"max-w-5xl",children:n.jsx(ee,{sessionId:s?.id??null,stream:i,showBadge:!0,showCaption:!0})})}const Ue=6,De=3600*1e3,ze=3,Ge=["bead","formula_run","session","github_pr","github_issue","order_run"],Ke={bead:"Beads",session:"Sessions",github_pr:"Pull requests",github_issue:"Issues",formula_run:"Formula runs",order_run:"Order runs"};function He({view:e,loading:t,error:s,now:r,onOpenBead:i}){const[l,u]=h.useState(!1),a=h.useMemo(()=>Je(e),[e]),o=h.useMemo(()=>Xe(e),[e]),c=o.unresolved>=ze;return n.jsxs("section",{className:"mt-12",children:[n.jsxs("header",{className:"flex items-baseline justify-between mb-4 gap-3",children:[n.jsx("h2",{className:"text-label uppercase tracking-wider text-fg-faint",children:"Related"}),n.jsxs("div",{className:"flex items-baseline gap-3 min-w-0",children:[e&&e.asOf&&n.jsxs("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum shrink-0",children:["as of ",D(e.asOf,r)]}),n.jsx(Ve,{loading:t,counts:o,showMark:c})]})]}),s!==null?n.jsx("p",{className:"text-body text-accent",role:"alert",children:s}):t&&e===null?n.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading related entities."}):e===null||a.length===0?n.jsx("p",{className:"text-body text-fg-muted italic",children:"No related entities."}):n.jsxs(n.Fragment,{children:[e.partial&&n.jsx("p",{className:"text-label uppercase tracking-wider text-warn mb-4",role:"status",children:"Partial: some sources did not load. Links may be incomplete."}),n.jsx("button",{type:"button",onClick:()=>u(f=>!f),className:"text-label uppercase tracking-wider text-fg-faint hover:text-fg focus-mark mb-4","aria-expanded":l,children:l?"Hide detail":"Show detail"}),l&&n.jsx("div",{className:"space-y-8",children:a.map(f=>n.jsx(qe,{type:f.type,rows:f.rows,now:r,...i!==void 0?{onOpenBead:i}:{}},f.type))})]})]})}function Ve({loading:e,counts:t,showMark:s}){if(e)return n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:"·"});const r=[];t.resolved>0&&r.push(`${t.resolved} resolved`),t.unresolved>0&&r.push(`${t.unresolved} unresolved`),t.candidates>0&&r.push(`${t.candidates} candidates`);const i=r.length>0?r.join(", "):"none";return n.jsxs("span",{className:`text-label uppercase tracking-wider tnum truncate ${s?"text-accent":"text-fg-faint"}`,children:[s&&n.jsx("span",{"aria-hidden":!0,children:"■ "}),i]})}function qe({type:e,rows:t,now:s,onOpenBead:r}){const i=t.slice(0,Ue),l=t.length-i.length;return n.jsxs("div",{children:[n.jsxs("header",{className:"flex items-baseline justify-between mb-2",children:[n.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint",children:Ke[e]}),n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:t.length})]}),n.jsx("ul",{className:"space-y-2",children:i.map(u=>n.jsx(We,{row:u,now:s,...r!==void 0?{onOpenBead:r}:{}},`${u.relation}\0${u.node.key}`))}),l>0&&n.jsxs("p",{className:"text-label uppercase tracking-wider text-fg-faint mt-2",children:["+ ",l," more"]})]})}function We({row:e,now:t,onOpenBead:s}){const{node:r,relation:i}=e,l=Qe(r.fetchedAt,t),u=r.title??r.ref,a=r.unresolved||l;return n.jsxs("li",{className:"flex items-baseline gap-3 min-w-0",children:[n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint shrink-0 w-20 truncate",children:i}),n.jsx("span",{className:"min-w-0 flex-1 truncate",children:n.jsx(Ye,{node:r,label:u,dimmed:a,...s!==void 0?{onOpenBead:s}:{}})}),n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum shrink-0",children:r.unresolved?Ze(r):r.fetchedAt?D(r.fetchedAt,t):r.status??"·"})]})}function Ye({node:e,label:t,dimmed:s,onOpenBead:r}){const i=`text-body text-left truncate min-w-0 focus-mark ${s?"text-fg-muted":"text-fg hover:text-accent"}`;return e.type==="bead"&&!e.unresolved&&r?n.jsx("button",{type:"button",onClick:()=>r(e.ref),className:i,title:`Open ${e.ref}`,children:t}):e.type==="session"&&!e.unresolved?n.jsx(X,{to:`/agents/${encodeURIComponent(e.ref)}`,className:i,children:t}):e.url?n.jsxs("a",{href:e.url,target:"_blank",rel:"noreferrer noopener",className:i,title:e.url,children:[t," ",n.jsx("span",{"aria-hidden":!0,children:"↗"})]}):n.jsx("span",{className:i,children:t})}function Ze(e){return e.candidateCount!==void 0&&e.candidateCount>1?`${e.candidateCount} candidates`:"unresolved"}function Xe(e){const t={resolved:0,unresolved:0,candidates:0};if(e===null)return t;for(const s of e.nodes)s.key!==e.focus.key&&(s.candidateCount!==void 0&&s.candidateCount>1?t.candidates+=1:s.unresolved?t.unresolved+=1:t.resolved+=1);return t}function Je(e){if(e===null)return[];const t=new Map;for(const i of e.nodes)t.set(i.key,i);const s=new Map;for(const i of e.edges){if(i.from!==e.focus.key)continue;const l=t.get(i.to);if(l===void 0)continue;const u=s.get(l.type)??[];u.push({node:l,relation:i.relation}),s.set(l.type,u)}const r=[];for(const i of Ge){const l=s.get(i);l&&l.length>0&&(l.sort((u,a)=>Number(u.node.unresolved)-Number(a.node.unresolved)),r.push({type:i,rows:l}))}return r}function Qe(e,t){if(e===null)return!1;const s=Date.parse(e);return Number.isFinite(s)?t-s>De:!1}function lt({open:e,onClose:t,beadId:s,initialBead:r=null,onOpenBead:i,depNode:l=null,sessions:u,renderActions:a}){const{bead:o,loading:c,error:f,notFound:m,now:d}=ke(e,s,r),g=Be(e?s:null),[z,k]=h.useState(!1),S=o&&u&&o.assignee&&o.assignee.length>0?te(o.assignee,u):null,I=P(S),R=o?a?.(o):void 0,G=R||I?n.jsxs(n.Fragment,{children:[R,I&&n.jsx(J,{size:"sm",tone:"quiet",onClick:()=>k(!0),children:"View live run"})]}):void 0;return n.jsxs(n.Fragment,{children:[n.jsx(U,{open:e,onClose:t,title:o?.title??s??"Bead",caption:o?n.jsxs("span",{children:[n.jsx("code",{className:"text-fg-muted",children:o.id})," · ",o.issue_type," · P",o.priority==null?"—":o.priority]}):s?n.jsx("code",{className:"text-fg-muted",children:s}):void 0,widthClass:"max-w-3xl",footer:G,children:m?n.jsxs("div",{className:"space-y-2",children:[n.jsx("p",{className:"text-fg-muted",children:"This decision was resolved or removed."}),n.jsx("p",{className:"text-fg-faint text-sm",children:"The bead it pointed to is no longer in the supervisor — it was likely closed or pruned since this link was surfaced."})]}):f?n.jsx("p",{className:"text-accent",role:"alert",children:f}):c&&o===null?n.jsx("p",{className:"text-fg-muted italic",children:"Fetching bead."}):o===null?n.jsx("p",{className:"text-fg-muted italic",children:"No bead."}):n.jsxs("div",{className:"space-y-8",children:[n.jsx(Ce,{bead:o}),l&&n.jsx(Oe,{node:l,...i!==void 0?{onOpenBead:i}:{}}),n.jsx(He,{view:g.view,loading:g.loading,error:g.error,now:d,...i!==void 0?{onOpenBead:i}:{}})]})}),o&&n.jsx(Pe,{open:z,onClose:()=>k(!1),session:S,beadTitle:o.title})]})}export{lt as B,He as R,Be as u}; diff --git a/internal/api/dashboardspa/dist/assets/Beads-BdIAJPDE.js b/internal/api/dashboardspa/dist/assets/Beads-DIx9v9cO.js similarity index 97% rename from internal/api/dashboardspa/dist/assets/Beads-BdIAJPDE.js rename to internal/api/dashboardspa/dist/assets/Beads-DIx9v9cO.js index 07e6a74933..75b87ecb70 100644 --- a/internal/api/dashboardspa/dist/assets/Beads-BdIAJPDE.js +++ b/internal/api/dashboardspa/dist/assets/Beads-DIx9v9cO.js @@ -1 +1 @@ -import{j as e,S as fe,B as C,r as o,v as U,w as te,a as $e,g as Oe,T as Pe,b as V,c as Le,l as Te,f as Fe,K as me,R as pe,i as G,Q as De,G as qe}from"./index-DDS7Ehww.js";import{b as ze,r as He}from"./routeHighlight-B30gQO2o.js";import{B as Ke}from"./BeadDetailModal-DpGateYl.js";import{u as Ve,F as Ge}from"./useListFilters-HxlZke6_.js";import{L as Ue,f as Ye}from"./projectOf-BjfQvzy4.js";import{M as ge}from"./constants-CQJOeNM1.js";import{P as Qe}from"./PageHeader-nOBkk_AA.js";import{l as Xe}from"./agentReads-D6cjHIrb.js";import"./format-fte2CeYD.js";import"./Field-BEMyWxxD.js";import"./LiveSessionPeek-F4FmVdxt.js";import"./time-BVuL_AnL.js";function Je(t){if(t===void 0)return null;const n=t.indexOf("?");if(n<0)return null;const l=new URLSearchParams(t.slice(n+1)).get("bead");return l!==null&&l.length>0?l:null}function We({items:t,onOpen:n}){const l=t.filter(a=>a.severity==="attention"||a.severity==="watch");return l.length===0?null:e.jsxs("section",{"aria-labelledby":"beads-attention-title",className:"mb-8 space-y-3",children:[e.jsxs("h2",{id:"beads-attention-title",className:"text-label uppercase tracking-wider text-fg-muted",children:["Needs you ",e.jsxs("span",{className:"tnum text-fg",children:["(",l.length,")"]})]}),e.jsx("ul",{className:"space-y-2",children:l.map(a=>{const i=Je(a.href);return e.jsxs("li",{className:"flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1",children:[e.jsxs("div",{className:"min-w-0 space-y-0.5",children:[e.jsx(fe,{tone:a.severity==="attention"?"stuck":"warn",label:a.title}),a.summary!==void 0&&e.jsx("p",{className:"text-body text-fg-muted",children:a.summary})]}),i!==null&&e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(C,{type:"button",size:"sm",tone:"quiet",onClick:()=>n(i),children:"Open"})})]},a.id)})})]})}const se=[{id:"ready",label:"ready"},{id:"open",label:"open"},{id:"in_progress",label:"in progress"},{id:"blocked",label:"blocked"},{id:"done",label:"done"}];function Ze(t){const n=new Set,l=[];for(const a of t.needs??[])a.length===0||n.has(a)||(n.add(a),l.push({id:a,kind:"needs"}));for(const a of t.dependencies??[]){const i=a.depends_on_id;i.length===0||n.has(i)||(n.add(i),l.push({id:i,kind:a.type}))}return l}function et(t){return(t.needs??[]).filter(n=>n.length>0)}function tt(t){switch(t.bead.status){case"in_progress":return"in_progress";case"blocked":return"blocked";case"closed":return"done";default:return t.ready?"ready":"open"}}function st(t,n){const l=t.bead.priority??Number.POSITIVE_INFINITY,a=n.bead.priority??Number.POSITIVE_INFINITY;return l!==a?l-a:t.bead.idn.bead.id?1:0}function nt(t){const n=new Map;for(const r of t)n.set(r.id,r);const l=new Map,a=new Map;for(const r of t){const c=Ze(r).map(({id:m,kind:g})=>({id:m,kind:g,bead:n.get(m)??null})),u=c.some(m=>m.bead===null),d=et(r),h=r.status==="open"&&d.every(m=>n.get(m)?.status==="closed"),p={bead:r,deps:c,blocks:[],ready:h,hasUnresolvedDeps:u,column:"open"};p.column=tt(p),a.set(r.id,p);for(const m of c){if(m.bead===null)continue;const g=l.get(m.id);g?g.push(r):l.set(m.id,[r])}}for(const[r,c]of l){const u=a.get(r);u&&(u.blocks=[...c].sort((d,h)=>d.idh.id?1:0))}const i=be();for(const r of a.values())i[r.column].push(r);for(const r of se)i[r.id].sort(st);return{nodes:a,columns:i}}function be(){return{ready:[],open:[],in_progress:[],blocked:[],done:[]}}function at(t,n){const l=be();for(const a of se)l[a.id]=t.columns[a.id].filter(i=>n.has(i.bead.id));return l}function lt({node:t,selected:n,attentionSeverity:l=null,onSelect:a}){const{bead:i,deps:r,blocks:c,hasUnresolvedDeps:u}=t,d=o.useRef(null),h=r.length,p=c.length,m=h>0||p>0,{className:g="",...S}=ze(l);return o.useEffect(()=>{n&&d.current?.scrollIntoView?.({block:"center",inline:"nearest"})},[n]),e.jsx("li",{ref:d,...S,className:`px-2 py-2 -mx-2 rounded-sm transition-colors duration-150 ease-out-quart ${n?"bg-surface-tint":"hover:bg-surface-tint/60"} ${g}`,children:e.jsxs("button",{type:"button",onClick:()=>a(i.id),className:"text-left w-full focus-mark rounded-sm","aria-pressed":n,title:`Select ${i.id}`,children:[e.jsxs("span",{className:"flex items-baseline gap-2",children:[e.jsx("span",{className:"text-fg-faint","aria-hidden":"true",children:n?"▸":" "}),e.jsx("span",{className:`min-w-0 line-clamp-2 text-body ${n?"text-fg font-medium":"text-fg"}`,children:i.title})]}),e.jsxs("span",{className:"flex items-baseline gap-3 pl-4 mt-0.5 text-label uppercase tracking-wider text-fg-faint",children:[e.jsx("span",{className:"tnum",children:i.id}),i.priority!=null&&e.jsxs("span",{className:"tnum",children:["P",i.priority]}),m&&e.jsxs("span",{className:"tnum normal-case tracking-normal",children:[h>0&&`needs ${h}`,h>0&&p>0&&" · ",p>0&&`blocks ${p}`]}),u&&e.jsx("span",{className:"normal-case tracking-normal text-warn",children:"unresolved"})]})]})})}function rt({columns:t,selectedId:n,attentionSeverity:l,onSelect:a}){return e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-5 gap-x-8 gap-y-8",children:se.map(i=>{const r=t[i.id],u=i.id==="blocked"&&r.length>0?"text-accent":"text-fg-muted";return e.jsxs("section",{"aria-label":i.label,children:[e.jsxs("header",{className:"flex items-baseline justify-between border-b border-rule pb-2 mb-3",children:[e.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-muted",children:i.label}),e.jsx("span",{className:`text-label tnum ${u}`,children:r.length})]}),r.length===0?e.jsx("p",{className:"text-body text-fg-faint italic",children:"·"}):e.jsx("ul",{className:"space-y-1",children:r.map(d=>e.jsx(lt,{node:d,selected:d.bead.id===n,attentionSeverity:l?.(d.bead.id)??null,onSelect:a},d.bead.id))})]},i.id)})})}function ot({label:t,count:n,graph:l,ids:a,selectedId:i,attentionSeverity:r,onSelect:c}){const u=at(l,a);return e.jsxs("section",{"aria-label":t,children:[e.jsxs("header",{className:"flex items-baseline justify-between border-b border-rule pb-2 mb-4",children:[e.jsx("h2",{className:"text-headline text-fg",children:t}),e.jsx("span",{className:"text-label tnum text-fg-muted",children:n})]}),e.jsx(rt,{columns:u,selectedId:i,...r===void 0?{}:{attentionSeverity:r},onSelect:c})]})}function it(t,n){const l=t?.trim();if(!l)return;const a=n.find(r=>r.name===l);return a?a.name:n.find(r=>r.path===l)?.name}function ct(t){return Array.from(new Set(t.map(n=>n.name.trim()).filter(n=>n.length>0))).sort((n,l)=>n.localeCompare(l))}async function dt(){const t=await U().listRigs(te("list supervisor rigs"));return{...t,items:t.items??[]}}async function ut(t){await U().closeBead(te("close supervisor bead"),t)}async function mt(t){const n=t.title.trim(),l=t.description.trim(),a=t.rig.trim(),i=t.target.trim();if(n.length===0)throw new Error("bead title is required");if(i.length===0)throw new Error("sling target is required");const r=te("create and sling supervisor bead"),c={title:n};l.length>0&&(c.description=l);const u=await U().createBead(r,c),d={bead:u.id,target:i};a.length>0&&(d.rig=a);const h=await U().sling(r,d);return{bead:u,sling:h}}const pt=new Set,N="",xe="closed",gt=1e4,he=[{id:"open",label:"open",match:t=>t.status==="open"},{id:"in_progress",label:"in progress",match:t=>t.status==="in_progress"},{id:"blocked",label:"blocked",match:t=>t.status==="blocked"},{id:xe,label:"closed",match:t=>t.status==="closed"}],ht=t=>[t.id,t.title,t.assignee,...t.labels??[]];function At(){const t=$e(),n=Oe(),a=De()??"no-city",[i]=Pe(),r=ft(i.get("bead")),[c,u]=o.useState(N),[d,h]=o.useState(!1),[p,m]=o.useState(r),[g,S]=o.useState(null),[I,ne]=o.useState(null),[O,B]=o.useState(null),[Y,P]=o.useState(!1),[L,ae]=o.useState(!1),[le,Q]=o.useState(null),[T,re]=o.useState(""),[X,oe]=o.useState(""),[R,ie]=o.useState(""),[y,_]=o.useState(""),{data:v,loading:F,error:ce,refresh:A}=V(`beads:board:${a}:${c}:${d?"all":"open"}`,()=>Le({includeClosed:d,...c===N?{}:{rigFilter:c}})),ye=o.useMemo(()=>v?.items??[],[v]),de=v?.total??0,J=v?.upstream_total,W=v?.upstream_fetched,je=v?.fetch_limit,D=v!==void 0,q=V(`sessions:${a}`,Te),Ne=o.useMemo(()=>q.data?.items??[],[q.data]),E=V(`agents:${a}`,Xe),j=o.useMemo(()=>E.data?.items??[],[E.data]),z=V(`rigs:${a}`,dt),H=o.useMemo(()=>z.data?.items??[],[z.data]),w=o.useMemo(()=>ct(H),[H]),k=o.useCallback(s=>it(s.rig,H),[H]),M=o.useMemo(()=>R.length===0?j:j.filter(s=>k(s)===R),[j,k,R]);o.useEffect(()=>{if(Y){if(M.length===0){y.length>0&&_("");return}M.some(s=>s.name===y)||_(M[0]?.name??"")}},[Y,M,y]),o.useEffect(()=>{c!==N&&!w.includes(c)&&u(N)},[w,c]);const K=ye,f=Ve({viewKey:"beads",rows:K,projectOf:Ye,searchOf:ht,chips:he}),{toggleChip:ue}=f,we=o.useCallback(s=>{s===xe&&h(b=>!b),ue(s)},[ue]);Fe([qe.bead],()=>{A()},{coalesceMs:gt}),o.useEffect(()=>{r!==null&&m(r)},[r]);const Ce=o.useCallback(async s=>{if(!n){ne(s.id),B(null);try{await ut(s.id),S(null),B({tone:"ok",text:`Closed ${s.id}.`}),await A()}catch(b){B({tone:"error",text:me(b,"close failed")})}finally{ne(null)}}},[n,A]),ve=o.useCallback(()=>{const s=w[0]??"",b=j.find(x=>s.length===0||k(x)===s);re(""),oe(""),ie(s),_(b?.name??""),Q(null),B(null),P(!0)},[j,k,w]),ke=o.useCallback(s=>{if(ie(s),!j.some(x=>x.name===y&&(s.length===0||k(x)===s))){const x=j.find(ee=>s.length===0||k(ee)===s);_(x?.name??"")}},[j,k,y]),Se=o.useCallback(async()=>{if(!n){ae(!0),Q(null);try{const s=await mt({title:T,description:X,rig:R,target:y});B({tone:"ok",text:`Created ${s.bead.id} and slung to ${y}.`}),P(!1),await A()}catch(s){Q(me(s,"create and sling failed"))}finally{ae(!1)}}},[y,X,R,T,n,A]),$=o.useMemo(()=>f.groups.flatMap(s=>s.rows),[f.groups]),Z=o.useMemo(()=>nt($),[$]),Ie=o.useMemo(()=>{const s=new Map;for(const b of f.groups)s.set(b.projectKey,new Set(b.rows.map(x=>x.id)));return s},[f.groups]),Be=o.useMemo(()=>$.find(s=>s.id===p)??null,[$,p]),Re=o.useMemo(()=>p===null?null:Z.nodes.get(p)??null,[Z,p]),Ae=o.useMemo(()=>s=>He(t,"beads",s),[t]),_e=o.useCallback(s=>{const b=I!==null,x=I===s.id?"closing":null,ee=n?G:void 0;return e.jsxs("div",{className:"flex flex-wrap items-center justify-end gap-2",children:[n&&e.jsx(pe,{}),x&&e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:x}),e.jsx(C,{type:"button",size:"sm",tone:"quiet",title:ee,disabled:n||b||s.status==="closed",onClick:()=>{B(null),S(s)},children:"Close"})]})},[I,n]),Ee=o.useMemo(()=>D?bt(K,de,c):"Loading beads.",[K,D,de,c]),Me=typeof J=="number"&&typeof W=="number"&&W{A()},disabled:F,children:F&&!D?"Loading":F?"Refreshing":"Refresh"})]})}),e.jsxs("div",{className:"space-y-2 mb-6 text-body text-fg-muted max-w-prose",children:[Me&&e.jsx("p",{className:"text-warn",children:e.jsx(fe,{tone:"warn",label:`Fetch window covered ${W} of ${J} store beads. Raise the fetch limit (currently ${je??"?"}) if engineering work sits past the window.`})}),c!==N&&e.jsxs("p",{children:["Filtering by rig ",e.jsx("span",{className:"text-accent",children:c}),"."," ",e.jsx("button",{type:"button",onClick:()=>u(N),className:"text-fg-muted hover:text-fg focus-mark underline decoration-dotted underline-offset-2 rounded-sm",children:"Clear"})]}),O&&e.jsx("p",{className:O.tone==="error"?"text-accent":"text-fg-muted",role:O.tone==="error"?"alert":"status",children:O.text})]}),e.jsx(We,{items:t.byDomain.beads.items,onOpen:m}),e.jsxs("div",{className:"mb-6 space-y-3",children:[e.jsx(Ue,{value:f.search,onChange:f.setSearch,placeholder:"Search beads by id, title, label, assignee",matchCount:f.totalMatches,totalCount:K.length,ariaLabel:"Search beads"}),e.jsxs("div",{className:"flex flex-wrap items-baseline gap-x-8 gap-y-3",children:[e.jsx(Ge,{chips:he,activeIds:f.activeChipIds,onToggle:we,legend:"Status"}),w.length>1&&e.jsxs("label",{className:"flex items-baseline gap-2 text-label",children:[e.jsx("span",{className:"uppercase tracking-wider text-fg-muted",children:"Rig"}),e.jsxs("select",{value:c,onChange:s=>u(s.target.value),"aria-label":"Rig filter",className:"text-label uppercase tracking-wider text-fg-muted bg-transparent border-0 focus-mark cursor-pointer hover:text-fg transition-colors duration-150 ease-out-quart",children:[e.jsx("option",{value:N,children:"all rigs"}),w.map(s=>e.jsx("option",{value:s,children:s},s))]})]})]})]}),!D&&F?e.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading beads."}):$.length===0?e.jsx("p",{className:"text-body text-fg-muted italic",children:f.search.length>0||f.activeChipIds.size>0?"No beads match the current search or filter.":"Nothing on the queue right now."}):e.jsx("div",{className:"space-y-12",children:f.groups.map(s=>e.jsx(ot,{label:s.project,count:s.totalInProject,graph:Z,ids:Ie.get(s.projectKey)??pt,selectedId:p,attentionSeverity:Ae,onSelect:m},s.projectKey))}),e.jsx(Ke,{open:p!==null,onClose:()=>m(null),beadId:p,initialBead:Be,depNode:Re,sessions:Ne,onOpenBead:m,renderActions:_e}),e.jsx(ge,{open:g!==null,onClose:()=>{I===null&&S(null)},title:g?`Close ${g.id}`:"Close bead",caption:g?.title,widthClass:"max-w-xl",footer:e.jsxs(e.Fragment,{children:[e.jsx(C,{type:"button",size:"sm",tone:"quiet",disabled:I!==null,onClick:()=>S(null),children:"Cancel"}),e.jsx(C,{type:"button",size:"sm",tone:"accent",title:n?G:void 0,disabled:n||g===null||I!==null,onClick:()=>{g&&Ce(g)},children:"Close bead"})]}),children:e.jsx("p",{className:"text-body text-fg-muted",children:"Close this bead? It will be marked closed and drop out of the open queue."})}),e.jsx(ge,{open:Y,onClose:()=>{L||P(!1)},title:"New bead",caption:"Create and sling",widthClass:"max-w-2xl",footer:e.jsxs(e.Fragment,{children:[e.jsx(C,{type:"button",size:"sm",tone:"quiet",disabled:L,onClick:()=>P(!1),children:"Cancel"}),e.jsx(C,{type:"submit",form:"new-bead-form",size:"sm",title:n?G:void 0,disabled:n||L||T.trim().length===0||y.trim().length===0,children:L?"Creating":"Create and sling"})]}),children:e.jsxs("form",{id:"new-bead-form",className:"space-y-5",onSubmit:s=>{s.preventDefault(),Se()},children:[le&&e.jsx("p",{className:"text-accent",role:"alert",children:le}),e.jsxs("label",{className:"block space-y-2 text-body",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Title"}),e.jsx("input",{value:T,onChange:s=>re(s.target.value),required:!0,className:"w-full rounded-sm border border-rule bg-transparent px-3 py-2 text-body text-fg focus-mark"})]}),e.jsxs("label",{className:"block space-y-2 text-body",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Body"}),e.jsx("textarea",{value:X,onChange:s=>oe(s.target.value),rows:5,className:"w-full rounded-sm border border-rule bg-transparent px-3 py-2 text-body text-fg focus-mark"})]}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsxs("label",{className:"block space-y-2 text-body",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Rig"}),e.jsxs("select",{value:R,onChange:s=>ke(s.target.value),className:"w-full rounded-sm border border-rule bg-transparent px-3 py-2 text-body text-fg focus-mark",children:[w.length===0&&e.jsx("option",{value:"",children:"all rigs"}),w.map(s=>e.jsx("option",{value:s,children:s},s))]})]}),e.jsxs("label",{className:"block space-y-2 text-body",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Agent"}),e.jsx("select",{value:y,onChange:s=>_(s.target.value),required:!0,className:"w-full rounded-sm border border-rule bg-transparent px-3 py-2 text-body text-fg focus-mark",children:M.map(s=>e.jsx("option",{value:s.name,children:s.display_name??s.name},s.name))})]})]})]})})]})}function ft(t){const n=t?.trim();return n&&n.length>0?n:null}function bt(t,n,l){if(l!==N&&t.length===0)return`No beads on ${l}.`;const a=t.filter(d=>d.status==="open").length,i=t.filter(d=>d.status==="in_progress").length,r=t.filter(d=>d.status==="blocked").length,c=[];if(a>0&&c.push(`${a} open`),i>0&&c.push(`${i} in progress`),r>0&&c.push(`${r} blocked`),c.length===0)return"Nothing on the queue.";let u=`${c.join(", ")}.`;return l!==N&&(u=`${l}: ${u}`),n>t.length&&(u+=` Showing ${t.length} of ${n}.`),u}export{At as BeadsPage}; +import{j as e,S as fe,B as C,r as o,v as U,w as te,a as $e,g as Oe,T as Pe,b as V,c as Le,l as Te,f as Fe,K as me,R as pe,i as G,Q as De,G as qe}from"./index-BDHAaQRP.js";import{b as ze,r as He}from"./routeHighlight-B30gQO2o.js";import{B as Ke}from"./BeadDetailModal-B7DCLOq5.js";import{u as Ve,F as Ge}from"./useListFilters-D3eLt7Cq.js";import{L as Ue,f as Ye}from"./projectOf-mIrvrzQE.js";import{M as ge}from"./constants-D5DlRFFg.js";import{P as Qe}from"./PageHeader-BW5bf722.js";import{l as Xe}from"./agentReads-BYWP7eVX.js";import"./format-fte2CeYD.js";import"./Field-BSdtNgao.js";import"./LiveSessionPeek-VUsvyqKB.js";import"./time-BVuL_AnL.js";function Je(t){if(t===void 0)return null;const n=t.indexOf("?");if(n<0)return null;const l=new URLSearchParams(t.slice(n+1)).get("bead");return l!==null&&l.length>0?l:null}function We({items:t,onOpen:n}){const l=t.filter(a=>a.severity==="attention"||a.severity==="watch");return l.length===0?null:e.jsxs("section",{"aria-labelledby":"beads-attention-title",className:"mb-8 space-y-3",children:[e.jsxs("h2",{id:"beads-attention-title",className:"text-label uppercase tracking-wider text-fg-muted",children:["Needs you ",e.jsxs("span",{className:"tnum text-fg",children:["(",l.length,")"]})]}),e.jsx("ul",{className:"space-y-2",children:l.map(a=>{const i=Je(a.href);return e.jsxs("li",{className:"flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1",children:[e.jsxs("div",{className:"min-w-0 space-y-0.5",children:[e.jsx(fe,{tone:a.severity==="attention"?"stuck":"warn",label:a.title}),a.summary!==void 0&&e.jsx("p",{className:"text-body text-fg-muted",children:a.summary})]}),i!==null&&e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(C,{type:"button",size:"sm",tone:"quiet",onClick:()=>n(i),children:"Open"})})]},a.id)})})]})}const se=[{id:"ready",label:"ready"},{id:"open",label:"open"},{id:"in_progress",label:"in progress"},{id:"blocked",label:"blocked"},{id:"done",label:"done"}];function Ze(t){const n=new Set,l=[];for(const a of t.needs??[])a.length===0||n.has(a)||(n.add(a),l.push({id:a,kind:"needs"}));for(const a of t.dependencies??[]){const i=a.depends_on_id;i.length===0||n.has(i)||(n.add(i),l.push({id:i,kind:a.type}))}return l}function et(t){return(t.needs??[]).filter(n=>n.length>0)}function tt(t){switch(t.bead.status){case"in_progress":return"in_progress";case"blocked":return"blocked";case"closed":return"done";default:return t.ready?"ready":"open"}}function st(t,n){const l=t.bead.priority??Number.POSITIVE_INFINITY,a=n.bead.priority??Number.POSITIVE_INFINITY;return l!==a?l-a:t.bead.idn.bead.id?1:0}function nt(t){const n=new Map;for(const r of t)n.set(r.id,r);const l=new Map,a=new Map;for(const r of t){const c=Ze(r).map(({id:m,kind:g})=>({id:m,kind:g,bead:n.get(m)??null})),u=c.some(m=>m.bead===null),d=et(r),h=r.status==="open"&&d.every(m=>n.get(m)?.status==="closed"),p={bead:r,deps:c,blocks:[],ready:h,hasUnresolvedDeps:u,column:"open"};p.column=tt(p),a.set(r.id,p);for(const m of c){if(m.bead===null)continue;const g=l.get(m.id);g?g.push(r):l.set(m.id,[r])}}for(const[r,c]of l){const u=a.get(r);u&&(u.blocks=[...c].sort((d,h)=>d.idh.id?1:0))}const i=be();for(const r of a.values())i[r.column].push(r);for(const r of se)i[r.id].sort(st);return{nodes:a,columns:i}}function be(){return{ready:[],open:[],in_progress:[],blocked:[],done:[]}}function at(t,n){const l=be();for(const a of se)l[a.id]=t.columns[a.id].filter(i=>n.has(i.bead.id));return l}function lt({node:t,selected:n,attentionSeverity:l=null,onSelect:a}){const{bead:i,deps:r,blocks:c,hasUnresolvedDeps:u}=t,d=o.useRef(null),h=r.length,p=c.length,m=h>0||p>0,{className:g="",...S}=ze(l);return o.useEffect(()=>{n&&d.current?.scrollIntoView?.({block:"center",inline:"nearest"})},[n]),e.jsx("li",{ref:d,...S,className:`px-2 py-2 -mx-2 rounded-sm transition-colors duration-150 ease-out-quart ${n?"bg-surface-tint":"hover:bg-surface-tint/60"} ${g}`,children:e.jsxs("button",{type:"button",onClick:()=>a(i.id),className:"text-left w-full focus-mark rounded-sm","aria-pressed":n,title:`Select ${i.id}`,children:[e.jsxs("span",{className:"flex items-baseline gap-2",children:[e.jsx("span",{className:"text-fg-faint","aria-hidden":"true",children:n?"▸":" "}),e.jsx("span",{className:`min-w-0 line-clamp-2 text-body ${n?"text-fg font-medium":"text-fg"}`,children:i.title})]}),e.jsxs("span",{className:"flex items-baseline gap-3 pl-4 mt-0.5 text-label uppercase tracking-wider text-fg-faint",children:[e.jsx("span",{className:"tnum",children:i.id}),i.priority!=null&&e.jsxs("span",{className:"tnum",children:["P",i.priority]}),m&&e.jsxs("span",{className:"tnum normal-case tracking-normal",children:[h>0&&`needs ${h}`,h>0&&p>0&&" · ",p>0&&`blocks ${p}`]}),u&&e.jsx("span",{className:"normal-case tracking-normal text-warn",children:"unresolved"})]})]})})}function rt({columns:t,selectedId:n,attentionSeverity:l,onSelect:a}){return e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-5 gap-x-8 gap-y-8",children:se.map(i=>{const r=t[i.id],u=i.id==="blocked"&&r.length>0?"text-accent":"text-fg-muted";return e.jsxs("section",{"aria-label":i.label,children:[e.jsxs("header",{className:"flex items-baseline justify-between border-b border-rule pb-2 mb-3",children:[e.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-muted",children:i.label}),e.jsx("span",{className:`text-label tnum ${u}`,children:r.length})]}),r.length===0?e.jsx("p",{className:"text-body text-fg-faint italic",children:"·"}):e.jsx("ul",{className:"space-y-1",children:r.map(d=>e.jsx(lt,{node:d,selected:d.bead.id===n,attentionSeverity:l?.(d.bead.id)??null,onSelect:a},d.bead.id))})]},i.id)})})}function ot({label:t,count:n,graph:l,ids:a,selectedId:i,attentionSeverity:r,onSelect:c}){const u=at(l,a);return e.jsxs("section",{"aria-label":t,children:[e.jsxs("header",{className:"flex items-baseline justify-between border-b border-rule pb-2 mb-4",children:[e.jsx("h2",{className:"text-headline text-fg",children:t}),e.jsx("span",{className:"text-label tnum text-fg-muted",children:n})]}),e.jsx(rt,{columns:u,selectedId:i,...r===void 0?{}:{attentionSeverity:r},onSelect:c})]})}function it(t,n){const l=t?.trim();if(!l)return;const a=n.find(r=>r.name===l);return a?a.name:n.find(r=>r.path===l)?.name}function ct(t){return Array.from(new Set(t.map(n=>n.name.trim()).filter(n=>n.length>0))).sort((n,l)=>n.localeCompare(l))}async function dt(){const t=await U().listRigs(te("list supervisor rigs"));return{...t,items:t.items??[]}}async function ut(t){await U().closeBead(te("close supervisor bead"),t)}async function mt(t){const n=t.title.trim(),l=t.description.trim(),a=t.rig.trim(),i=t.target.trim();if(n.length===0)throw new Error("bead title is required");if(i.length===0)throw new Error("sling target is required");const r=te("create and sling supervisor bead"),c={title:n};l.length>0&&(c.description=l);const u=await U().createBead(r,c),d={bead:u.id,target:i};a.length>0&&(d.rig=a);const h=await U().sling(r,d);return{bead:u,sling:h}}const pt=new Set,N="",xe="closed",gt=1e4,he=[{id:"open",label:"open",match:t=>t.status==="open"},{id:"in_progress",label:"in progress",match:t=>t.status==="in_progress"},{id:"blocked",label:"blocked",match:t=>t.status==="blocked"},{id:xe,label:"closed",match:t=>t.status==="closed"}],ht=t=>[t.id,t.title,t.assignee,...t.labels??[]];function At(){const t=$e(),n=Oe(),a=De()??"no-city",[i]=Pe(),r=ft(i.get("bead")),[c,u]=o.useState(N),[d,h]=o.useState(!1),[p,m]=o.useState(r),[g,S]=o.useState(null),[I,ne]=o.useState(null),[O,B]=o.useState(null),[Y,P]=o.useState(!1),[L,ae]=o.useState(!1),[le,Q]=o.useState(null),[T,re]=o.useState(""),[X,oe]=o.useState(""),[R,ie]=o.useState(""),[y,_]=o.useState(""),{data:v,loading:F,error:ce,refresh:A}=V(`beads:board:${a}:${c}:${d?"all":"open"}`,()=>Le({includeClosed:d,...c===N?{}:{rigFilter:c}})),ye=o.useMemo(()=>v?.items??[],[v]),de=v?.total??0,J=v?.upstream_total,W=v?.upstream_fetched,je=v?.fetch_limit,D=v!==void 0,q=V(`sessions:${a}`,Te),Ne=o.useMemo(()=>q.data?.items??[],[q.data]),E=V(`agents:${a}`,Xe),j=o.useMemo(()=>E.data?.items??[],[E.data]),z=V(`rigs:${a}`,dt),H=o.useMemo(()=>z.data?.items??[],[z.data]),w=o.useMemo(()=>ct(H),[H]),k=o.useCallback(s=>it(s.rig,H),[H]),M=o.useMemo(()=>R.length===0?j:j.filter(s=>k(s)===R),[j,k,R]);o.useEffect(()=>{if(Y){if(M.length===0){y.length>0&&_("");return}M.some(s=>s.name===y)||_(M[0]?.name??"")}},[Y,M,y]),o.useEffect(()=>{c!==N&&!w.includes(c)&&u(N)},[w,c]);const K=ye,f=Ve({viewKey:"beads",rows:K,projectOf:Ye,searchOf:ht,chips:he}),{toggleChip:ue}=f,we=o.useCallback(s=>{s===xe&&h(b=>!b),ue(s)},[ue]);Fe([qe.bead],()=>{A()},{coalesceMs:gt}),o.useEffect(()=>{r!==null&&m(r)},[r]);const Ce=o.useCallback(async s=>{if(!n){ne(s.id),B(null);try{await ut(s.id),S(null),B({tone:"ok",text:`Closed ${s.id}.`}),await A()}catch(b){B({tone:"error",text:me(b,"close failed")})}finally{ne(null)}}},[n,A]),ve=o.useCallback(()=>{const s=w[0]??"",b=j.find(x=>s.length===0||k(x)===s);re(""),oe(""),ie(s),_(b?.name??""),Q(null),B(null),P(!0)},[j,k,w]),ke=o.useCallback(s=>{if(ie(s),!j.some(x=>x.name===y&&(s.length===0||k(x)===s))){const x=j.find(ee=>s.length===0||k(ee)===s);_(x?.name??"")}},[j,k,y]),Se=o.useCallback(async()=>{if(!n){ae(!0),Q(null);try{const s=await mt({title:T,description:X,rig:R,target:y});B({tone:"ok",text:`Created ${s.bead.id} and slung to ${y}.`}),P(!1),await A()}catch(s){Q(me(s,"create and sling failed"))}finally{ae(!1)}}},[y,X,R,T,n,A]),$=o.useMemo(()=>f.groups.flatMap(s=>s.rows),[f.groups]),Z=o.useMemo(()=>nt($),[$]),Ie=o.useMemo(()=>{const s=new Map;for(const b of f.groups)s.set(b.projectKey,new Set(b.rows.map(x=>x.id)));return s},[f.groups]),Be=o.useMemo(()=>$.find(s=>s.id===p)??null,[$,p]),Re=o.useMemo(()=>p===null?null:Z.nodes.get(p)??null,[Z,p]),Ae=o.useMemo(()=>s=>He(t,"beads",s),[t]),_e=o.useCallback(s=>{const b=I!==null,x=I===s.id?"closing":null,ee=n?G:void 0;return e.jsxs("div",{className:"flex flex-wrap items-center justify-end gap-2",children:[n&&e.jsx(pe,{}),x&&e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:x}),e.jsx(C,{type:"button",size:"sm",tone:"quiet",title:ee,disabled:n||b||s.status==="closed",onClick:()=>{B(null),S(s)},children:"Close"})]})},[I,n]),Ee=o.useMemo(()=>D?bt(K,de,c):"Loading beads.",[K,D,de,c]),Me=typeof J=="number"&&typeof W=="number"&&W{A()},disabled:F,children:F&&!D?"Loading":F?"Refreshing":"Refresh"})]})}),e.jsxs("div",{className:"space-y-2 mb-6 text-body text-fg-muted max-w-prose",children:[Me&&e.jsx("p",{className:"text-warn",children:e.jsx(fe,{tone:"warn",label:`Fetch window covered ${W} of ${J} store beads. Raise the fetch limit (currently ${je??"?"}) if engineering work sits past the window.`})}),c!==N&&e.jsxs("p",{children:["Filtering by rig ",e.jsx("span",{className:"text-accent",children:c}),"."," ",e.jsx("button",{type:"button",onClick:()=>u(N),className:"text-fg-muted hover:text-fg focus-mark underline decoration-dotted underline-offset-2 rounded-sm",children:"Clear"})]}),O&&e.jsx("p",{className:O.tone==="error"?"text-accent":"text-fg-muted",role:O.tone==="error"?"alert":"status",children:O.text})]}),e.jsx(We,{items:t.byDomain.beads.items,onOpen:m}),e.jsxs("div",{className:"mb-6 space-y-3",children:[e.jsx(Ue,{value:f.search,onChange:f.setSearch,placeholder:"Search beads by id, title, label, assignee",matchCount:f.totalMatches,totalCount:K.length,ariaLabel:"Search beads"}),e.jsxs("div",{className:"flex flex-wrap items-baseline gap-x-8 gap-y-3",children:[e.jsx(Ge,{chips:he,activeIds:f.activeChipIds,onToggle:we,legend:"Status"}),w.length>1&&e.jsxs("label",{className:"flex items-baseline gap-2 text-label",children:[e.jsx("span",{className:"uppercase tracking-wider text-fg-muted",children:"Rig"}),e.jsxs("select",{value:c,onChange:s=>u(s.target.value),"aria-label":"Rig filter",className:"text-label uppercase tracking-wider text-fg-muted bg-transparent border-0 focus-mark cursor-pointer hover:text-fg transition-colors duration-150 ease-out-quart",children:[e.jsx("option",{value:N,children:"all rigs"}),w.map(s=>e.jsx("option",{value:s,children:s},s))]})]})]})]}),!D&&F?e.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading beads."}):$.length===0?e.jsx("p",{className:"text-body text-fg-muted italic",children:f.search.length>0||f.activeChipIds.size>0?"No beads match the current search or filter.":"Nothing on the queue right now."}):e.jsx("div",{className:"space-y-12",children:f.groups.map(s=>e.jsx(ot,{label:s.project,count:s.totalInProject,graph:Z,ids:Ie.get(s.projectKey)??pt,selectedId:p,attentionSeverity:Ae,onSelect:m},s.projectKey))}),e.jsx(Ke,{open:p!==null,onClose:()=>m(null),beadId:p,initialBead:Be,depNode:Re,sessions:Ne,onOpenBead:m,renderActions:_e}),e.jsx(ge,{open:g!==null,onClose:()=>{I===null&&S(null)},title:g?`Close ${g.id}`:"Close bead",caption:g?.title,widthClass:"max-w-xl",footer:e.jsxs(e.Fragment,{children:[e.jsx(C,{type:"button",size:"sm",tone:"quiet",disabled:I!==null,onClick:()=>S(null),children:"Cancel"}),e.jsx(C,{type:"button",size:"sm",tone:"accent",title:n?G:void 0,disabled:n||g===null||I!==null,onClick:()=>{g&&Ce(g)},children:"Close bead"})]}),children:e.jsx("p",{className:"text-body text-fg-muted",children:"Close this bead? It will be marked closed and drop out of the open queue."})}),e.jsx(ge,{open:Y,onClose:()=>{L||P(!1)},title:"New bead",caption:"Create and sling",widthClass:"max-w-2xl",footer:e.jsxs(e.Fragment,{children:[e.jsx(C,{type:"button",size:"sm",tone:"quiet",disabled:L,onClick:()=>P(!1),children:"Cancel"}),e.jsx(C,{type:"submit",form:"new-bead-form",size:"sm",title:n?G:void 0,disabled:n||L||T.trim().length===0||y.trim().length===0,children:L?"Creating":"Create and sling"})]}),children:e.jsxs("form",{id:"new-bead-form",className:"space-y-5",onSubmit:s=>{s.preventDefault(),Se()},children:[le&&e.jsx("p",{className:"text-accent",role:"alert",children:le}),e.jsxs("label",{className:"block space-y-2 text-body",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Title"}),e.jsx("input",{value:T,onChange:s=>re(s.target.value),required:!0,className:"w-full rounded-sm border border-rule bg-transparent px-3 py-2 text-body text-fg focus-mark"})]}),e.jsxs("label",{className:"block space-y-2 text-body",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Body"}),e.jsx("textarea",{value:X,onChange:s=>oe(s.target.value),rows:5,className:"w-full rounded-sm border border-rule bg-transparent px-3 py-2 text-body text-fg focus-mark"})]}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsxs("label",{className:"block space-y-2 text-body",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Rig"}),e.jsxs("select",{value:R,onChange:s=>ke(s.target.value),className:"w-full rounded-sm border border-rule bg-transparent px-3 py-2 text-body text-fg focus-mark",children:[w.length===0&&e.jsx("option",{value:"",children:"all rigs"}),w.map(s=>e.jsx("option",{value:s,children:s},s))]})]}),e.jsxs("label",{className:"block space-y-2 text-body",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Agent"}),e.jsx("select",{value:y,onChange:s=>_(s.target.value),required:!0,className:"w-full rounded-sm border border-rule bg-transparent px-3 py-2 text-body text-fg focus-mark",children:M.map(s=>e.jsx("option",{value:s.name,children:s.display_name??s.name},s.name))})]})]})]})})]})}function ft(t){const n=t?.trim();return n&&n.length>0?n:null}function bt(t,n,l){if(l!==N&&t.length===0)return`No beads on ${l}.`;const a=t.filter(d=>d.status==="open").length,i=t.filter(d=>d.status==="in_progress").length,r=t.filter(d=>d.status==="blocked").length,c=[];if(a>0&&c.push(`${a} open`),i>0&&c.push(`${i} in progress`),r>0&&c.push(`${r} blocked`),c.length===0)return"Nothing on the queue.";let u=`${c.join(", ")}.`;return l!==N&&(u=`${l}: ${u}`),n>t.length&&(u+=` Showing ${t.length} of ${n}.`),u}export{At as BeadsPage}; diff --git a/internal/api/dashboardspa/dist/assets/CockpitHome-DJOqblJc.js b/internal/api/dashboardspa/dist/assets/CockpitHome-BpfJnXxo.js similarity index 99% rename from internal/api/dashboardspa/dist/assets/CockpitHome-DJOqblJc.js rename to internal/api/dashboardspa/dist/assets/CockpitHome-BpfJnXxo.js index 81de2ec6b4..36a9ff9c45 100644 --- a/internal/api/dashboardspa/dist/assets/CockpitHome-DJOqblJc.js +++ b/internal/api/dashboardspa/dist/assets/CockpitHome-BpfJnXxo.js @@ -1 +1 @@ -import{N as pe,j as t,L as _,r as m,b as T,v as W,w as C,O as be,a as ve,P as ie,Q as je}from"./index-DDS7Ehww.js";import{P as ye}from"./PageHeader-nOBkk_AA.js";const Q=2;function re(a){return typeof a=="number"&&Number.isFinite(a)&&a>=0?a:0}function ke(a){if(a.length===0)return[];const e=a.map(re),s=e.reduce((i,o)=>i+o,0);if(s===0||Q*e.length>=100)return e.map(()=>100/e.length);const n=100-Q*e.length;return e.map(i=>Q+i/s*n)}function Ne(a){const e=s=>Math.floor(re(s));return[{key:"pending",label:"queued",count:e(a?.pending),href:"/runs"},{key:"active",label:"running",count:e(a?.active),href:"/runs"},{key:"waiting",label:"waiting",count:e(a?.waiting),href:"/runs"},{key:"canceling",label:"stopping",count:e(a?.canceling),href:"/runs"}]}function we(a){const e=[a.input_tokens,a.output_tokens,a.cache_read_tokens,a.cache_creation_tokens];if(e.some(n=>!Number.isFinite(n)||n<0))return null;const s=e.reduce((n,i)=>n+i,0);return Number.isFinite(s)?s:null}function _e(a,e){const s=we(a);if(s===null||!Number.isFinite(e)||e<=0)return null;const n=s/e*60;return Number.isFinite(n)?n:null}function $e(a,e){if(!Number.isFinite(a.cost_usd_estimate)||a.cost_usd_estimate<0||!Number.isFinite(e)||e<=0)return null;const s=a.cost_usd_estimate*(3600/e);return Number.isFinite(s)?s:null}const Se={intake:1,implementation:2,review:3,approval:4,finalization:5,complete:5,blocked:1,active:1};function Me(a){const e=a.progress,s=(e.status==="active_step"||e.status==="stage_only")&&e.stage.status==="available"?e.stage:null,n=Math.max(1,s?.index===void 0?Se[a.phase]??1:s.index+1),i=Math.max(1,a.stages.length,n),o=e.status==="active_step"&&e.attempt.status==="available"?Math.max(1,e.attempt.value):void 0,u=a.formula.status==="known"?a.formula.name:null;return{id:a.id,label:u??a.title,stage:n,totalStages:i,stageWord:s?.label??a.phaseLabel,...o===void 0?{}:{attempt:o},href:pe(a.id,a.scope)}}function b({children:a}){return t.jsx("p",{className:"mt-1 text-label italic text-fg-faint",children:a})}function Re({label:a,value:e,note:s}){const n=e===null?null:Math.max(0,Math.floor(e)),i=n===null?"—":String(n).padStart(4,"0");return t.jsxs("div",{role:"status","aria-label":`${a}: ${n===null?"unavailable":n}`,className:"min-w-36 text-center",children:[t.jsx("div",{"aria-hidden":!0,className:"text-display leading-none tracking-[0.08em] text-fg tnum",children:i}),t.jsx("div",{className:"mt-2 text-label uppercase tracking-wider text-fg-faint",children:a}),s&&t.jsx(b,{children:s})]})}function D({label:a,value:e,note:s}){return t.jsxs("div",{role:"status","aria-label":`${a}: ${e===null?"unavailable":e}`,className:"min-w-28 text-center",children:[t.jsx("div",{"aria-hidden":!0,className:"text-title text-fg tnum",children:e===null?"—":e}),t.jsx("div",{className:"mt-1 text-label uppercase tracking-wider text-fg-faint",children:a}),s&&t.jsx(b,{children:s})]})}function Y({label:a,value:e,max:s,formatted:n,href:i,note:o}){const u=e===null||!Number.isFinite(e)?0:Math.max(0,e),v=-120+(s>0?Math.min(u/s,1):0)*240;return t.jsxs("div",{className:"min-w-36 text-center",children:[t.jsxs(_,{to:i,className:"focus-mark inline-flex min-h-6 flex-col items-center no-underline","aria-label":`${a}: ${e===null?"unavailable":n}`,children:[t.jsxs("svg",{viewBox:"0 0 160 112",width:"160",height:"112","aria-hidden":!0,children:[t.jsx("path",{d:"M 26.306 109 A 62 62 0 1 1 133.694 109",fill:"none",className:"stroke-rule",strokeWidth:"2"}),Array.from({length:7},(k,N)=>{const f=(-120+N*40)*Math.PI/180,$=80+Math.sin(f)*62,P=78-Math.cos(f)*62,A=80+Math.sin(f)*54,j=78-Math.cos(f)*54;return t.jsx("line",{x1:$,y1:P,x2:A,y2:j,className:"stroke-fg-muted"},N)}),t.jsx("g",{className:"transition-transform duration-300 motion-reduce:transition-none",style:{transform:`rotate(${v}deg)`,transformOrigin:"80px 78px"},children:t.jsx("line",{x1:"80",y1:"78",x2:"80",y2:"30",className:"stroke-fg",strokeWidth:"2",strokeLinecap:"round"})}),t.jsx("circle",{cx:"80",cy:"78",r:"4",className:"fill-fg"})]}),t.jsx("span",{className:"text-title text-fg tnum",children:e===null?"—":n}),t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:a})]}),o&&t.jsx(b,{children:o})]})}function Pe({samples:a,available:e=!0,note:s}){const n=a.length>0?a:[0],i=Math.max(1,...n),o=n.map((v,k)=>{const N=n.length===1?0:k/(n.length-1)*100,f=28-Math.max(0,v)/i*24;return`${N},${f}`}).join(" "),u=n.at(-1)??0,h=e?`recent model activity: ${u} invocation${u===1?"":"s"} in the current window`:"recent model activity: unavailable";return t.jsxs("figure",{className:"m-0","aria-label":`${h}${s?`; ${s}`:""}`,children:[t.jsxs("div",{className:"mb-2 flex items-baseline justify-between gap-4",children:[t.jsx("figcaption",{className:"text-label uppercase tracking-wider text-fg-faint",children:"recent model activity"}),t.jsx("span",{className:"text-label text-fg-muted tnum",children:a.length>1?`${a.length} samples`:"collecting samples"})]}),t.jsxs("svg",{viewBox:"0 0 100 32",preserveAspectRatio:"none",className:"h-24 w-full border-y border-rule","aria-hidden":!0,children:[t.jsx("line",{x1:"0",y1:"28",x2:"100",y2:"28",className:"stroke-rule",strokeWidth:"0.4"}),t.jsx("polyline",{points:o,fill:"none",className:"stroke-fg",strokeWidth:"1.2",vectorEffect:"non-scaling-stroke",strokeLinejoin:"round"})]}),s&&t.jsx(b,{children:s})]})}function Ae({segments:a,available:e=!0}){const s=ke(a.map(n=>n.count));return t.jsxs("div",{"aria-label":`runs in flight: ${e?"current":"unavailable"}`,"data-testid":"pipeline",children:[t.jsx("div",{className:"flex h-3 gap-px overflow-hidden rounded-sm","aria-hidden":!0,children:a.map((n,i)=>t.jsx("span",{"data-testid":"pipeline-track-segment",className:"block bg-fg transition-[width] duration-300 motion-reduce:transition-none",style:{width:`${s[i]??0}%`,opacity:.2+i*.2}},n.key))}),t.jsx("div",{className:"mt-2 flex flex-wrap gap-x-5 gap-y-1",children:a.map(n=>t.jsxs(_,{to:n.href,"aria-label":`${n.label}: ${e?n.count:"unavailable"}`,className:"focus-mark inline-flex min-h-6 items-center gap-2 no-underline",children:[t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:n.label}),t.jsx("span",{className:"text-label text-fg tnum",children:e?n.count:"—"})]},n.key))})]})}function Fe({meters:a}){return t.jsx("div",{className:"flex min-h-40 flex-wrap items-end gap-3","data-testid":"context-meters",children:a.map(e=>{const s=Math.min(Math.max(e.value,0),100);return t.jsxs(_,{to:e.href,className:"focus-mark inline-flex min-h-6 w-14 flex-col items-center no-underline","aria-label":`${e.label}: ${Math.round(s)}% context used`,children:[t.jsx("span",{className:"relative block h-28 w-10 overflow-hidden rounded-sm border border-rule","aria-hidden":!0,children:t.jsx("span",{className:"absolute inset-x-0 bottom-0 bg-ok/60 transition-[height] duration-300 motion-reduce:transition-none",style:{height:`${s}%`}})}),t.jsx("span",{className:"mt-1 w-14 truncate text-center text-label uppercase tracking-wider text-fg-faint",children:e.label}),t.jsxs("span",{className:"text-label text-fg-muted tnum",children:[Math.round(s),"%"]})]},e.id)})})}function Ee({runs:a}){return t.jsx("div",{className:"flex min-h-24 flex-wrap content-start gap-3","data-testid":"run-rings",children:a.map(e=>{const s=2*Math.PI*28,n=Math.min(Math.max(e.stage/Math.max(e.totalStages,1),0),1),i=e.attempt!==void 0&&e.attempt>1,o=i?`, retry attempt ${e.attempt}`:"";return t.jsxs(_,{to:e.href,className:"focus-mark inline-flex min-h-6 w-20 flex-col items-center no-underline","aria-label":`${e.label}: stage ${e.stage} of ${e.totalStages}${o}`,children:[t.jsxs("span",{className:"relative block h-20 w-20","aria-hidden":!0,children:[t.jsxs("svg",{viewBox:"0 0 72 72",width:"80",height:"80",children:[t.jsx("circle",{cx:"36",cy:"36",r:"28",fill:"none",className:"stroke-rule",strokeWidth:"3"}),t.jsx("circle",{cx:"36",cy:"36",r:"28",fill:"none",className:"stroke-ok transition-[stroke-dashoffset] duration-300 motion-reduce:transition-none",strokeWidth:"3",strokeDasharray:s,strokeDashoffset:s*(1-n),transform:"rotate(-90 36 36)"})]}),t.jsxs("span",{className:"absolute inset-0 flex flex-col items-center justify-center px-3 text-center text-label text-fg tnum",children:[t.jsxs("span",{children:[e.stage,"/",e.totalStages]}),t.jsx("span",{className:`w-full truncate ${i?"text-warn":"text-fg-faint"}`,title:i?`retry ${e.attempt}`:e.stageWord,children:i?`retry ${e.attempt}`:e.stageWord})]})]}),t.jsx("span",{className:"w-20 truncate text-center text-label text-fg-muted",children:e.label})]},e.id)})})}function Le({lamps:a}){return t.jsx("div",{className:"space-y-2",children:a.map(e=>t.jsxs(_,{to:e.href,className:"focus-mark grid min-h-6 grid-cols-[12px_1fr] items-center gap-x-2 no-underline","aria-label":`${e.label}: ${e.state}, ${e.value}`,children:[t.jsx("span",{"aria-hidden":!0,className:`h-2.5 w-2.5 rounded-full border ${e.state==="healthy"?"border-ok bg-ok/70":e.state==="warning"?"border-warn bg-warn/70":"border-rule bg-transparent"}`}),t.jsxs("span",{className:"flex flex-wrap items-baseline justify-between gap-x-3",children:[t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:e.label}),t.jsx("span",{className:"text-label text-fg-muted",children:e.value})]})]},e.key))})}const O=15e3,Te=8,We=86400;function Ue(){const a=je(),e=a??"no-city",[s,n]=m.useState(!1),i=m.useRef(s);i.current=s;const o=T(`cockpit:usage:${e}`,()=>W().cityUsage(C("cockpit usage read"))),u=T(`cockpit:status:${e}`,()=>W().cityStatus(C("cockpit status read"))),h=T(`cockpit:runs:${e}`,()=>W().runCensus(C("cockpit run census read"))),v=T(`cockpit:sessions:${e}`,()=>W().listSessions(C("cockpit sessions read"))),k=be(),N=ve();I(o.refresh,o.loading,i),I(u.refresh,u.loading,i),I(h.refresh,h.loading,i),I(v.refresh,v.loading,i);const f=R(U(o,e),s),$=R(U(u,e),s),P=R(U(h,e),s),A=R(U(v,e),s),j=R({source:k.source,loading:k.loading,sseState:k.sseState},s),r=f.data,c=$.data,S=P.data,M=A.data,p=j.source,[X,le]=m.useState([]),J=m.useRef(null);m.useEffect(()=>{if(s||r===void 0||!r.available||J.current===r.updated_at)return;J.current=r.updated_at;const l=Math.max(0,r.recent.invocations);le(z=>[...z,l].slice(-48))},[s,r]);const x=r?.available===!0,d=r?.last_24h,oe=r===void 0?void 0:[r.available?void 0:"usage recording is not local",r.available&&!r.recording?"usage recording is off":void 0,r.partial?r.partial_reasons?.join(" · ")||"usage estimate is partial":void 0,r.today.unpriced>0||r.recent.unpriced>0||(r.last_24h?.unpriced??0)>0?"cost excludes unpriced model calls":void 0].filter(l=>l!==void 0).join(" · ")||void 0,y=x?r.recent.invocations>0?{totals:r.recent,seconds:r.recent_window_secs}:d!==void 0&&d.invocations>0?{totals:d,seconds:We,basis:"24 h average"}:null:null,F=y?_e(y.totals,y.seconds):null,E=y?$e(y.totals,y.seconds):null,Z=c?.session_counts_detail?.active,L=Z??(M===void 0?null:(M.items??[]).filter(l=>l.running).length),ce=m.useMemo(()=>Ne(S?.status_counts??null),[S?.status_counts]),ee=m.useMemo(()=>(M?.items??[]).filter(l=>l.running&&typeof l.context_pct=="number"&&Number.isFinite(l.context_pct)).sort((l,z)=>(z.context_pct??0)-(l.context_pct??0)).slice(0,8).map(l=>({id:l.id,label:l.title||l.session_name||l.template,value:l.context_pct??0,href:"/agents"})),[M?.items]),te=m.useMemo(()=>p===void 0||p.status==="error"?[]:[...p.data.lanes,...p.data.blockedLanes].slice(0,Te).map(Me),[p]),ue=j.sseState==="open"?"healthy":"unknown",de=c!==void 0&&$.stale,me=c?.partial===!0,g=de?"stale":me?"partial":null,he=[{key:"feed",label:"live feed",value:j.sseState==="open"?"connected":De(j.sseState),state:ue,href:"/activity"},c===void 0?{key:"store",label:"dolt store",value:"unavailable",state:"unknown",href:"/health"}:c.store_health===void 0?{key:"store",label:"dolt store",value:"not reported",state:"unknown",href:"/health"}:{key:"store",label:"dolt store",value:g===null?K(c.store_health):`${g} · last reported ${K(c.store_health)}`,state:g!==null?"unknown":K(c.store_health)!=="healthy"?"warning":"healthy",href:"/health"},c===void 0?{key:"mail",label:"mail",value:"unavailable",state:"unknown",href:"/mail"}:{key:"mail",label:"mail",value:g===null?`${c.mail.unread} unread`:`${g} · last reported ${c.mail.unread} unread`,state:g!==null?"unknown":c.mail.unread>0?"warning":"healthy",href:"/mail"},c===void 0?{key:"agents",label:"agents",value:"unavailable",state:"unknown",href:"/agents"}:{key:"agents",label:"agents",value:`${g===null?"":`${g} · last reported `}${c.agents.quarantined>0?`${c.agents.quarantined} quarantined`:`${c.agents.running}/${c.agents.total} running`}`,state:g!==null?"unknown":c.agents.quarantined>0||c.agents.suspended>0?"warning":"healthy",href:"/agents"}],w=H(f,"usage",oe),ae=[y?.basis,w].filter(l=>l!==void 0).join(" · ")||void 0,fe=H($,"city status",c?.partial?"city status is partial":void 0),se=H(P,"run states",S?.partial?"run projection is partial":void 0),G=H(A,"sessions",M?.partial?"session list is partial":void 0),xe=Z===void 0?G:fe,ne=p===void 0?j.loading?"loading run progress…":"run progress unavailable":p.status==="error"?"run progress unavailable":p.status==="stale"?"run progress is stale":te.length===0?"no runs in flight":void 0,ge=`${a??"city"} · ${q(L)} active sessions · ${q(S?.status_counts.active)} running · ${x?B(r.today.input_tokens+r.today.output_tokens+r.today.cache_read_tokens+r.today.cache_creation_tokens):"—"} tokens today`;return t.jsxs("section",{children:[t.jsx(ye,{title:"Home",synopsis:ge,meta:t.jsxs("button",{type:"button","aria-pressed":s,onClick:()=>n(l=>!l),className:"focus-mark min-h-6 border-b border-rule text-fg-muted hover:text-fg",children:[s?"resume":"pause"," instruments"]})}),t.jsx(Ce,{items:N.topItems}),t.jsx("div",{className:"mb-8",children:t.jsx(Pe,{samples:X,available:x,note:w??(X.length===0?"waiting for the first usage sample":void 0)})}),t.jsxs("div",{className:"mb-8 grid items-start justify-items-center gap-x-4 gap-y-8 [grid-template-columns:repeat(auto-fit,minmax(150px,1fr))]","data-testid":"dial-grid",children:[t.jsx(Re,{label:"model calls today",value:x?r.today.invocations:null,note:x?[`${V(r.today.cost_usd_estimate)} estimated today`,w].filter(l=>l!==void 0).join(" · "):w}),t.jsx(Y,{label:"active sessions",value:L,max:Math.max(10,(L??0)*1.25),formatted:q(L),href:"/agents",note:xe}),t.jsx(Y,{label:"tokens / min",value:F,max:Math.max(1e3,(F??0)*1.25),formatted:F===null?"—":B(F),href:"/activity",note:ae}),t.jsx(Y,{label:"burn · $ / hr",value:E,max:Math.max(10,(E??0)*1.25),formatted:E===null?"—":V(E),href:"/activity",note:ae})]}),t.jsxs("section",{className:"mb-8","aria-labelledby":"last24h-title",children:[t.jsx("h2",{id:"last24h-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"last 24 hours"}),t.jsxs("div",{className:"grid items-start justify-items-center gap-x-4 gap-y-4 [grid-template-columns:repeat(auto-fit,minmax(120px,1fr))]","data-testid":"last24h-grid",children:[t.jsx(D,{label:"tokens in",value:x&&d!==void 0?B(d.input_tokens):null}),t.jsx(D,{label:"tokens out",value:x&&d!==void 0?B(d.output_tokens):null}),t.jsx(D,{label:"model calls",value:x&&d!==void 0?q(d.invocations):null}),t.jsx(D,{label:"est. cost",value:x&&d!==void 0?V(d.cost_usd_estimate):null})]}),w&&t.jsx(b,{children:w})]}),t.jsxs("section",{className:"mb-8","aria-labelledby":"run-state-title",children:[t.jsx("h2",{id:"run-state-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"runs in flight · canonical state"}),t.jsx(Ae,{segments:ce,available:S!==void 0}),se&&t.jsx(b,{children:se})]}),t.jsxs("div",{className:"grid grid-cols-1 gap-10 lg:[grid-template-columns:5fr_4fr_3fr]",children:[t.jsxs("section",{"aria-labelledby":"context-title",children:[t.jsx("h2",{id:"context-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"live session context"}),t.jsx(Fe,{meters:ee}),(G||ee.length===0)&&t.jsx(b,{children:G??"no live session context reported"})]}),t.jsxs("section",{"aria-labelledby":"progress-title",children:[t.jsx("h2",{id:"progress-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"formula run progress"}),t.jsx(Ee,{runs:te}),ne&&t.jsx(b,{children:ne})]}),t.jsxs("section",{"aria-labelledby":"systems-title",children:[t.jsx("h2",{id:"systems-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"systems"}),t.jsx(Le,{lamps:he})]})]})]})}function I(a,e,s){m.useEffect(()=>{let n=!1,i;function o(h){n||(i!==void 0&&clearTimeout(i),i=setTimeout(u,h))}function u(){if(i=void 0,s.current){o(O);return}const h=a();o(ie),h.then(()=>o(O),()=>o(O))}return o(e?ie:O),()=>{n=!0,i!==void 0&&clearTimeout(i)}},[e,s,a])}function R(a,e){const s=m.useRef(a);return e||(s.current=a),s.current}function U(a,e){const s=m.useRef(null);s.current?.key!==e&&(s.current=null),a.error!==null&&a.data!==void 0?s.current={key:e,data:a.data,fetchedAt:a.fetchedAt}:s.current!==null&&!a.loading&&(s.current=null);const n=s.current;return{data:n?.data??a.data,loading:a.loading,fetchedAt:n?.fetchedAt??a.fetchedAt,stale:n!==null}}function H(a,e,s){if(a.data===void 0)return a.loading?`loading ${e}…`:`${e} unavailable`;if(a.stale)return`${e} is stale · refresh failed`;if(s)return s}function K(a){const e=a.last_gc_status?.trim();return e&&e!=="success"?"maintenance failed":a.warning?"maintenance overdue":"healthy"}function Ce({items:a}){const e=a.find(n=>n.severity==="attention");if(!e)return null;const s=t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"mr-2 uppercase tracking-wider",children:"needs you"}),t.jsx("span",{className:"text-fg",children:e.title})]});return t.jsx("div",{className:"mb-8 border-y border-accent/30 py-2 text-label text-accent",children:e.href?t.jsx(_,{to:e.href,className:"focus-mark inline-block min-h-6 no-underline",children:s}):s})}function De(a){switch(a){case"connecting":return"connecting";case"degraded":return"degraded";default:return"disconnected"}}function q(a){return typeof a=="number"&&Number.isFinite(a)?String(Math.max(0,Math.round(a))):"—"}function B(a){return new Intl.NumberFormat("en",{notation:"compact",maximumFractionDigits:1}).format(Math.max(0,a))}function V(a){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:2}).format(Math.max(0,a))}export{Ue as CockpitHomePage}; +import{N as pe,j as t,L as _,r as m,b as T,v as W,w as C,O as be,a as ve,P as ie,Q as je}from"./index-BDHAaQRP.js";import{P as ye}from"./PageHeader-BW5bf722.js";const Q=2;function re(a){return typeof a=="number"&&Number.isFinite(a)&&a>=0?a:0}function ke(a){if(a.length===0)return[];const e=a.map(re),s=e.reduce((i,o)=>i+o,0);if(s===0||Q*e.length>=100)return e.map(()=>100/e.length);const n=100-Q*e.length;return e.map(i=>Q+i/s*n)}function Ne(a){const e=s=>Math.floor(re(s));return[{key:"pending",label:"queued",count:e(a?.pending),href:"/runs"},{key:"active",label:"running",count:e(a?.active),href:"/runs"},{key:"waiting",label:"waiting",count:e(a?.waiting),href:"/runs"},{key:"canceling",label:"stopping",count:e(a?.canceling),href:"/runs"}]}function we(a){const e=[a.input_tokens,a.output_tokens,a.cache_read_tokens,a.cache_creation_tokens];if(e.some(n=>!Number.isFinite(n)||n<0))return null;const s=e.reduce((n,i)=>n+i,0);return Number.isFinite(s)?s:null}function _e(a,e){const s=we(a);if(s===null||!Number.isFinite(e)||e<=0)return null;const n=s/e*60;return Number.isFinite(n)?n:null}function $e(a,e){if(!Number.isFinite(a.cost_usd_estimate)||a.cost_usd_estimate<0||!Number.isFinite(e)||e<=0)return null;const s=a.cost_usd_estimate*(3600/e);return Number.isFinite(s)?s:null}const Se={intake:1,implementation:2,review:3,approval:4,finalization:5,complete:5,blocked:1,active:1};function Me(a){const e=a.progress,s=(e.status==="active_step"||e.status==="stage_only")&&e.stage.status==="available"?e.stage:null,n=Math.max(1,s?.index===void 0?Se[a.phase]??1:s.index+1),i=Math.max(1,a.stages.length,n),o=e.status==="active_step"&&e.attempt.status==="available"?Math.max(1,e.attempt.value):void 0,u=a.formula.status==="known"?a.formula.name:null;return{id:a.id,label:u??a.title,stage:n,totalStages:i,stageWord:s?.label??a.phaseLabel,...o===void 0?{}:{attempt:o},href:pe(a.id,a.scope)}}function b({children:a}){return t.jsx("p",{className:"mt-1 text-label italic text-fg-faint",children:a})}function Re({label:a,value:e,note:s}){const n=e===null?null:Math.max(0,Math.floor(e)),i=n===null?"—":String(n).padStart(4,"0");return t.jsxs("div",{role:"status","aria-label":`${a}: ${n===null?"unavailable":n}`,className:"min-w-36 text-center",children:[t.jsx("div",{"aria-hidden":!0,className:"text-display leading-none tracking-[0.08em] text-fg tnum",children:i}),t.jsx("div",{className:"mt-2 text-label uppercase tracking-wider text-fg-faint",children:a}),s&&t.jsx(b,{children:s})]})}function D({label:a,value:e,note:s}){return t.jsxs("div",{role:"status","aria-label":`${a}: ${e===null?"unavailable":e}`,className:"min-w-28 text-center",children:[t.jsx("div",{"aria-hidden":!0,className:"text-title text-fg tnum",children:e===null?"—":e}),t.jsx("div",{className:"mt-1 text-label uppercase tracking-wider text-fg-faint",children:a}),s&&t.jsx(b,{children:s})]})}function Y({label:a,value:e,max:s,formatted:n,href:i,note:o}){const u=e===null||!Number.isFinite(e)?0:Math.max(0,e),v=-120+(s>0?Math.min(u/s,1):0)*240;return t.jsxs("div",{className:"min-w-36 text-center",children:[t.jsxs(_,{to:i,className:"focus-mark inline-flex min-h-6 flex-col items-center no-underline","aria-label":`${a}: ${e===null?"unavailable":n}`,children:[t.jsxs("svg",{viewBox:"0 0 160 112",width:"160",height:"112","aria-hidden":!0,children:[t.jsx("path",{d:"M 26.306 109 A 62 62 0 1 1 133.694 109",fill:"none",className:"stroke-rule",strokeWidth:"2"}),Array.from({length:7},(k,N)=>{const f=(-120+N*40)*Math.PI/180,$=80+Math.sin(f)*62,P=78-Math.cos(f)*62,A=80+Math.sin(f)*54,j=78-Math.cos(f)*54;return t.jsx("line",{x1:$,y1:P,x2:A,y2:j,className:"stroke-fg-muted"},N)}),t.jsx("g",{className:"transition-transform duration-300 motion-reduce:transition-none",style:{transform:`rotate(${v}deg)`,transformOrigin:"80px 78px"},children:t.jsx("line",{x1:"80",y1:"78",x2:"80",y2:"30",className:"stroke-fg",strokeWidth:"2",strokeLinecap:"round"})}),t.jsx("circle",{cx:"80",cy:"78",r:"4",className:"fill-fg"})]}),t.jsx("span",{className:"text-title text-fg tnum",children:e===null?"—":n}),t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:a})]}),o&&t.jsx(b,{children:o})]})}function Pe({samples:a,available:e=!0,note:s}){const n=a.length>0?a:[0],i=Math.max(1,...n),o=n.map((v,k)=>{const N=n.length===1?0:k/(n.length-1)*100,f=28-Math.max(0,v)/i*24;return`${N},${f}`}).join(" "),u=n.at(-1)??0,h=e?`recent model activity: ${u} invocation${u===1?"":"s"} in the current window`:"recent model activity: unavailable";return t.jsxs("figure",{className:"m-0","aria-label":`${h}${s?`; ${s}`:""}`,children:[t.jsxs("div",{className:"mb-2 flex items-baseline justify-between gap-4",children:[t.jsx("figcaption",{className:"text-label uppercase tracking-wider text-fg-faint",children:"recent model activity"}),t.jsx("span",{className:"text-label text-fg-muted tnum",children:a.length>1?`${a.length} samples`:"collecting samples"})]}),t.jsxs("svg",{viewBox:"0 0 100 32",preserveAspectRatio:"none",className:"h-24 w-full border-y border-rule","aria-hidden":!0,children:[t.jsx("line",{x1:"0",y1:"28",x2:"100",y2:"28",className:"stroke-rule",strokeWidth:"0.4"}),t.jsx("polyline",{points:o,fill:"none",className:"stroke-fg",strokeWidth:"1.2",vectorEffect:"non-scaling-stroke",strokeLinejoin:"round"})]}),s&&t.jsx(b,{children:s})]})}function Ae({segments:a,available:e=!0}){const s=ke(a.map(n=>n.count));return t.jsxs("div",{"aria-label":`runs in flight: ${e?"current":"unavailable"}`,"data-testid":"pipeline",children:[t.jsx("div",{className:"flex h-3 gap-px overflow-hidden rounded-sm","aria-hidden":!0,children:a.map((n,i)=>t.jsx("span",{"data-testid":"pipeline-track-segment",className:"block bg-fg transition-[width] duration-300 motion-reduce:transition-none",style:{width:`${s[i]??0}%`,opacity:.2+i*.2}},n.key))}),t.jsx("div",{className:"mt-2 flex flex-wrap gap-x-5 gap-y-1",children:a.map(n=>t.jsxs(_,{to:n.href,"aria-label":`${n.label}: ${e?n.count:"unavailable"}`,className:"focus-mark inline-flex min-h-6 items-center gap-2 no-underline",children:[t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:n.label}),t.jsx("span",{className:"text-label text-fg tnum",children:e?n.count:"—"})]},n.key))})]})}function Fe({meters:a}){return t.jsx("div",{className:"flex min-h-40 flex-wrap items-end gap-3","data-testid":"context-meters",children:a.map(e=>{const s=Math.min(Math.max(e.value,0),100);return t.jsxs(_,{to:e.href,className:"focus-mark inline-flex min-h-6 w-14 flex-col items-center no-underline","aria-label":`${e.label}: ${Math.round(s)}% context used`,children:[t.jsx("span",{className:"relative block h-28 w-10 overflow-hidden rounded-sm border border-rule","aria-hidden":!0,children:t.jsx("span",{className:"absolute inset-x-0 bottom-0 bg-ok/60 transition-[height] duration-300 motion-reduce:transition-none",style:{height:`${s}%`}})}),t.jsx("span",{className:"mt-1 w-14 truncate text-center text-label uppercase tracking-wider text-fg-faint",children:e.label}),t.jsxs("span",{className:"text-label text-fg-muted tnum",children:[Math.round(s),"%"]})]},e.id)})})}function Ee({runs:a}){return t.jsx("div",{className:"flex min-h-24 flex-wrap content-start gap-3","data-testid":"run-rings",children:a.map(e=>{const s=2*Math.PI*28,n=Math.min(Math.max(e.stage/Math.max(e.totalStages,1),0),1),i=e.attempt!==void 0&&e.attempt>1,o=i?`, retry attempt ${e.attempt}`:"";return t.jsxs(_,{to:e.href,className:"focus-mark inline-flex min-h-6 w-20 flex-col items-center no-underline","aria-label":`${e.label}: stage ${e.stage} of ${e.totalStages}${o}`,children:[t.jsxs("span",{className:"relative block h-20 w-20","aria-hidden":!0,children:[t.jsxs("svg",{viewBox:"0 0 72 72",width:"80",height:"80",children:[t.jsx("circle",{cx:"36",cy:"36",r:"28",fill:"none",className:"stroke-rule",strokeWidth:"3"}),t.jsx("circle",{cx:"36",cy:"36",r:"28",fill:"none",className:"stroke-ok transition-[stroke-dashoffset] duration-300 motion-reduce:transition-none",strokeWidth:"3",strokeDasharray:s,strokeDashoffset:s*(1-n),transform:"rotate(-90 36 36)"})]}),t.jsxs("span",{className:"absolute inset-0 flex flex-col items-center justify-center px-3 text-center text-label text-fg tnum",children:[t.jsxs("span",{children:[e.stage,"/",e.totalStages]}),t.jsx("span",{className:`w-full truncate ${i?"text-warn":"text-fg-faint"}`,title:i?`retry ${e.attempt}`:e.stageWord,children:i?`retry ${e.attempt}`:e.stageWord})]})]}),t.jsx("span",{className:"w-20 truncate text-center text-label text-fg-muted",children:e.label})]},e.id)})})}function Le({lamps:a}){return t.jsx("div",{className:"space-y-2",children:a.map(e=>t.jsxs(_,{to:e.href,className:"focus-mark grid min-h-6 grid-cols-[12px_1fr] items-center gap-x-2 no-underline","aria-label":`${e.label}: ${e.state}, ${e.value}`,children:[t.jsx("span",{"aria-hidden":!0,className:`h-2.5 w-2.5 rounded-full border ${e.state==="healthy"?"border-ok bg-ok/70":e.state==="warning"?"border-warn bg-warn/70":"border-rule bg-transparent"}`}),t.jsxs("span",{className:"flex flex-wrap items-baseline justify-between gap-x-3",children:[t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:e.label}),t.jsx("span",{className:"text-label text-fg-muted",children:e.value})]})]},e.key))})}const O=15e3,Te=8,We=86400;function Ue(){const a=je(),e=a??"no-city",[s,n]=m.useState(!1),i=m.useRef(s);i.current=s;const o=T(`cockpit:usage:${e}`,()=>W().cityUsage(C("cockpit usage read"))),u=T(`cockpit:status:${e}`,()=>W().cityStatus(C("cockpit status read"))),h=T(`cockpit:runs:${e}`,()=>W().runCensus(C("cockpit run census read"))),v=T(`cockpit:sessions:${e}`,()=>W().listSessions(C("cockpit sessions read"))),k=be(),N=ve();I(o.refresh,o.loading,i),I(u.refresh,u.loading,i),I(h.refresh,h.loading,i),I(v.refresh,v.loading,i);const f=R(U(o,e),s),$=R(U(u,e),s),P=R(U(h,e),s),A=R(U(v,e),s),j=R({source:k.source,loading:k.loading,sseState:k.sseState},s),r=f.data,c=$.data,S=P.data,M=A.data,p=j.source,[X,le]=m.useState([]),J=m.useRef(null);m.useEffect(()=>{if(s||r===void 0||!r.available||J.current===r.updated_at)return;J.current=r.updated_at;const l=Math.max(0,r.recent.invocations);le(z=>[...z,l].slice(-48))},[s,r]);const x=r?.available===!0,d=r?.last_24h,oe=r===void 0?void 0:[r.available?void 0:"usage recording is not local",r.available&&!r.recording?"usage recording is off":void 0,r.partial?r.partial_reasons?.join(" · ")||"usage estimate is partial":void 0,r.today.unpriced>0||r.recent.unpriced>0||(r.last_24h?.unpriced??0)>0?"cost excludes unpriced model calls":void 0].filter(l=>l!==void 0).join(" · ")||void 0,y=x?r.recent.invocations>0?{totals:r.recent,seconds:r.recent_window_secs}:d!==void 0&&d.invocations>0?{totals:d,seconds:We,basis:"24 h average"}:null:null,F=y?_e(y.totals,y.seconds):null,E=y?$e(y.totals,y.seconds):null,Z=c?.session_counts_detail?.active,L=Z??(M===void 0?null:(M.items??[]).filter(l=>l.running).length),ce=m.useMemo(()=>Ne(S?.status_counts??null),[S?.status_counts]),ee=m.useMemo(()=>(M?.items??[]).filter(l=>l.running&&typeof l.context_pct=="number"&&Number.isFinite(l.context_pct)).sort((l,z)=>(z.context_pct??0)-(l.context_pct??0)).slice(0,8).map(l=>({id:l.id,label:l.title||l.session_name||l.template,value:l.context_pct??0,href:"/agents"})),[M?.items]),te=m.useMemo(()=>p===void 0||p.status==="error"?[]:[...p.data.lanes,...p.data.blockedLanes].slice(0,Te).map(Me),[p]),ue=j.sseState==="open"?"healthy":"unknown",de=c!==void 0&&$.stale,me=c?.partial===!0,g=de?"stale":me?"partial":null,he=[{key:"feed",label:"live feed",value:j.sseState==="open"?"connected":De(j.sseState),state:ue,href:"/activity"},c===void 0?{key:"store",label:"dolt store",value:"unavailable",state:"unknown",href:"/health"}:c.store_health===void 0?{key:"store",label:"dolt store",value:"not reported",state:"unknown",href:"/health"}:{key:"store",label:"dolt store",value:g===null?K(c.store_health):`${g} · last reported ${K(c.store_health)}`,state:g!==null?"unknown":K(c.store_health)!=="healthy"?"warning":"healthy",href:"/health"},c===void 0?{key:"mail",label:"mail",value:"unavailable",state:"unknown",href:"/mail"}:{key:"mail",label:"mail",value:g===null?`${c.mail.unread} unread`:`${g} · last reported ${c.mail.unread} unread`,state:g!==null?"unknown":c.mail.unread>0?"warning":"healthy",href:"/mail"},c===void 0?{key:"agents",label:"agents",value:"unavailable",state:"unknown",href:"/agents"}:{key:"agents",label:"agents",value:`${g===null?"":`${g} · last reported `}${c.agents.quarantined>0?`${c.agents.quarantined} quarantined`:`${c.agents.running}/${c.agents.total} running`}`,state:g!==null?"unknown":c.agents.quarantined>0||c.agents.suspended>0?"warning":"healthy",href:"/agents"}],w=H(f,"usage",oe),ae=[y?.basis,w].filter(l=>l!==void 0).join(" · ")||void 0,fe=H($,"city status",c?.partial?"city status is partial":void 0),se=H(P,"run states",S?.partial?"run projection is partial":void 0),G=H(A,"sessions",M?.partial?"session list is partial":void 0),xe=Z===void 0?G:fe,ne=p===void 0?j.loading?"loading run progress…":"run progress unavailable":p.status==="error"?"run progress unavailable":p.status==="stale"?"run progress is stale":te.length===0?"no runs in flight":void 0,ge=`${a??"city"} · ${q(L)} active sessions · ${q(S?.status_counts.active)} running · ${x?B(r.today.input_tokens+r.today.output_tokens+r.today.cache_read_tokens+r.today.cache_creation_tokens):"—"} tokens today`;return t.jsxs("section",{children:[t.jsx(ye,{title:"Home",synopsis:ge,meta:t.jsxs("button",{type:"button","aria-pressed":s,onClick:()=>n(l=>!l),className:"focus-mark min-h-6 border-b border-rule text-fg-muted hover:text-fg",children:[s?"resume":"pause"," instruments"]})}),t.jsx(Ce,{items:N.topItems}),t.jsx("div",{className:"mb-8",children:t.jsx(Pe,{samples:X,available:x,note:w??(X.length===0?"waiting for the first usage sample":void 0)})}),t.jsxs("div",{className:"mb-8 grid items-start justify-items-center gap-x-4 gap-y-8 [grid-template-columns:repeat(auto-fit,minmax(150px,1fr))]","data-testid":"dial-grid",children:[t.jsx(Re,{label:"model calls today",value:x?r.today.invocations:null,note:x?[`${V(r.today.cost_usd_estimate)} estimated today`,w].filter(l=>l!==void 0).join(" · "):w}),t.jsx(Y,{label:"active sessions",value:L,max:Math.max(10,(L??0)*1.25),formatted:q(L),href:"/agents",note:xe}),t.jsx(Y,{label:"tokens / min",value:F,max:Math.max(1e3,(F??0)*1.25),formatted:F===null?"—":B(F),href:"/activity",note:ae}),t.jsx(Y,{label:"burn · $ / hr",value:E,max:Math.max(10,(E??0)*1.25),formatted:E===null?"—":V(E),href:"/activity",note:ae})]}),t.jsxs("section",{className:"mb-8","aria-labelledby":"last24h-title",children:[t.jsx("h2",{id:"last24h-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"last 24 hours"}),t.jsxs("div",{className:"grid items-start justify-items-center gap-x-4 gap-y-4 [grid-template-columns:repeat(auto-fit,minmax(120px,1fr))]","data-testid":"last24h-grid",children:[t.jsx(D,{label:"tokens in",value:x&&d!==void 0?B(d.input_tokens):null}),t.jsx(D,{label:"tokens out",value:x&&d!==void 0?B(d.output_tokens):null}),t.jsx(D,{label:"model calls",value:x&&d!==void 0?q(d.invocations):null}),t.jsx(D,{label:"est. cost",value:x&&d!==void 0?V(d.cost_usd_estimate):null})]}),w&&t.jsx(b,{children:w})]}),t.jsxs("section",{className:"mb-8","aria-labelledby":"run-state-title",children:[t.jsx("h2",{id:"run-state-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"runs in flight · canonical state"}),t.jsx(Ae,{segments:ce,available:S!==void 0}),se&&t.jsx(b,{children:se})]}),t.jsxs("div",{className:"grid grid-cols-1 gap-10 lg:[grid-template-columns:5fr_4fr_3fr]",children:[t.jsxs("section",{"aria-labelledby":"context-title",children:[t.jsx("h2",{id:"context-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"live session context"}),t.jsx(Fe,{meters:ee}),(G||ee.length===0)&&t.jsx(b,{children:G??"no live session context reported"})]}),t.jsxs("section",{"aria-labelledby":"progress-title",children:[t.jsx("h2",{id:"progress-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"formula run progress"}),t.jsx(Ee,{runs:te}),ne&&t.jsx(b,{children:ne})]}),t.jsxs("section",{"aria-labelledby":"systems-title",children:[t.jsx("h2",{id:"systems-title",className:"mb-2 text-label uppercase tracking-wider text-fg-faint",children:"systems"}),t.jsx(Le,{lamps:he})]})]})]})}function I(a,e,s){m.useEffect(()=>{let n=!1,i;function o(h){n||(i!==void 0&&clearTimeout(i),i=setTimeout(u,h))}function u(){if(i=void 0,s.current){o(O);return}const h=a();o(ie),h.then(()=>o(O),()=>o(O))}return o(e?ie:O),()=>{n=!0,i!==void 0&&clearTimeout(i)}},[e,s,a])}function R(a,e){const s=m.useRef(a);return e||(s.current=a),s.current}function U(a,e){const s=m.useRef(null);s.current?.key!==e&&(s.current=null),a.error!==null&&a.data!==void 0?s.current={key:e,data:a.data,fetchedAt:a.fetchedAt}:s.current!==null&&!a.loading&&(s.current=null);const n=s.current;return{data:n?.data??a.data,loading:a.loading,fetchedAt:n?.fetchedAt??a.fetchedAt,stale:n!==null}}function H(a,e,s){if(a.data===void 0)return a.loading?`loading ${e}…`:`${e} unavailable`;if(a.stale)return`${e} is stale · refresh failed`;if(s)return s}function K(a){const e=a.last_gc_status?.trim();return e&&e!=="success"?"maintenance failed":a.warning?"maintenance overdue":"healthy"}function Ce({items:a}){const e=a.find(n=>n.severity==="attention");if(!e)return null;const s=t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"mr-2 uppercase tracking-wider",children:"needs you"}),t.jsx("span",{className:"text-fg",children:e.title})]});return t.jsx("div",{className:"mb-8 border-y border-accent/30 py-2 text-label text-accent",children:e.href?t.jsx(_,{to:e.href,className:"focus-mark inline-block min-h-6 no-underline",children:s}):s})}function De(a){switch(a){case"connecting":return"connecting";case"degraded":return"degraded";default:return"disconnected"}}function q(a){return typeof a=="number"&&Number.isFinite(a)?String(Math.max(0,Math.round(a))):"—"}function B(a){return new Intl.NumberFormat("en",{notation:"compact",maximumFractionDigits:1}).format(Math.max(0,a))}function V(a){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:2}).format(Math.max(0,a))}export{Ue as CockpitHomePage}; diff --git a/internal/api/dashboardspa/dist/assets/Field-BEMyWxxD.js b/internal/api/dashboardspa/dist/assets/Field-BSdtNgao.js similarity index 85% rename from internal/api/dashboardspa/dist/assets/Field-BEMyWxxD.js rename to internal/api/dashboardspa/dist/assets/Field-BSdtNgao.js index d8d059d744..a872551cd2 100644 --- a/internal/api/dashboardspa/dist/assets/Field-BEMyWxxD.js +++ b/internal/api/dashboardspa/dist/assets/Field-BSdtNgao.js @@ -1 +1 @@ -import{j as e}from"./index-DDS7Ehww.js";function i({label:t,children:s,variant:a="definition"}){return a==="form"?e.jsxs("label",{className:"block space-y-1.5",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:t}),s]}):e.jsxs("div",{children:[e.jsx("dt",{className:"text-label uppercase tracking-wider text-fg-faint mb-1",children:t}),e.jsx("dd",{className:"text-body text-fg",children:s})]})}export{i as F}; +import{j as e}from"./index-BDHAaQRP.js";function i({label:t,children:s,variant:a="definition"}){return a==="form"?e.jsxs("label",{className:"block space-y-1.5",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:t}),s]}):e.jsxs("div",{children:[e.jsx("dt",{className:"text-label uppercase tracking-wider text-fg-faint mb-1",children:t}),e.jsx("dd",{className:"text-body text-fg",children:s})]})}export{i as F}; diff --git a/internal/api/dashboardspa/dist/assets/FormulaRunDetail-Cz_p7EMT.js b/internal/api/dashboardspa/dist/assets/FormulaRunDetail-BceCG60V.js similarity index 98% rename from internal/api/dashboardspa/dist/assets/FormulaRunDetail-Cz_p7EMT.js rename to internal/api/dashboardspa/dist/assets/FormulaRunDetail-BceCG60V.js index ce9e1c7575..592c7b0792 100644 --- a/internal/api/dashboardspa/dist/assets/FormulaRunDetail-Cz_p7EMT.js +++ b/internal/api/dashboardspa/dist/assets/FormulaRunDetail-BceCG60V.js @@ -1 +1 @@ -import{j as n,r as f,S as ae,a3 as z,a4 as D,a5 as oe,a6 as ie,C as Z,A as H,b as le,E as ce,T as ue,f as de,u as fe,a7 as me,L as pe,B as ge,Q as xe,G}from"./index-DDS7Ehww.js";import{P as he}from"./PageHeader-nOBkk_AA.js";import{u as be,R as ke,B as ye}from"./BeadDetailModal-DpGateYl.js";import{u as ve,S as je}from"./LiveSessionPeek-F4FmVdxt.js";import{S as U}from"./StageLadder-BZC9xxGP.js";import"./format-fte2CeYD.js";import"./Field-BEMyWxxD.js";import"./constants-CQJOeNM1.js";import"./time-BVuL_AnL.js";const we=/^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$/,q={pending:"pending",ready:"ready",running:"running",active:"running",done:"done",completed:"done",failed:"failed",blocked:"blocked",skipped:"skipped",canceled:"canceled"};function Ne({node:e,selected:t,onToggle:s}){const r=Re(e.constructKind),o=Ie(e.status),i=e.iterationSummary.kind==="stacked"?`${e.iterationSummary.iterationCount} iterations, showing ${e.iterationSummary.visibleIteration}`:null,u=e.attemptSummary.kind==="tracked"&&e.attemptSummary.badge.kind==="bounded"?` · attempt ${e.attemptSummary.badge.label}${_e(e)}`:"";return n.jsxs("button",{type:"button","aria-pressed":t,onClick:()=>s(e.id),className:`focus-mark w-full text-left px-4 py-3 bg-transparent transition-colors duration-150 ease-out-quart ${r} ${t?"text-fg border-accent bg-surface-tint ring-2 ring-accent/45 ring-offset-2 ring-offset-surface":"text-fg border-rule hover:border-fg-faint hover:bg-surface-tint"}`,children:[n.jsxs("div",{className:"flex items-start justify-between gap-3",children:[n.jsxs("div",{children:[n.jsx("p",{className:"text-body text-fg leading-snug",children:e.title}),n.jsxs("p",{className:"mt-1 text-label uppercase tracking-wider text-fg-faint",children:[Se(e.constructKind),u]})]}),n.jsxs("span",{className:`text-label uppercase tracking-wider shrink-0 ${o}`,children:[Ee(e.status)," ",q[e.status]]})]}),i&&n.jsxs("p",{className:"mt-2 text-label uppercase tracking-wider text-fg-faint tnum",children:["stacked history: ",i]}),e.controlBadges.length>0&&n.jsx("div",{className:"mt-2 flex flex-wrap gap-2",children:e.controlBadges.map(l=>n.jsxs("span",{className:"text-label uppercase tracking-wider text-fg-muted border border-rule px-1.5 py-0.5",children:[l.label,": ",q[l.status]]},l.id))})]})}function _e(e){return e.attemptSummary.kind==="tracked"&&e.attemptSummary.active.kind==="running"?` · running attempt ${e.attemptSummary.active.value}`:""}function Se(e){switch(e){case"run-root":return"run root";case"run-finalize":return"finalize";case"step":case"retry":case"check-loop":case"scope":case"condition":case"fanout":case"expansion":case"scope-check":case"spec":case"control":case"unknown":return e.replace(/-/g," ")}}function Re(e){switch(e){case"run-root":return"formula-run-node-shape-root";case"step":case"unknown":return"formula-run-node-shape-step";case"retry":return"formula-run-node-shape-retry";case"check-loop":return"formula-run-node-shape-check-loop";case"scope":return"formula-run-node-shape-scope";case"condition":return"formula-run-node-shape-condition";case"fanout":return"formula-run-node-shape-fanout";case"expansion":return"formula-run-node-shape-expansion";case"scope-check":case"run-finalize":case"spec":case"control":return"formula-run-node-shape-control"}}function Ie(e){switch(e){case"failed":case"blocked":return"text-accent";case"active":case"running":case"ready":return"text-fg";case"completed":case"done":return"text-fg-muted";case"pending":case"skipped":case"canceled":return"text-fg-faint"}}function Ee(e){switch(e){case"completed":case"done":return"✓";case"active":case"running":return"●";case"failed":case"blocked":return"!";case"skipped":return"∅";case"canceled":return"⊘";case"pending":case"ready":return"·"}}function Le({detail:e,selectedNodeId:t,onToggleNode:s}){const r=Ce(e),o=Fe(e);return r.length===0?n.jsx("p",{className:"text-body text-fg-muted italic",children:"No graph nodes have materialized for this formula run."}):n.jsxs("section",{"aria-label":"Formula run graph",children:[n.jsx("div",{className:"flex items-baseline justify-between gap-4",children:n.jsx("h2",{className:"text-title text-fg",children:"Formula Graph"})}),n.jsx("ol",{className:"mt-5 space-y-3 relative",children:r.map((i,u)=>{const l=o.get(i.id),d=u>0?o.get(r[u-1]?.id??""):void 0,a=l!==void 0&&l!==d;return n.jsxs("li",{className:"relative pl-6",children:[a&&n.jsx("p",{className:"mb-1 text-label uppercase tracking-wider text-fg-faint",children:l}),ut.visibleInGraph!==!1)}function Fe(e){const t=new Map;for(const s of e.lanes)for(const r of s.nodeIds)t.set(r,s.label);return t}function $e({node:e,visible:t}){const s=f.useMemo(()=>e?.executionInstances.sort(Q)??[],[e]),r=f.useMemo(()=>Me(e?.visibleExecutionInstanceId,s),[e?.visibleExecutionInstanceId,s]),[o,i]=f.useState(null);if(f.useEffect(()=>{i(r?h(r):null)},[e?.id,r]),!e)return n.jsx("p",{className:"text-body text-fg-muted italic",children:"Select a node to inspect its session."});if(s.length===0)return n.jsx("p",{className:"text-body text-fg-muted italic",children:V(e)});const u=s.find(c=>h(c)===o)??r??s[0],l=u?E(u):"base",d=Pe(s),a=s.filter(c=>E(c)===l);return u?n.jsxs("section",{children:[n.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[n.jsx("h3",{className:"text-body font-semibold text-fg",children:e.title}),(e.historicalOnly||u?.historical)&&n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:e.historicalOnly?"historical-only":"historical"})]}),d.length>1&&n.jsxs("div",{className:"mt-3 flex flex-wrap items-baseline gap-x-2 gap-y-1 text-label",role:"radiogroup","aria-label":"Iterations",children:[n.jsx("span",{className:"uppercase tracking-wider text-fg-faint",children:"Iterations"}),d.map(c=>{const m=c.instances.at(-1);if(!m)return null;const x=c.iteration==="base"?"Base":`Iteration ${c.iteration}`,b=c.iteration===l;return n.jsxs("span",{className:"flex items-baseline gap-1",children:[n.jsx("span",{"aria-hidden":!0,className:"text-fg-faint",children:"·"}),n.jsx("button",{type:"button",role:"radio","aria-checked":b,className:`focus-mark rounded-sm px-0.5 uppercase tracking-wider ${b?"text-fg font-semibold underline decoration-fg underline-offset-4":"text-fg-muted hover:text-fg"}`,onClick:()=>i(h(m)),children:x})]},x)})]}),a.length>1&&n.jsxs("div",{className:"mt-2 flex flex-wrap items-baseline gap-x-2 gap-y-1 text-label",role:"radiogroup","aria-label":"Attempts",children:[n.jsx("span",{className:"uppercase tracking-wider text-fg-faint",children:"Attempts"}),a.map(c=>n.jsxs("span",{className:"flex items-baseline gap-1",children:[n.jsx("span",{"aria-hidden":!0,className:"text-fg-faint",children:"·"}),n.jsxs("button",{type:"button",role:"radio","aria-checked":h(c)===h(u),className:`focus-mark rounded-sm px-0.5 uppercase tracking-wider ${h(c)===h(u)?"text-fg font-semibold underline decoration-fg underline-offset-4":"text-fg-muted hover:text-fg"}`,onClick:()=>i(h(c)),children:["Attempt ",K(c)]})]},h(c)))]}),n.jsxs("dl",{className:"mt-4 grid grid-cols-[max-content_minmax(0,1fr)] gap-x-3 gap-y-1 text-label",children:[n.jsx("dt",{className:"uppercase tracking-wider text-fg-faint",children:"Execution instance"}),n.jsx("dd",{className:"break-all text-fg-muted tnum",children:u.id}),n.jsx("dt",{className:"uppercase tracking-wider text-fg-faint",children:"Bead"}),n.jsx("dd",{className:"break-all text-fg-muted tnum",children:u.beadId})]}),n.jsx(Be,{instance:u,visible:t})]}):n.jsx("p",{className:"text-body text-fg-muted italic",children:V(e)})}function Be({instance:e,visible:t}){const s=e.session.kind==="attached"?e.session:null,r=s?.link?.sessionId??null,o=t&&!!s?.streamable,i=ve(r,o);if(s===null)return n.jsx("p",{className:"mt-5 text-body text-fg-muted italic",children:Ae(e)});if(r===null)return n.jsx("p",{className:"mt-5 text-body text-fg-muted italic",children:"Session transcript is unavailable for this node."});const u=De(i.stream),l=i.status==="loading",d=i.status==="ready"?i.result:null,a=i.status==="failed"?i.error:null,c=i.status==="ready"&&i.stream.status==="degraded"?i.stream.error:null;return n.jsxs("div",{className:"mt-5 space-y-4",children:[s?.streamable&&n.jsx("div",{className:"flex justify-end",children:n.jsx(ae,{tone:u.tone,label:u.label,title:`Session stream: ${i.stream.status}`,className:"text-label uppercase tracking-wider"})}),c!==null&&n.jsx("p",{className:"text-accent",role:"alert",children:c}),n.jsx(je,{loading:l,error:a,result:d})]})}function De(e){switch(e.status){case"open":return{tone:"ok",label:"live"};case"connecting":return{tone:"warn",label:"connecting"};case"closed":return{tone:"stuck",label:"offline"};case"degraded":return{tone:"warn",label:"degraded"};case"idle":return{tone:"neutral",label:"snapshot"}}}function V(e){const t=e.executionInstances.filter(r=>r.session.kind==="none");return t.some(r=>r.currentIteration&&r.session.kind==="none"&&r.session.reason==="session_unresolved"&&J(r.status))?"Session unresolved for the current running node.":t.some(r=>r.session.kind==="none"&&r.session.reason==="session_unresolved")?"Session unresolved for this node.":"This node has not started a session yet."}function Ae(e){return e.session.kind==="attached"?"":e.currentIteration&&e.session.reason==="session_unresolved"&&J(e.status)?"Session unresolved for the current running node.":e.session.reason==="session_unresolved"?"Session unresolved for this node.":"This node has not started a session yet."}function J(e){return e==="active"||e==="running"}function Me(e,t){return(e?t.find(r=>h(r)===e):void 0)??t.at(-1)}function Pe(e){const t=new Map;for(const s of e){const r=E(s);t.set(r,[...t.get(r)??[],s])}return[...t.entries()].map(([s,r])=>({iteration:s,instances:r.sort(Q)})).sort((s,r)=>A(s.iteration)-A(r.iteration))}function Q(e,t){return A(E(e))-A(E(t))||K(e)-K(t)||e.id.localeCompare(t.id)}function h(e){return e.id}function E(e){return e.iteration.kind==="loop"?e.iteration.value:"base"}function A(e){return e==="base"?0:e}function K(e){return e.attempt.kind==="attempt"?e.attempt.value:1}function Te({selectedNode:e}){return n.jsxs("section",{"aria-label":"Run evidence",children:[n.jsx("div",{className:"flex items-baseline gap-2 text-label",role:"tablist","aria-label":"Run evidence views",children:n.jsx("button",{id:"run-evidence-tab-session",type:"button",role:"tab","aria-selected":!0,"aria-controls":"run-evidence-panel",className:"focus-mark rounded-sm px-0.5 uppercase tracking-wider text-fg font-semibold underline decoration-fg underline-offset-4",children:"Session"})}),n.jsx("div",{id:"run-evidence-panel",role:"tabpanel","aria-labelledby":"run-evidence-tab-session",className:"pt-5",children:n.jsx($e,{node:e,visible:!0})})]})}function Ke(e,t){const s=e.runIds.size===0||e.runIds.has(t.runId),r=e.rootBeadIds.size===0||e.rootBeadIds.has(t.rootBeadId);return s&&r}function Oe(e){const t={runIds:new Set,rootBeadIds:new Set};return v(e,t),v(p(e.run),t),v(p(e.payload),t),v(p(p(e.payload)?.run),t),v(p(e.bead),t),v(p(p(e.payload)?.bead),t),v(p(e.root),t),v(p(p(e.payload)?.root),t),O(p(e.metadata),t),O(p(p(e.payload)?.metadata),t),t}function v(e,t){e&&(k(t.runIds,e.run_id),k(t.runIds,e.workflow_id),k(t.rootBeadIds,e.root_bead_id),O(p(e.metadata),t))}function O(e,t){e&&(k(t.runIds,e["gc.run_id"]),k(t.runIds,e["gc.workflow_id"]),k(t.runIds,e.run_id),k(t.runIds,e.workflow_id),k(t.rootBeadIds,e["gc.root_bead_id"]),k(t.rootBeadIds,e.root_bead_id))}function k(e,t){if(typeof t!="string")return;const s=t.trim();s&&e.add(s)}function p(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0}function ze(e,t,s){const[r,o]=f.useState({nodeId:null,routeKey:"",source:"route"});f.useEffect(()=>{if(!e)return;const a=Ge(e,t);o(c=>c.routeKey===s&&(c.source==="user"||c.nodeId===a)?c:{nodeId:a,routeKey:s,source:"route"})},[e,s,t]);const i=f.useCallback(()=>{o(a=>({nodeId:null,routeKey:a.routeKey,source:"user"}))},[]);f.useEffect(()=>{const a=c=>{c.key==="Escape"&&i()};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[i]);const u=f.useCallback(a=>{o(c=>({nodeId:c.nodeId===a?null:a,routeKey:s,source:"user"}))},[s]),l=r.nodeId,d=f.useMemo(()=>e?.nodes.find(a=>a.id===l)??null,[e,l]);return{selectedNodeId:l,selectedNode:d,toggleNode:u,clearSelection:i}}function Ge(e,t){return t&&e.nodes.some(s=>s.id===t)?t:null}const W=[600,1200,2400],Ue=5e3,qe=18e4;async function Ve(e,t){let s=0;for(let r=0;;r+=1)try{return await z.runDetail(e)}catch(o){const i=We(o,r,s);if(i===void 0||t?.keepPolling?.()===!1||(ee(o)&&t?.onWarming?.({reason:o.reason}),s+=i,await Ye(i),t?.keepPolling?.()===!1))throw o}}function We(e,t,s){if(ee(e)){const r=W[t]??Ue;return s+r<=qe?r:void 0}return Xe(e)?W[t]:void 0}function ee(e){return e instanceof D&&e.status===503}function Xe(e){return e instanceof D?e.status>=500:e instanceof TypeError}function Ye(e){return new Promise(t=>setTimeout(t,e))}function Ze(e,t,s,r,o){const[i,u]=f.useState("unavailable"),l=f.useRef(s);l.current=s;const d=f.useRef(!1),a=te(e,r,o);return f.useEffect(()=>{if(d.current=!1,!e||!t||typeof EventSource>"u"){u("unavailable");return}let c=!1;u("connecting");const m=new EventSource(z.runDetailStreamUrl(e),{withCredentials:!0});m.onopen=()=>{c||u("open")};const x=b=>{if(c)return;const y=He(b.data,e,d);y!==null&&(oe(a,{kind:"loaded",detail:y}),l.current?.(y,a),u("open"))};return m.addEventListener("detail",x),m.onerror=()=>{c||u(m.readyState===EventSource.CLOSED?"closed":"connecting")},()=>{c=!0,m.close()}},[e,t,a]),i}function He(e,t,s){let r;try{r=JSON.parse(e)}catch(o){return X(t,s,o),null}try{return ie(r,z.runDetailStreamUrl(t))}catch(o){return X(t,s,o),null}}function X(e,t,s){t.current||(t.current=!0,Z({component:"formula-run-detail-stream",operation:"parse stream frame",message:`${e}: ${H(s)}`}))}function Je(e,t,s){const r=te(e,t,s),[o,i]=f.useState(null),u=f.useRef(0);f.useEffect(()=>()=>{u.current+=1},[]);const{data:l,loading:d,error:a,refresh:c}=le(r,()=>{const w=++u.current,N=()=>u.current===w;return Qe(e,{onWarming:$=>{N()&&i($)},keepPolling:N}).finally(()=>{N()&&i(null)})},{onError:w=>{e!==void 0&&nt("load detail",e,w)}}),[m,x]=f.useState(null),b=f.useCallback((w,N)=>x({key:N,detail:w}),[]),y=e!==void 0&&l?.kind!=="unsupported"&&l?.kind!=="not_found",L=Ze(e,y,b,t,s),M=m?.key===r?m.detail:null,g=L==="open"||L==="connecting",j=f.useCallback(async()=>{x(null),await c()},[c]);if(e===void 0)return{kind:"idle",refresh:et,streamActive:g};const C=M??(l?.kind==="loaded"?l.detail:null);return C!==null?{kind:"ready",detail:C,refresh:j,refreshState:tt(d,a),streamActive:g}:l?.kind==="unsupported"?{kind:"unsupported",refresh:j,streamActive:g}:l?.kind==="not_found"?{kind:"not_found",refresh:j,streamActive:g}:a!==null?{kind:"failed",error:a,refresh:j,streamActive:g}:{kind:"loading",warming:o,refresh:j,streamActive:g}}async function Qe(e,t){if(!e)return{kind:"unrequested"};try{return{kind:"loaded",detail:await Ve(e,t)}}catch(s){if(s instanceof D&&s.status===422&&s.reason==="not_run_view")return{kind:"unsupported"};if(s instanceof D&&s.status===404)return{kind:"not_found"};throw s}}async function et(){}function tt(e,t){return t!==null?{kind:"failed",error:t}:e?{kind:"refreshing"}:{kind:"idle"}}function nt(e,t,s){Z({component:"formula-run-detail",operation:e,message:`${t}: ${H(s)}`})}function te(e,t,s){return["formula-run",e??"missing",t??"default",s??"default"].map(encodeURIComponent).join(":")}const st=[G.bead,G.session],rt=[];function Rt(){const{runId:e}=ce(),[t]=ue(),s=xt(t),r=s.ok?s.scope:void 0,o=s.ok?null:s.error,i=t.get("node"),u=[e??"",r?.scopeKind??"",r?.scopeRef??"",i??""].join("\0"),l=Je(o?void 0:e,r?.scopeKind,r?.scopeRef),d=l.kind==="ready"?l:null,a=d?.detail??null,c=l.kind==="unsupported",m=l.kind==="not_found",x=l.kind==="loading",b=d!==null&&d.refreshState.kind==="refreshing",y=x||b,L=l.kind==="failed"?l.error:d!==null&&d.refreshState.kind==="failed"?d.refreshState.error:null,M=l.streamActive;de(o?rt:st,()=>{at(M,l.refresh)},{matches:S=>{const R=Oe(S);return a===null?e!==void 0&&(R.runIds.size===0||R.runIds.has(e)):a.progress.terminal&&ot(R)?!1:Ke(R,{runId:a.runId,rootBeadId:a.rootBeadId})}});const g=o??L,j=l.kind==="loading"&&l.warming?.reason==="unknown_run",{selectedNodeId:C,selectedNode:w,toggleNode:N}=ze(a,i,u),F=be(a?.rootBeadId??null),[$,P]=f.useState(null),ne=fe(),se=xe(),[B]=f.useState(()=>me(`runs:summary:${se??"no-city"}`)),T=f.useMemo(()=>{if(!e)return null;const S=B&&B.status!=="error"?B.data:null;return S==null?null:[...S.lanes,...S.blockedLanes].find(R=>R.id===e)??null},[B,e]),re=a?`${a.progress.visibleNodeCount} nodes. ${ht(a.progress)}.`:x&&!o||c||m?void 0:"Formula run unavailable.";return n.jsxs("section",{children:[n.jsx(he,{title:a?.title??"Formula Run",synopsis:re,meta:n.jsxs(n.Fragment,{children:[n.jsx(pe,{to:"/runs",className:"focus-mark text-label uppercase tracking-wider text-fg-muted hover:text-fg",children:"Runs"}),g&&a&&n.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:g}),a&&n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:ct(a)}),n.jsx(ge,{size:"sm",onClick:()=>{l.refresh()},disabled:y||!!o,children:b?"Refreshing":"Refresh"})]})}),y&&!o&&!a?T?n.jsxs(n.Fragment,{children:[n.jsx(U,{stages:T.stages,label:T.title}),n.jsx("p",{className:"text-body text-fg-muted italic mt-8",children:"Loading run detail."})]}):j?n.jsx("p",{className:"text-body text-fg-muted italic",role:"status",children:"This run may still be being recorded — new work can take a couple of minutes to appear — or it may no longer exist."}):n.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading formula run."}):c?n.jsx("p",{className:"text-body text-fg-muted",role:"status",children:"Detailed step view isn’t available for this run (v1/wisp runs are list-only) — this run appears in the run list only."}):m?n.jsx("p",{className:"text-body text-fg-muted",role:"status",children:"This run’s detail snapshot was not found. It may be a v1/wisp run, a completed run whose snapshot wasn’t retained, or no longer available."}):g&&!a?n.jsx("p",{className:"text-body text-accent",role:"alert",children:g}):d?n.jsxs(n.Fragment,{children:[n.jsx(it,{detail:d.detail}),n.jsx(U,{stages:d.detail.stages,label:d.detail.title}),n.jsx(dt,{detail:d.detail}),n.jsxs("div",{className:"mt-8 grid gap-10 lg:grid-cols-[minmax(0,0.95fr)_minmax(22rem,1.05fr)]",children:[n.jsx(Le,{detail:d.detail,selectedNodeId:C,onToggleNode:N}),n.jsx(Te,{selectedNode:w})]}),n.jsx(ke,{view:F.view,loading:F.loading,error:F.error,now:ne,onOpenBead:P}),n.jsx(ye,{open:$!==null,onClose:()=>P(null),beadId:$,onOpenBead:P})]}):null]})}function at(e,t){return e?Promise.resolve():t()}function ot(e){return e.runIds.size===0&&e.rootBeadIds.size===0}function it({detail:e}){const t=ut(e.formulaDetail);return n.jsxs("dl",{className:"grid gap-x-8 gap-y-3 sm:grid-cols-2 lg:grid-cols-4",children:[n.jsx(lt,{formula:e.formula}),t!==null&&n.jsx(I,{label:"Formula Detail",value:t}),n.jsx(I,{label:"Root",value:e.rootBeadId}),n.jsx(I,{label:"Scope",value:`${e.scopeKind}:${e.scopeRef}`}),n.jsx(I,{label:"Store",value:e.resolvedRootStore||e.rootStoreRef||"unknown"})]})}function I({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{className:"text-label uppercase tracking-wider text-fg-faint",children:e}),n.jsx("dd",{className:"text-body text-fg break-all tnum",children:t})]})}const Y="name inferred from bead title — supervisor did not set gc.formula on this graph.v2 root";function lt({formula:e}){if(e.kind!=="known")return n.jsx(I,{label:"Formula",value:"metadata missing"});switch(e.source){case"metadata":return n.jsx(I,{label:"Formula",value:e.name});case"title_fallback":return n.jsxs("div",{children:[n.jsx("dt",{className:"text-label uppercase tracking-wider text-fg-faint",children:"Formula"}),n.jsxs("dd",{className:"text-body text-warn break-all tnum",title:Y,"aria-label":`${e.name} (${Y})`,children:[e.name,n.jsx("span",{className:"ml-2 text-label uppercase tracking-wider text-warn",children:"inferred from bead title"})]})]});default:return e.source}}function ct(e){return e.snapshotEventSeq.kind==="known"?`v${e.snapshotVersion} · seq ${e.snapshotEventSeq.seq}`:`v${e.snapshotVersion}`}function ut(e){return e.kind==="available"?`available for ${e.target}`:e.reason==="missing_formula_metadata"?null:e.reason==="missing_run_target"?`missing run target for ${e.name}`:`${e.failure} for ${e.target}`}function dt({detail:e}){if(e.completeness.kind!=="partial")return null;const t=ft(e.completeness.reasons);return t.length===0?null:n.jsxs("p",{className:"mt-5 text-label uppercase tracking-wider text-warn",role:"status",children:["Partial run data: ",pt(t),"."]})}function ft(e){return e.filter(t=>!mt(t))}function mt(e){switch(e){case"formula_detail_missing_formula_metadata":case"formula_detail_missing_run_target":case"formula_detail_fetch_failed":return!0;case"supervisor_snapshot_partial":case"runtime_bead_read_failed":case"session_list_failed":return!1}}function pt(e){return e.map(gt).join(", ")}function gt(e){switch(e){case"supervisor_snapshot_partial":return"supervisor snapshot is partial";case"runtime_bead_read_failed":return"runtime bead refresh failed";case"session_list_failed":return"session list failed";case"formula_detail_missing_formula_metadata":return"formula metadata is missing";case"formula_detail_missing_run_target":return"formula run target is missing";case"formula_detail_fetch_failed":return"formula detail fetch failed"}}function xt(e){const t=e.getAll("scope_kind"),s=e.getAll("scope_ref");if(t.length>1||s.length>1)return{ok:!1,error:"Invalid run scope query."};const r=t[0],o=s[0];return r===void 0&&o===void 0?{ok:!0}:r===void 0||o===void 0?{ok:!1,error:"Invalid run scope query."}:r!=="city"&&r!=="rig"?{ok:!1,error:"Invalid run scope query."}:we.test(o)?{ok:!0,scope:{scopeKind:r,scopeRef:o}}:{ok:!1,error:"Invalid run scope query."}}function ht(e){const t=[_(e,["active","running"],"running"),_(e,["completed","done"],"done"),_(e,"ready","ready"),_(e,"blocked","blocked"),_(e,"failed","failed"),_(e,"skipped","skipped"),_(e,"pending","pending")].filter(s=>s!==null);return t.length>0?t.join(", "):"No node status yet"}function _(e,t,s){const o=(typeof t=="string"?[t]:t).reduce((i,u)=>i+(e.statusCounts[u]??0),0);return o>0?`${o} ${s}`:null}export{Rt as FormulaRunDetailPage,at as runDetailNudgeRefresh}; +import{j as n,r as f,S as ae,a3 as z,a4 as D,a5 as oe,a6 as ie,C as Z,A as H,b as le,E as ce,T as ue,f as de,u as fe,a7 as me,L as pe,B as ge,Q as xe,G}from"./index-BDHAaQRP.js";import{P as he}from"./PageHeader-BW5bf722.js";import{u as be,R as ke,B as ye}from"./BeadDetailModal-B7DCLOq5.js";import{u as ve,S as je}from"./LiveSessionPeek-VUsvyqKB.js";import{S as U}from"./StageLadder-CoXQBCKu.js";import"./format-fte2CeYD.js";import"./Field-BSdtNgao.js";import"./constants-D5DlRFFg.js";import"./time-BVuL_AnL.js";const we=/^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$/,q={pending:"pending",ready:"ready",running:"running",active:"running",done:"done",completed:"done",failed:"failed",blocked:"blocked",skipped:"skipped",canceled:"canceled"};function Ne({node:e,selected:t,onToggle:s}){const r=Re(e.constructKind),o=Ie(e.status),i=e.iterationSummary.kind==="stacked"?`${e.iterationSummary.iterationCount} iterations, showing ${e.iterationSummary.visibleIteration}`:null,u=e.attemptSummary.kind==="tracked"&&e.attemptSummary.badge.kind==="bounded"?` · attempt ${e.attemptSummary.badge.label}${_e(e)}`:"";return n.jsxs("button",{type:"button","aria-pressed":t,onClick:()=>s(e.id),className:`focus-mark w-full text-left px-4 py-3 bg-transparent transition-colors duration-150 ease-out-quart ${r} ${t?"text-fg border-accent bg-surface-tint ring-2 ring-accent/45 ring-offset-2 ring-offset-surface":"text-fg border-rule hover:border-fg-faint hover:bg-surface-tint"}`,children:[n.jsxs("div",{className:"flex items-start justify-between gap-3",children:[n.jsxs("div",{children:[n.jsx("p",{className:"text-body text-fg leading-snug",children:e.title}),n.jsxs("p",{className:"mt-1 text-label uppercase tracking-wider text-fg-faint",children:[Se(e.constructKind),u]})]}),n.jsxs("span",{className:`text-label uppercase tracking-wider shrink-0 ${o}`,children:[Ee(e.status)," ",q[e.status]]})]}),i&&n.jsxs("p",{className:"mt-2 text-label uppercase tracking-wider text-fg-faint tnum",children:["stacked history: ",i]}),e.controlBadges.length>0&&n.jsx("div",{className:"mt-2 flex flex-wrap gap-2",children:e.controlBadges.map(l=>n.jsxs("span",{className:"text-label uppercase tracking-wider text-fg-muted border border-rule px-1.5 py-0.5",children:[l.label,": ",q[l.status]]},l.id))})]})}function _e(e){return e.attemptSummary.kind==="tracked"&&e.attemptSummary.active.kind==="running"?` · running attempt ${e.attemptSummary.active.value}`:""}function Se(e){switch(e){case"run-root":return"run root";case"run-finalize":return"finalize";case"step":case"retry":case"check-loop":case"scope":case"condition":case"fanout":case"expansion":case"scope-check":case"spec":case"control":case"unknown":return e.replace(/-/g," ")}}function Re(e){switch(e){case"run-root":return"formula-run-node-shape-root";case"step":case"unknown":return"formula-run-node-shape-step";case"retry":return"formula-run-node-shape-retry";case"check-loop":return"formula-run-node-shape-check-loop";case"scope":return"formula-run-node-shape-scope";case"condition":return"formula-run-node-shape-condition";case"fanout":return"formula-run-node-shape-fanout";case"expansion":return"formula-run-node-shape-expansion";case"scope-check":case"run-finalize":case"spec":case"control":return"formula-run-node-shape-control"}}function Ie(e){switch(e){case"failed":case"blocked":return"text-accent";case"active":case"running":case"ready":return"text-fg";case"completed":case"done":return"text-fg-muted";case"pending":case"skipped":case"canceled":return"text-fg-faint"}}function Ee(e){switch(e){case"completed":case"done":return"✓";case"active":case"running":return"●";case"failed":case"blocked":return"!";case"skipped":return"∅";case"canceled":return"⊘";case"pending":case"ready":return"·"}}function Le({detail:e,selectedNodeId:t,onToggleNode:s}){const r=Ce(e),o=Fe(e);return r.length===0?n.jsx("p",{className:"text-body text-fg-muted italic",children:"No graph nodes have materialized for this formula run."}):n.jsxs("section",{"aria-label":"Formula run graph",children:[n.jsx("div",{className:"flex items-baseline justify-between gap-4",children:n.jsx("h2",{className:"text-title text-fg",children:"Formula Graph"})}),n.jsx("ol",{className:"mt-5 space-y-3 relative",children:r.map((i,u)=>{const l=o.get(i.id),d=u>0?o.get(r[u-1]?.id??""):void 0,a=l!==void 0&&l!==d;return n.jsxs("li",{className:"relative pl-6",children:[a&&n.jsx("p",{className:"mb-1 text-label uppercase tracking-wider text-fg-faint",children:l}),ut.visibleInGraph!==!1)}function Fe(e){const t=new Map;for(const s of e.lanes)for(const r of s.nodeIds)t.set(r,s.label);return t}function $e({node:e,visible:t}){const s=f.useMemo(()=>e?.executionInstances.sort(Q)??[],[e]),r=f.useMemo(()=>Me(e?.visibleExecutionInstanceId,s),[e?.visibleExecutionInstanceId,s]),[o,i]=f.useState(null);if(f.useEffect(()=>{i(r?h(r):null)},[e?.id,r]),!e)return n.jsx("p",{className:"text-body text-fg-muted italic",children:"Select a node to inspect its session."});if(s.length===0)return n.jsx("p",{className:"text-body text-fg-muted italic",children:V(e)});const u=s.find(c=>h(c)===o)??r??s[0],l=u?E(u):"base",d=Pe(s),a=s.filter(c=>E(c)===l);return u?n.jsxs("section",{children:[n.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[n.jsx("h3",{className:"text-body font-semibold text-fg",children:e.title}),(e.historicalOnly||u?.historical)&&n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:e.historicalOnly?"historical-only":"historical"})]}),d.length>1&&n.jsxs("div",{className:"mt-3 flex flex-wrap items-baseline gap-x-2 gap-y-1 text-label",role:"radiogroup","aria-label":"Iterations",children:[n.jsx("span",{className:"uppercase tracking-wider text-fg-faint",children:"Iterations"}),d.map(c=>{const m=c.instances.at(-1);if(!m)return null;const x=c.iteration==="base"?"Base":`Iteration ${c.iteration}`,b=c.iteration===l;return n.jsxs("span",{className:"flex items-baseline gap-1",children:[n.jsx("span",{"aria-hidden":!0,className:"text-fg-faint",children:"·"}),n.jsx("button",{type:"button",role:"radio","aria-checked":b,className:`focus-mark rounded-sm px-0.5 uppercase tracking-wider ${b?"text-fg font-semibold underline decoration-fg underline-offset-4":"text-fg-muted hover:text-fg"}`,onClick:()=>i(h(m)),children:x})]},x)})]}),a.length>1&&n.jsxs("div",{className:"mt-2 flex flex-wrap items-baseline gap-x-2 gap-y-1 text-label",role:"radiogroup","aria-label":"Attempts",children:[n.jsx("span",{className:"uppercase tracking-wider text-fg-faint",children:"Attempts"}),a.map(c=>n.jsxs("span",{className:"flex items-baseline gap-1",children:[n.jsx("span",{"aria-hidden":!0,className:"text-fg-faint",children:"·"}),n.jsxs("button",{type:"button",role:"radio","aria-checked":h(c)===h(u),className:`focus-mark rounded-sm px-0.5 uppercase tracking-wider ${h(c)===h(u)?"text-fg font-semibold underline decoration-fg underline-offset-4":"text-fg-muted hover:text-fg"}`,onClick:()=>i(h(c)),children:["Attempt ",K(c)]})]},h(c)))]}),n.jsxs("dl",{className:"mt-4 grid grid-cols-[max-content_minmax(0,1fr)] gap-x-3 gap-y-1 text-label",children:[n.jsx("dt",{className:"uppercase tracking-wider text-fg-faint",children:"Execution instance"}),n.jsx("dd",{className:"break-all text-fg-muted tnum",children:u.id}),n.jsx("dt",{className:"uppercase tracking-wider text-fg-faint",children:"Bead"}),n.jsx("dd",{className:"break-all text-fg-muted tnum",children:u.beadId})]}),n.jsx(Be,{instance:u,visible:t})]}):n.jsx("p",{className:"text-body text-fg-muted italic",children:V(e)})}function Be({instance:e,visible:t}){const s=e.session.kind==="attached"?e.session:null,r=s?.link?.sessionId??null,o=t&&!!s?.streamable,i=ve(r,o);if(s===null)return n.jsx("p",{className:"mt-5 text-body text-fg-muted italic",children:Ae(e)});if(r===null)return n.jsx("p",{className:"mt-5 text-body text-fg-muted italic",children:"Session transcript is unavailable for this node."});const u=De(i.stream),l=i.status==="loading",d=i.status==="ready"?i.result:null,a=i.status==="failed"?i.error:null,c=i.status==="ready"&&i.stream.status==="degraded"?i.stream.error:null;return n.jsxs("div",{className:"mt-5 space-y-4",children:[s?.streamable&&n.jsx("div",{className:"flex justify-end",children:n.jsx(ae,{tone:u.tone,label:u.label,title:`Session stream: ${i.stream.status}`,className:"text-label uppercase tracking-wider"})}),c!==null&&n.jsx("p",{className:"text-accent",role:"alert",children:c}),n.jsx(je,{loading:l,error:a,result:d})]})}function De(e){switch(e.status){case"open":return{tone:"ok",label:"live"};case"connecting":return{tone:"warn",label:"connecting"};case"closed":return{tone:"stuck",label:"offline"};case"degraded":return{tone:"warn",label:"degraded"};case"idle":return{tone:"neutral",label:"snapshot"}}}function V(e){const t=e.executionInstances.filter(r=>r.session.kind==="none");return t.some(r=>r.currentIteration&&r.session.kind==="none"&&r.session.reason==="session_unresolved"&&J(r.status))?"Session unresolved for the current running node.":t.some(r=>r.session.kind==="none"&&r.session.reason==="session_unresolved")?"Session unresolved for this node.":"This node has not started a session yet."}function Ae(e){return e.session.kind==="attached"?"":e.currentIteration&&e.session.reason==="session_unresolved"&&J(e.status)?"Session unresolved for the current running node.":e.session.reason==="session_unresolved"?"Session unresolved for this node.":"This node has not started a session yet."}function J(e){return e==="active"||e==="running"}function Me(e,t){return(e?t.find(r=>h(r)===e):void 0)??t.at(-1)}function Pe(e){const t=new Map;for(const s of e){const r=E(s);t.set(r,[...t.get(r)??[],s])}return[...t.entries()].map(([s,r])=>({iteration:s,instances:r.sort(Q)})).sort((s,r)=>A(s.iteration)-A(r.iteration))}function Q(e,t){return A(E(e))-A(E(t))||K(e)-K(t)||e.id.localeCompare(t.id)}function h(e){return e.id}function E(e){return e.iteration.kind==="loop"?e.iteration.value:"base"}function A(e){return e==="base"?0:e}function K(e){return e.attempt.kind==="attempt"?e.attempt.value:1}function Te({selectedNode:e}){return n.jsxs("section",{"aria-label":"Run evidence",children:[n.jsx("div",{className:"flex items-baseline gap-2 text-label",role:"tablist","aria-label":"Run evidence views",children:n.jsx("button",{id:"run-evidence-tab-session",type:"button",role:"tab","aria-selected":!0,"aria-controls":"run-evidence-panel",className:"focus-mark rounded-sm px-0.5 uppercase tracking-wider text-fg font-semibold underline decoration-fg underline-offset-4",children:"Session"})}),n.jsx("div",{id:"run-evidence-panel",role:"tabpanel","aria-labelledby":"run-evidence-tab-session",className:"pt-5",children:n.jsx($e,{node:e,visible:!0})})]})}function Ke(e,t){const s=e.runIds.size===0||e.runIds.has(t.runId),r=e.rootBeadIds.size===0||e.rootBeadIds.has(t.rootBeadId);return s&&r}function Oe(e){const t={runIds:new Set,rootBeadIds:new Set};return v(e,t),v(p(e.run),t),v(p(e.payload),t),v(p(p(e.payload)?.run),t),v(p(e.bead),t),v(p(p(e.payload)?.bead),t),v(p(e.root),t),v(p(p(e.payload)?.root),t),O(p(e.metadata),t),O(p(p(e.payload)?.metadata),t),t}function v(e,t){e&&(k(t.runIds,e.run_id),k(t.runIds,e.workflow_id),k(t.rootBeadIds,e.root_bead_id),O(p(e.metadata),t))}function O(e,t){e&&(k(t.runIds,e["gc.run_id"]),k(t.runIds,e["gc.workflow_id"]),k(t.runIds,e.run_id),k(t.runIds,e.workflow_id),k(t.rootBeadIds,e["gc.root_bead_id"]),k(t.rootBeadIds,e.root_bead_id))}function k(e,t){if(typeof t!="string")return;const s=t.trim();s&&e.add(s)}function p(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0}function ze(e,t,s){const[r,o]=f.useState({nodeId:null,routeKey:"",source:"route"});f.useEffect(()=>{if(!e)return;const a=Ge(e,t);o(c=>c.routeKey===s&&(c.source==="user"||c.nodeId===a)?c:{nodeId:a,routeKey:s,source:"route"})},[e,s,t]);const i=f.useCallback(()=>{o(a=>({nodeId:null,routeKey:a.routeKey,source:"user"}))},[]);f.useEffect(()=>{const a=c=>{c.key==="Escape"&&i()};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[i]);const u=f.useCallback(a=>{o(c=>({nodeId:c.nodeId===a?null:a,routeKey:s,source:"user"}))},[s]),l=r.nodeId,d=f.useMemo(()=>e?.nodes.find(a=>a.id===l)??null,[e,l]);return{selectedNodeId:l,selectedNode:d,toggleNode:u,clearSelection:i}}function Ge(e,t){return t&&e.nodes.some(s=>s.id===t)?t:null}const W=[600,1200,2400],Ue=5e3,qe=18e4;async function Ve(e,t){let s=0;for(let r=0;;r+=1)try{return await z.runDetail(e)}catch(o){const i=We(o,r,s);if(i===void 0||t?.keepPolling?.()===!1||(ee(o)&&t?.onWarming?.({reason:o.reason}),s+=i,await Ye(i),t?.keepPolling?.()===!1))throw o}}function We(e,t,s){if(ee(e)){const r=W[t]??Ue;return s+r<=qe?r:void 0}return Xe(e)?W[t]:void 0}function ee(e){return e instanceof D&&e.status===503}function Xe(e){return e instanceof D?e.status>=500:e instanceof TypeError}function Ye(e){return new Promise(t=>setTimeout(t,e))}function Ze(e,t,s,r,o){const[i,u]=f.useState("unavailable"),l=f.useRef(s);l.current=s;const d=f.useRef(!1),a=te(e,r,o);return f.useEffect(()=>{if(d.current=!1,!e||!t||typeof EventSource>"u"){u("unavailable");return}let c=!1;u("connecting");const m=new EventSource(z.runDetailStreamUrl(e),{withCredentials:!0});m.onopen=()=>{c||u("open")};const x=b=>{if(c)return;const y=He(b.data,e,d);y!==null&&(oe(a,{kind:"loaded",detail:y}),l.current?.(y,a),u("open"))};return m.addEventListener("detail",x),m.onerror=()=>{c||u(m.readyState===EventSource.CLOSED?"closed":"connecting")},()=>{c=!0,m.close()}},[e,t,a]),i}function He(e,t,s){let r;try{r=JSON.parse(e)}catch(o){return X(t,s,o),null}try{return ie(r,z.runDetailStreamUrl(t))}catch(o){return X(t,s,o),null}}function X(e,t,s){t.current||(t.current=!0,Z({component:"formula-run-detail-stream",operation:"parse stream frame",message:`${e}: ${H(s)}`}))}function Je(e,t,s){const r=te(e,t,s),[o,i]=f.useState(null),u=f.useRef(0);f.useEffect(()=>()=>{u.current+=1},[]);const{data:l,loading:d,error:a,refresh:c}=le(r,()=>{const w=++u.current,N=()=>u.current===w;return Qe(e,{onWarming:$=>{N()&&i($)},keepPolling:N}).finally(()=>{N()&&i(null)})},{onError:w=>{e!==void 0&&nt("load detail",e,w)}}),[m,x]=f.useState(null),b=f.useCallback((w,N)=>x({key:N,detail:w}),[]),y=e!==void 0&&l?.kind!=="unsupported"&&l?.kind!=="not_found",L=Ze(e,y,b,t,s),M=m?.key===r?m.detail:null,g=L==="open"||L==="connecting",j=f.useCallback(async()=>{x(null),await c()},[c]);if(e===void 0)return{kind:"idle",refresh:et,streamActive:g};const C=M??(l?.kind==="loaded"?l.detail:null);return C!==null?{kind:"ready",detail:C,refresh:j,refreshState:tt(d,a),streamActive:g}:l?.kind==="unsupported"?{kind:"unsupported",refresh:j,streamActive:g}:l?.kind==="not_found"?{kind:"not_found",refresh:j,streamActive:g}:a!==null?{kind:"failed",error:a,refresh:j,streamActive:g}:{kind:"loading",warming:o,refresh:j,streamActive:g}}async function Qe(e,t){if(!e)return{kind:"unrequested"};try{return{kind:"loaded",detail:await Ve(e,t)}}catch(s){if(s instanceof D&&s.status===422&&s.reason==="not_run_view")return{kind:"unsupported"};if(s instanceof D&&s.status===404)return{kind:"not_found"};throw s}}async function et(){}function tt(e,t){return t!==null?{kind:"failed",error:t}:e?{kind:"refreshing"}:{kind:"idle"}}function nt(e,t,s){Z({component:"formula-run-detail",operation:e,message:`${t}: ${H(s)}`})}function te(e,t,s){return["formula-run",e??"missing",t??"default",s??"default"].map(encodeURIComponent).join(":")}const st=[G.bead,G.session],rt=[];function Rt(){const{runId:e}=ce(),[t]=ue(),s=xt(t),r=s.ok?s.scope:void 0,o=s.ok?null:s.error,i=t.get("node"),u=[e??"",r?.scopeKind??"",r?.scopeRef??"",i??""].join("\0"),l=Je(o?void 0:e,r?.scopeKind,r?.scopeRef),d=l.kind==="ready"?l:null,a=d?.detail??null,c=l.kind==="unsupported",m=l.kind==="not_found",x=l.kind==="loading",b=d!==null&&d.refreshState.kind==="refreshing",y=x||b,L=l.kind==="failed"?l.error:d!==null&&d.refreshState.kind==="failed"?d.refreshState.error:null,M=l.streamActive;de(o?rt:st,()=>{at(M,l.refresh)},{matches:S=>{const R=Oe(S);return a===null?e!==void 0&&(R.runIds.size===0||R.runIds.has(e)):a.progress.terminal&&ot(R)?!1:Ke(R,{runId:a.runId,rootBeadId:a.rootBeadId})}});const g=o??L,j=l.kind==="loading"&&l.warming?.reason==="unknown_run",{selectedNodeId:C,selectedNode:w,toggleNode:N}=ze(a,i,u),F=be(a?.rootBeadId??null),[$,P]=f.useState(null),ne=fe(),se=xe(),[B]=f.useState(()=>me(`runs:summary:${se??"no-city"}`)),T=f.useMemo(()=>{if(!e)return null;const S=B&&B.status!=="error"?B.data:null;return S==null?null:[...S.lanes,...S.blockedLanes].find(R=>R.id===e)??null},[B,e]),re=a?`${a.progress.visibleNodeCount} nodes. ${ht(a.progress)}.`:x&&!o||c||m?void 0:"Formula run unavailable.";return n.jsxs("section",{children:[n.jsx(he,{title:a?.title??"Formula Run",synopsis:re,meta:n.jsxs(n.Fragment,{children:[n.jsx(pe,{to:"/runs",className:"focus-mark text-label uppercase tracking-wider text-fg-muted hover:text-fg",children:"Runs"}),g&&a&&n.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:g}),a&&n.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:ct(a)}),n.jsx(ge,{size:"sm",onClick:()=>{l.refresh()},disabled:y||!!o,children:b?"Refreshing":"Refresh"})]})}),y&&!o&&!a?T?n.jsxs(n.Fragment,{children:[n.jsx(U,{stages:T.stages,label:T.title}),n.jsx("p",{className:"text-body text-fg-muted italic mt-8",children:"Loading run detail."})]}):j?n.jsx("p",{className:"text-body text-fg-muted italic",role:"status",children:"This run may still be being recorded — new work can take a couple of minutes to appear — or it may no longer exist."}):n.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading formula run."}):c?n.jsx("p",{className:"text-body text-fg-muted",role:"status",children:"Detailed step view isn’t available for this run (v1/wisp runs are list-only) — this run appears in the run list only."}):m?n.jsx("p",{className:"text-body text-fg-muted",role:"status",children:"This run’s detail snapshot was not found. It may be a v1/wisp run, a completed run whose snapshot wasn’t retained, or no longer available."}):g&&!a?n.jsx("p",{className:"text-body text-accent",role:"alert",children:g}):d?n.jsxs(n.Fragment,{children:[n.jsx(it,{detail:d.detail}),n.jsx(U,{stages:d.detail.stages,label:d.detail.title}),n.jsx(dt,{detail:d.detail}),n.jsxs("div",{className:"mt-8 grid gap-10 lg:grid-cols-[minmax(0,0.95fr)_minmax(22rem,1.05fr)]",children:[n.jsx(Le,{detail:d.detail,selectedNodeId:C,onToggleNode:N}),n.jsx(Te,{selectedNode:w})]}),n.jsx(ke,{view:F.view,loading:F.loading,error:F.error,now:ne,onOpenBead:P}),n.jsx(ye,{open:$!==null,onClose:()=>P(null),beadId:$,onOpenBead:P})]}):null]})}function at(e,t){return e?Promise.resolve():t()}function ot(e){return e.runIds.size===0&&e.rootBeadIds.size===0}function it({detail:e}){const t=ut(e.formulaDetail);return n.jsxs("dl",{className:"grid gap-x-8 gap-y-3 sm:grid-cols-2 lg:grid-cols-4",children:[n.jsx(lt,{formula:e.formula}),t!==null&&n.jsx(I,{label:"Formula Detail",value:t}),n.jsx(I,{label:"Root",value:e.rootBeadId}),n.jsx(I,{label:"Scope",value:`${e.scopeKind}:${e.scopeRef}`}),n.jsx(I,{label:"Store",value:e.resolvedRootStore||e.rootStoreRef||"unknown"})]})}function I({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{className:"text-label uppercase tracking-wider text-fg-faint",children:e}),n.jsx("dd",{className:"text-body text-fg break-all tnum",children:t})]})}const Y="name inferred from bead title — supervisor did not set gc.formula on this graph.v2 root";function lt({formula:e}){if(e.kind!=="known")return n.jsx(I,{label:"Formula",value:"metadata missing"});switch(e.source){case"metadata":return n.jsx(I,{label:"Formula",value:e.name});case"title_fallback":return n.jsxs("div",{children:[n.jsx("dt",{className:"text-label uppercase tracking-wider text-fg-faint",children:"Formula"}),n.jsxs("dd",{className:"text-body text-warn break-all tnum",title:Y,"aria-label":`${e.name} (${Y})`,children:[e.name,n.jsx("span",{className:"ml-2 text-label uppercase tracking-wider text-warn",children:"inferred from bead title"})]})]});default:return e.source}}function ct(e){return e.snapshotEventSeq.kind==="known"?`v${e.snapshotVersion} · seq ${e.snapshotEventSeq.seq}`:`v${e.snapshotVersion}`}function ut(e){return e.kind==="available"?`available for ${e.target}`:e.reason==="missing_formula_metadata"?null:e.reason==="missing_run_target"?`missing run target for ${e.name}`:`${e.failure} for ${e.target}`}function dt({detail:e}){if(e.completeness.kind!=="partial")return null;const t=ft(e.completeness.reasons);return t.length===0?null:n.jsxs("p",{className:"mt-5 text-label uppercase tracking-wider text-warn",role:"status",children:["Partial run data: ",pt(t),"."]})}function ft(e){return e.filter(t=>!mt(t))}function mt(e){switch(e){case"formula_detail_missing_formula_metadata":case"formula_detail_missing_run_target":case"formula_detail_fetch_failed":return!0;case"supervisor_snapshot_partial":case"runtime_bead_read_failed":case"session_list_failed":return!1}}function pt(e){return e.map(gt).join(", ")}function gt(e){switch(e){case"supervisor_snapshot_partial":return"supervisor snapshot is partial";case"runtime_bead_read_failed":return"runtime bead refresh failed";case"session_list_failed":return"session list failed";case"formula_detail_missing_formula_metadata":return"formula metadata is missing";case"formula_detail_missing_run_target":return"formula run target is missing";case"formula_detail_fetch_failed":return"formula detail fetch failed"}}function xt(e){const t=e.getAll("scope_kind"),s=e.getAll("scope_ref");if(t.length>1||s.length>1)return{ok:!1,error:"Invalid run scope query."};const r=t[0],o=s[0];return r===void 0&&o===void 0?{ok:!0}:r===void 0||o===void 0?{ok:!1,error:"Invalid run scope query."}:r!=="city"&&r!=="rig"?{ok:!1,error:"Invalid run scope query."}:we.test(o)?{ok:!0,scope:{scopeKind:r,scopeRef:o}}:{ok:!1,error:"Invalid run scope query."}}function ht(e){const t=[_(e,["active","running"],"running"),_(e,["completed","done"],"done"),_(e,"ready","ready"),_(e,"blocked","blocked"),_(e,"failed","failed"),_(e,"skipped","skipped"),_(e,"pending","pending")].filter(s=>s!==null);return t.length>0?t.join(", "):"No node status yet"}function _(e,t,s){const o=(typeof t=="string"?[t]:t).reduce((i,u)=>i+(e.statusCounts[u]??0),0);return o>0?`${o} ${s}`:null}export{Rt as FormulaRunDetailPage,at as runDetailNudgeRefresh}; diff --git a/internal/api/dashboardspa/dist/assets/Health-TkHQ7rEN.js b/internal/api/dashboardspa/dist/assets/Health-5RAwdGI6.js similarity index 98% rename from internal/api/dashboardspa/dist/assets/Health-TkHQ7rEN.js rename to internal/api/dashboardspa/dist/assets/Health-5RAwdGI6.js index 7d98717347..993e397f64 100644 --- a/internal/api/dashboardspa/dist/assets/Health-TkHQ7rEN.js +++ b/internal/api/dashboardspa/dist/assets/Health-5RAwdGI6.js @@ -1 +1 @@ -import{a as ie,b as p,r as ue,j as t,B as ce,a3 as N,K as X,S as G,Q as J,ah as de}from"./index-DDS7Ehww.js";import{p as C,d as he}from"./routeHighlight-B30gQO2o.js";import{P as me}from"./PageHeader-nOBkk_AA.js";import{u as xe}from"./useVisibleRefresh-C8_1beQq.js";import{a as f}from"./format-fte2CeYD.js";import{b as be}from"./time-BVuL_AnL.js";const ve=2500,m="n/a";function at(){const e=ie(),a=J(),s=p("health:system",Le),r=p(`health:supervisor:${a??"no-city"}`,Me),i=p(`health:status:${a??"no-city"}`,Te),c=p("health:local-tools",De),o=p(`health:dolt-noms-trend:${a??"no-city"}`,Ae),d=p(`health:rig-store:${a??"no-city"}`,Fe),x=s.refresh,S=r.refresh,k=i.refresh,$=c.refresh,U=o.refresh,B=d.refresh,ae=s.loading||r.loading||i.loading||c.loading||o.loading||d.loading,V=[s.error,r.error,i.error,c.error,o.error,d.error].filter(oe=>oe!==null).join("; ")||null,E=ue.useCallback(async()=>{await Promise.all([x(),S(),k(),$(),U(),B()])},[U,$,B,S,k,x]),v=s.data??null,n=v?.status==="available"?v.data:null,R=v?.status==="unavailable"?v.error:null,u=r.data??null,H=i.data??null,I=c.data??null,h=o.data??null,g=d.data??null,O=g?ke(g):void 0,A=v!==null||u!==null||H!==null||I!==null||h!==null||g!==null,z=n===null?null:D(n),K=n?Be(n):void 0,se=C(e,"health",["health:supervisor-"]),le=C(e,"health",["health:load-","health:memory-"]),ne=C(e,"health",["health:dashboard-"]),re=C(e,"health",["health:dolt-noms-"]);return xe(E,3e4),t.jsxs("section",{children:[t.jsx(me,{title:"Health",synopsis:A?Pe(n,u):"Reading state from the supervisor.",meta:t.jsxs(t.Fragment,{children:[V&&t.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:V}),t.jsx(ce,{size:"sm",onClick:()=>{E()},children:ae&&!A?"Loading":"Refresh"})]})}),A?t.jsxs("div",{className:"space-y-12",children:[t.jsx(b,{title:"Supervisor",attention:se,...u?{status:Ue(u)}:{},children:u===null?t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading supervisor state."}):u.status==="available"?t.jsxs(j,{children:[u.data.city!==void 0?t.jsx(l,{label:"City",value:u.data.city}):t.jsx(l,{label:"City",value:"not reported by supervisor",tone:"warn"}),u.data.version!==void 0?t.jsx(l,{label:"Version",value:u.data.version}):t.jsx(l,{label:"Version",value:"not reported by supervisor",tone:"warn"}),t.jsx(l,{label:"Uptime",value:_(u.data.uptime_sec)}),t.jsx(l,{label:"Status",value:u.data.status})]}):t.jsx("p",{className:"text-body text-accent",children:"Supervisor not reachable. The dashboard shell stays up; live data is stale."})}),t.jsx(b,{title:"Host",attention:le,...K?{status:K}:{},children:v===null?t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading dashboard host health."}):n===null?t.jsxs("p",{className:"text-body text-accent",children:["Dashboard host health unavailable",R?`: ${R}`:"","."]}):t.jsxs(j,{children:[t.jsx(l,{label:"CPUs",value:q(n.host.cpu_count),...L(n.host.cpu_count)?{}:{tone:"warn"}}),t.jsx(l,{label:"Load (1m, 5m, 15m)",value:Ee(n),...!T(n)||P(n)>n.host.cpu_count?{tone:"warn"}:{}}),t.jsx(l,{label:"Memory free",value:Ve(n),...z===null||z<.1?{tone:"warn"}:{}}),t.jsx(l,{label:"Host uptime",value:Oe(n.host.uptime),...M(n.host.uptime)?{}:{tone:"warn"}})]})}),t.jsx(b,{title:"Admin process",attention:ne,children:v===null?t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading dashboard process health."}):n===null?t.jsxs("p",{className:"text-body text-accent",children:["Dashboard process health unavailable",R?`: ${R}`:"","."]}):t.jsxs(j,{children:[t.jsx(l,{label:"PID",value:q(n.admin.pid),...L(n.admin.pid)?{}:{tone:"warn"}}),t.jsx(l,{label:"Uptime",value:Ke(n.admin.uptime_sec),...w(n.admin.uptime_sec)?{}:{tone:"warn"}}),t.jsx(l,{label:"RSS",value:ze(n.admin.rss),...M(n.admin.rss)?{}:{tone:"warn"}}),t.jsx(l,{label:"Heap used",value:Qe(n.admin.heap_used_bytes),...w(n.admin.heap_used_bytes)?{}:{tone:"warn"}}),t.jsx(l,{label:"Node",value:n.admin.node_version})]})}),t.jsx(b,{title:"Tool versions",children:t.jsx(fe,{state:I})}),t.jsx(b,{title:"Diagnostics",children:t.jsxs("div",{className:"space-y-8",children:[t.jsx(ge,{usage:te(H)}),t.jsx(je,{usage:We(H)})]})}),t.jsx(b,{title:"Bead stores · per rig",meta:Se(g),...O?{status:O}:{},children:t.jsx(ye,{report:g})}),t.jsx(b,{title:"Store thresholds",children:t.jsx($e,{comparison:qe(H)})}),t.jsx(b,{title:"Dolt-noms · 24 h",attention:re,meta:h&&h.samples.length>0?`${h.samples.length} samples`:void 0,children:h===null?t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading."}):h.available?h.samples.length===0?t.jsx("p",{className:"text-body text-fg-muted italic",children:"No samples yet. Backend just started; next sample in ten minutes or less."}):t.jsx(He,{samples:h.samples}):t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Dolt-noms metric unavailable: ",Ce(h.reason),"."]})})]}):t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading."})]})}function b({title:e,status:a,meta:s,attention:r,children:i}){return t.jsxs("section",{...he(r??null),children:[t.jsxs("header",{className:"flex items-baseline justify-between gap-4 mb-4 pb-2 border-b border-rule",children:[t.jsx("h2",{className:"text-headline font-semibold text-fg",children:e}),t.jsxs("div",{className:"flex items-baseline gap-4",children:[s&&t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:s}),a&&t.jsx(G,{tone:a.tone,label:a.label})]})]}),i]})}function j({children:e}){return t.jsx("dl",{className:"grid grid-cols-[max-content_1fr] gap-x-8 gap-y-3 max-w-prose",children:e})}function l({label:e,value:a,tone:s}){const r=s==="warn"?"text-warn":s==="stuck"?"text-accent":"text-fg";return t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-body text-fg-muted",children:e}),t.jsx("dd",{className:`text-body tnum font-medium ${r}`,children:a})]})}function fe({state:e}){if(e===null)return t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading tool versions."});if(e.status==="unavailable")return t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Tool versions unavailable: ",e.error,"."]});const a=[{label:"gc",tool:e.data.gc},{label:"bd",tool:e.data.beads},{label:"dolt",tool:e.data.dolt}];return t.jsxs("div",{className:"grid grid-cols-[1fr_max-content] gap-x-8 gap-y-3 max-w-prose",children:[t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Tool"}),t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted text-right",children:"Installed"}),a.map(s=>t.jsx(pe,{label:s.label,tool:s.tool},s.label))]})}function pe({label:e,tool:a}){return t.jsxs("div",{className:"contents","data-tool-version-row":e,children:[t.jsx("div",{className:"text-body text-fg",children:e}),t.jsx("div",{className:"text-right",children:a.status==="available"?t.jsx("span",{className:"text-body tnum font-medium text-fg",children:a.version}):t.jsxs("div",{className:"space-y-1",children:[t.jsx("div",{className:"text-body tnum font-medium text-warn",children:"unavailable"}),t.jsx("div",{className:"text-label text-fg-muted normal-case",children:a.reason})]})})]})}function ge({usage:e}){if(e.status==="unavailable")return t.jsx(Y,{heading:"Dolt usage",reason:e.reason});const a=e.value;return t.jsxs("div",{className:"space-y-2",children:[t.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Dolt usage"}),e.stale!==void 0&&t.jsx(F,{message:e.stale}),t.jsxs(j,{children:[t.jsx(l,{label:"On-disk size",value:f(Xe(a.size_bytes))}),t.jsx(l,{label:"Live rows",value:a.live_rows.toLocaleString()}),t.jsx(l,{label:"MB per row",value:a.ratio_mb_per_row.toString()}),t.jsx(l,{label:"Last maintenance",value:a.last_gc_status??"not reported",...a.last_gc_status!==void 0&&a.last_gc_status!=="success"?{tone:"warn"}:{}}),a.last_gc_at!==void 0&&t.jsx(l,{label:"Last maintenance at",value:be(a.last_gc_at)}),t.jsx(l,{label:"Store path",value:a.path})]})]})}function je({usage:e}){if(e.status==="unavailable")return t.jsx(Y,{heading:"Beads usage",reason:e.reason});const a=e.value;return t.jsxs("div",{className:"space-y-2",children:[t.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Beads usage"}),e.stale!==void 0&&t.jsx(F,{message:e.stale}),t.jsxs(j,{children:[t.jsx(l,{label:"Open",value:a.open.toString()}),t.jsx(l,{label:"Ready",value:a.ready.toString()}),t.jsx(l,{label:"In progress",value:a.in_progress.toString()})]})]})}function ye({report:e}){if(e===null)return t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading per-rig store health."});if(!e.available&&e.rigs.length===0)return t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Per-rig store health unavailable: ",W(e.reason),"."]});const a=[...e.rigs].sort((s,r)=>Q(r.rollup)-Q(s.rollup));return t.jsxs("div",{className:"space-y-6 max-w-prose",children:[!e.available&&t.jsxs("p",{className:"text-body text-warn italic",children:["Showing the last sample; refresh failed: ",W(e.reason),"."]}),a.map(s=>t.jsx(we,{rig:s},s.rig))]})}function we({rig:e}){const a=Ne(e);return t.jsxs("div",{className:"space-y-2 border-b border-rule pb-4 last:border-b-0",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[t.jsx("span",{className:"text-body font-medium text-fg",children:e.rig}),t.jsx(G,{tone:a.tone,label:a.label})]}),t.jsxs("dl",{className:"grid grid-cols-[max-content_1fr] gap-x-6 gap-y-1",children:[t.jsx(l,{label:"Dolt server",value:_e(e),...e.doltConnected===!1?{tone:"stuck"}:{}}),e.issueCount!==null&&t.jsx(l,{label:"Live issues",value:e.issueCount.toLocaleString()})]}),e.problems.length>0&&t.jsx("ul",{className:"space-y-1",children:e.problems.map(s=>t.jsxs("li",{className:`text-label ${s.status==="error"?"text-accent":"text-warn"}`,children:[s.name,": ",s.message]},`${s.category}/${s.name}`))}),e.note!==void 0&&t.jsx("p",{className:"text-label text-fg-muted italic",children:e.note})]})}function _e(e){const a=e.doltEndpoint??"no endpoint reported";return e.doltConnected===!0?`up · ${a}`:e.doltConnected===!1?`DOWN · ${a}`:`unknown · ${a}`}function Ne(e){switch(e.rollup){case"ok":return{tone:"ok",label:"healthy"};case"warn":return{tone:"warn",label:"warnings"};case"down":return e.reachable?e.doltConnected===!1?{tone:"stuck",label:"dolt down"}:{tone:"stuck",label:"errors"}:{tone:"stuck",label:"unreachable"}}}function Q(e){return e==="down"?2:e==="warn"?1:0}function Se(e){if(e===null||e.rigs.length===0)return;const a={ok:0,warn:0,down:0};for(const s of e.rigs)a[s.rollup]+=1;return`${a.ok} ok · ${a.warn} warn · ${a.down} down`}function ke(e){if(e.rigs.some(a=>a.rollup==="down"))return{tone:"stuck",label:"attention"};if(e.rigs.some(a=>a.rollup==="warn"))return{tone:"warn",label:"warnings"};if(e.rigs.length>0)return{tone:"ok",label:"healthy"}}function W(e){switch(e){case"not_sampled_yet":return"backend just started; first sample is in flight";case"rig_list_failed":return"the supervisor rig list could not be read";case"fetch_failed":return"the dashboard backend could not be reached"}}function $e({comparison:e}){return e.status==="unavailable"?t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Comparison unavailable: ",e.reason,"."]}):t.jsxs("div",{className:"space-y-2",children:[e.stale!==void 0&&t.jsx(F,{message:e.stale}),t.jsxs("div",{className:"grid grid-cols-[1fr_max-content_max-content] gap-x-8 gap-y-3 max-w-prose",children:[t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Setting"}),t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted text-right",children:"Recommended"}),t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted text-right",children:"Loaded"}),e.value.map(a=>t.jsx(Re,{row:a},a.label))]})]})}function Re({row:e}){const a=e.withinRecommendation?"text-fg":"text-warn";return t.jsxs("div",{className:`contents ${a}`,"data-comparison-row":e.label,children:[t.jsxs("div",{className:`text-body ${a}`,children:[e.label,!e.withinRecommendation&&t.jsx("span",{className:"text-label uppercase tracking-wider text-warn",children:" · over"})]}),t.jsx("div",{className:"text-body tnum text-fg-muted text-right",children:e.recommended}),t.jsx("div",{className:`text-body tnum font-medium text-right ${a}`,children:e.loaded})]})}function Y({heading:e,reason:a}){return t.jsxs("div",{className:"space-y-2",children:[t.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-muted",children:e}),t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Unavailable: ",a,"."]})]})}function F({message:e}){return t.jsx("p",{className:"text-body text-warn italic",children:e})}function He({samples:e}){if(e.length===0)return null;const a=Math.max(...e.map(x=>x.bytes)),s=Math.min(...e.map(x=>x.bytes)),r=a-s||1,i=600,c=60,o=e.length>1?i/(e.length-1):i,d=e.map((x,S)=>{const k=S*o,$=c-(x.bytes-s)/r*c;return`${k.toFixed(1)},${$.toFixed(1)}`}).join(" ");return t.jsxs("div",{className:"space-y-3 max-w-prose",children:[t.jsx("svg",{viewBox:`0 0 ${i} ${c}`,preserveAspectRatio:"none",className:"w-full h-16","aria-label":"24 hour dolt-noms size trend",children:t.jsx("polyline",{fill:"none",stroke:"currentColor",strokeWidth:"1",className:"text-accent",points:d})}),t.jsxs("div",{className:"flex items-baseline justify-between text-label uppercase tracking-wider text-fg-muted tnum",children:[t.jsxs("span",{children:["min ",f(s)]}),t.jsxs("span",{children:["max ",f(a)]})]})]})}function Ce(e){switch(e){case"store_health_absent":return"supervisor is not reporting store_health; samples resume when it recovers";case"sample_failed":return"latest supervisor status read failed; check the backend log"}}async function Le(){try{return{status:"available",data:await N.systemHealth()}}catch(e){return{status:"unavailable",error:X(e,"dashboard host health unavailable")}}}async function Me(){const e=J();if(e===null)throw new Error("Health page loaded before an active city was resolved");try{return{status:"available",data:await de(ve).cityHealth(e)}}catch{return{status:"unavailable",error:"supervisor health unavailable"}}}function Z(e){switch(e){case"not_sampled_yet":return"supervisor status sample is warming up; data appears after the next backend sample";case"status_read_failed":return"latest supervisor status read failed; check the backend log"}}function ee(e){return`Showing the last sample; refresh failed: ${Z(e)}.`}async function Te(){try{const e=await N.supervisorStatus();return e.available?{status:"available",data:e.status,staleReason:null}:e.status!==null?{status:"available",data:e.status,staleReason:e.reason}:{status:"unavailable",error:Z(e.reason)}}catch(e){return{status:"unavailable",error:X(e,"supervisor status unavailable")}}}async function De(){try{return{status:"available",data:await N.localToolVersions()}}catch{return{status:"unavailable",error:"local tool versions unavailable"}}}async function Ae(){try{return await N.doltTrend()}catch{return{available:!1,reason:"sample_failed",samples:[]}}}async function Fe(){try{return await N.rigStoreHealth()}catch{return{available:!1,reason:"fetch_failed",rigs:[]}}}function Pe(e,a){const s=[];if(a===null)s.push("Supervisor state still loading.");else if(a.status==="available"){const o=a.data,d=o.status==="ok"?"healthy":o.status;o.city!==void 0?s.push(`Supervisor ${d} on ${o.city}, uptime ${_(o.uptime_sec)}.`):s.push(`Supervisor ${d}, uptime ${_(o.uptime_sec)}.`)}else s.push("Supervisor unreachable.");if(e===null)return s.push("Host health unavailable."),s.join(" ");const r=D(e),i=r===null?"Memory unavailable":`Memory at ${Math.round(100*(1-r))}%`,c=T(e)?`${e.host.cpu_count} CPUs averaging ${P(e).toFixed(2)} load`:"CPU/load unavailable";return s.push(`${i}; ${c}.`),s.join(" ")}function Ue(e){return e.status==="unavailable"?{tone:"stuck",label:"offline"}:e.data.status==="ok"?{tone:"ok",label:"healthy"}:{tone:"warn",label:e.data.status}}function Be(e){const a=D(e);if(a===null||!T(e)||!Ie(e.host.uptime))return{tone:"warn",label:"telemetry unavailable"};if(a<.05)return{tone:"stuck",label:"memory critical"};if(a<.1)return{tone:"warn",label:"memory low"};if(P(e)>e.host.cpu_count*1.5)return{tone:"warn",label:"load high"}}function T(e){if(e.host.load.status!=="available")return!1;const a=e.host.load.value;return L(e.host.cpu_count)&&y(a.load_avg_1)&&y(a.load_avg_5)&&y(a.load_avg_15)}function D(e){if(e.host.memory.status!=="available")return null;const a=e.host.memory.value.free_mem_bytes,s=e.host.memory.value.total_mem_bytes;return!Number.isFinite(a)||!Number.isFinite(s)||a<0||s<=0||a>s?null:a/s}function Ve(e){return D(e)===null||e.host.memory.status!=="available"?m:`${f(e.host.memory.value.free_mem_bytes)} of ${f(e.host.memory.value.total_mem_bytes)}`}function w(e){return Number.isFinite(e)&&e>0}function y(e){return Number.isFinite(e)&&e>=0}function L(e){return Number.isInteger(e)&&e>0}function q(e){return L(e)?e.toString():m}function Ee(e){if(!T(e)||e.host.load.status!=="available")return m;const a=e.host.load.value;return`${a.load_avg_1.toFixed(2)}, ${a.load_avg_5.toFixed(2)}, ${a.load_avg_15.toFixed(2)}`}function P(e){return e.host.load.status==="available"&&y(e.host.load.value.load_avg_1)?e.host.load.value.load_avg_1:0}function M(e){return e.status==="available"&&w(e.value)}function Ie(e){return e.status==="available"&&y(e.value)}function Oe(e){return M(e)&&e.status==="available"?_(e.value):m}function ze(e){return M(e)&&e.status==="available"?f(e.value):m}function Ke(e){return w(e)?_(e):m}function Qe(e){return w(e)?f(e):m}function te(e){if(e===null)return{status:"unavailable",reason:"supervisor status still loading"};if(e.status==="unavailable")return{status:"unavailable",reason:e.error};const a=e.data.store_health;return a===void 0?{status:"unavailable",reason:"supervisor did not report store_health"}:{status:"available",value:a,source:"supervisor status.store_health",...e.staleReason!==null?{stale:ee(e.staleReason)}:{}}}function We(e){return e===null?{status:"unavailable",reason:"supervisor status still loading"}:e.status==="unavailable"?{status:"unavailable",reason:e.error}:{status:"available",value:e.data.work,source:"supervisor status.work",...e.staleReason!==null?{stale:ee(e.staleReason)}:{}}}function qe(e){const a=te(e);if(a.status==="unavailable")return{status:"unavailable",reason:a.reason};const s=a.value;return{status:"available",source:"supervisor status.store_health (threshold vs actual)",...a.stale!==void 0?{stale:a.stale}:{},value:[{label:"Dolt MB-per-row ratio",recommended:`<= ${s.threshold_mb_per_row}`,loaded:String(s.ratio_mb_per_row),withinRecommendation:!s.warning}]}}function Xe(e){return typeof e=="bigint"?Number(e):e}function _(e){if(e<60)return`${e}s`;if(e<3600)return`${Math.round(e/60)}m`;if(e<86400)return`${Math.round(e/3600)}h`;const a=Math.floor(e/86400),s=Math.round(e%86400/3600);return s>0?`${a}d ${s}h`:`${a}d`}export{at as HealthPage}; +import{a as ie,b as p,r as ue,j as t,B as ce,a3 as N,K as X,S as G,Q as J,ah as de}from"./index-BDHAaQRP.js";import{p as C,d as he}from"./routeHighlight-B30gQO2o.js";import{P as me}from"./PageHeader-BW5bf722.js";import{u as xe}from"./useVisibleRefresh-B7rFi4L5.js";import{a as f}from"./format-fte2CeYD.js";import{b as be}from"./time-BVuL_AnL.js";const ve=2500,m="n/a";function at(){const e=ie(),a=J(),s=p("health:system",Le),r=p(`health:supervisor:${a??"no-city"}`,Me),i=p(`health:status:${a??"no-city"}`,Te),c=p("health:local-tools",De),o=p(`health:dolt-noms-trend:${a??"no-city"}`,Ae),d=p(`health:rig-store:${a??"no-city"}`,Fe),x=s.refresh,S=r.refresh,k=i.refresh,$=c.refresh,U=o.refresh,B=d.refresh,ae=s.loading||r.loading||i.loading||c.loading||o.loading||d.loading,V=[s.error,r.error,i.error,c.error,o.error,d.error].filter(oe=>oe!==null).join("; ")||null,E=ue.useCallback(async()=>{await Promise.all([x(),S(),k(),$(),U(),B()])},[U,$,B,S,k,x]),v=s.data??null,n=v?.status==="available"?v.data:null,R=v?.status==="unavailable"?v.error:null,u=r.data??null,H=i.data??null,I=c.data??null,h=o.data??null,g=d.data??null,O=g?ke(g):void 0,A=v!==null||u!==null||H!==null||I!==null||h!==null||g!==null,z=n===null?null:D(n),K=n?Be(n):void 0,se=C(e,"health",["health:supervisor-"]),le=C(e,"health",["health:load-","health:memory-"]),ne=C(e,"health",["health:dashboard-"]),re=C(e,"health",["health:dolt-noms-"]);return xe(E,3e4),t.jsxs("section",{children:[t.jsx(me,{title:"Health",synopsis:A?Pe(n,u):"Reading state from the supervisor.",meta:t.jsxs(t.Fragment,{children:[V&&t.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:V}),t.jsx(ce,{size:"sm",onClick:()=>{E()},children:ae&&!A?"Loading":"Refresh"})]})}),A?t.jsxs("div",{className:"space-y-12",children:[t.jsx(b,{title:"Supervisor",attention:se,...u?{status:Ue(u)}:{},children:u===null?t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading supervisor state."}):u.status==="available"?t.jsxs(j,{children:[u.data.city!==void 0?t.jsx(l,{label:"City",value:u.data.city}):t.jsx(l,{label:"City",value:"not reported by supervisor",tone:"warn"}),u.data.version!==void 0?t.jsx(l,{label:"Version",value:u.data.version}):t.jsx(l,{label:"Version",value:"not reported by supervisor",tone:"warn"}),t.jsx(l,{label:"Uptime",value:_(u.data.uptime_sec)}),t.jsx(l,{label:"Status",value:u.data.status})]}):t.jsx("p",{className:"text-body text-accent",children:"Supervisor not reachable. The dashboard shell stays up; live data is stale."})}),t.jsx(b,{title:"Host",attention:le,...K?{status:K}:{},children:v===null?t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading dashboard host health."}):n===null?t.jsxs("p",{className:"text-body text-accent",children:["Dashboard host health unavailable",R?`: ${R}`:"","."]}):t.jsxs(j,{children:[t.jsx(l,{label:"CPUs",value:q(n.host.cpu_count),...L(n.host.cpu_count)?{}:{tone:"warn"}}),t.jsx(l,{label:"Load (1m, 5m, 15m)",value:Ee(n),...!T(n)||P(n)>n.host.cpu_count?{tone:"warn"}:{}}),t.jsx(l,{label:"Memory free",value:Ve(n),...z===null||z<.1?{tone:"warn"}:{}}),t.jsx(l,{label:"Host uptime",value:Oe(n.host.uptime),...M(n.host.uptime)?{}:{tone:"warn"}})]})}),t.jsx(b,{title:"Admin process",attention:ne,children:v===null?t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading dashboard process health."}):n===null?t.jsxs("p",{className:"text-body text-accent",children:["Dashboard process health unavailable",R?`: ${R}`:"","."]}):t.jsxs(j,{children:[t.jsx(l,{label:"PID",value:q(n.admin.pid),...L(n.admin.pid)?{}:{tone:"warn"}}),t.jsx(l,{label:"Uptime",value:Ke(n.admin.uptime_sec),...w(n.admin.uptime_sec)?{}:{tone:"warn"}}),t.jsx(l,{label:"RSS",value:ze(n.admin.rss),...M(n.admin.rss)?{}:{tone:"warn"}}),t.jsx(l,{label:"Heap used",value:Qe(n.admin.heap_used_bytes),...w(n.admin.heap_used_bytes)?{}:{tone:"warn"}}),t.jsx(l,{label:"Node",value:n.admin.node_version})]})}),t.jsx(b,{title:"Tool versions",children:t.jsx(fe,{state:I})}),t.jsx(b,{title:"Diagnostics",children:t.jsxs("div",{className:"space-y-8",children:[t.jsx(ge,{usage:te(H)}),t.jsx(je,{usage:We(H)})]})}),t.jsx(b,{title:"Bead stores · per rig",meta:Se(g),...O?{status:O}:{},children:t.jsx(ye,{report:g})}),t.jsx(b,{title:"Store thresholds",children:t.jsx($e,{comparison:qe(H)})}),t.jsx(b,{title:"Dolt-noms · 24 h",attention:re,meta:h&&h.samples.length>0?`${h.samples.length} samples`:void 0,children:h===null?t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading."}):h.available?h.samples.length===0?t.jsx("p",{className:"text-body text-fg-muted italic",children:"No samples yet. Backend just started; next sample in ten minutes or less."}):t.jsx(He,{samples:h.samples}):t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Dolt-noms metric unavailable: ",Ce(h.reason),"."]})})]}):t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading."})]})}function b({title:e,status:a,meta:s,attention:r,children:i}){return t.jsxs("section",{...he(r??null),children:[t.jsxs("header",{className:"flex items-baseline justify-between gap-4 mb-4 pb-2 border-b border-rule",children:[t.jsx("h2",{className:"text-headline font-semibold text-fg",children:e}),t.jsxs("div",{className:"flex items-baseline gap-4",children:[s&&t.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:s}),a&&t.jsx(G,{tone:a.tone,label:a.label})]})]}),i]})}function j({children:e}){return t.jsx("dl",{className:"grid grid-cols-[max-content_1fr] gap-x-8 gap-y-3 max-w-prose",children:e})}function l({label:e,value:a,tone:s}){const r=s==="warn"?"text-warn":s==="stuck"?"text-accent":"text-fg";return t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-body text-fg-muted",children:e}),t.jsx("dd",{className:`text-body tnum font-medium ${r}`,children:a})]})}function fe({state:e}){if(e===null)return t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading tool versions."});if(e.status==="unavailable")return t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Tool versions unavailable: ",e.error,"."]});const a=[{label:"gc",tool:e.data.gc},{label:"bd",tool:e.data.beads},{label:"dolt",tool:e.data.dolt}];return t.jsxs("div",{className:"grid grid-cols-[1fr_max-content] gap-x-8 gap-y-3 max-w-prose",children:[t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Tool"}),t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted text-right",children:"Installed"}),a.map(s=>t.jsx(pe,{label:s.label,tool:s.tool},s.label))]})}function pe({label:e,tool:a}){return t.jsxs("div",{className:"contents","data-tool-version-row":e,children:[t.jsx("div",{className:"text-body text-fg",children:e}),t.jsx("div",{className:"text-right",children:a.status==="available"?t.jsx("span",{className:"text-body tnum font-medium text-fg",children:a.version}):t.jsxs("div",{className:"space-y-1",children:[t.jsx("div",{className:"text-body tnum font-medium text-warn",children:"unavailable"}),t.jsx("div",{className:"text-label text-fg-muted normal-case",children:a.reason})]})})]})}function ge({usage:e}){if(e.status==="unavailable")return t.jsx(Y,{heading:"Dolt usage",reason:e.reason});const a=e.value;return t.jsxs("div",{className:"space-y-2",children:[t.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Dolt usage"}),e.stale!==void 0&&t.jsx(F,{message:e.stale}),t.jsxs(j,{children:[t.jsx(l,{label:"On-disk size",value:f(Xe(a.size_bytes))}),t.jsx(l,{label:"Live rows",value:a.live_rows.toLocaleString()}),t.jsx(l,{label:"MB per row",value:a.ratio_mb_per_row.toString()}),t.jsx(l,{label:"Last maintenance",value:a.last_gc_status??"not reported",...a.last_gc_status!==void 0&&a.last_gc_status!=="success"?{tone:"warn"}:{}}),a.last_gc_at!==void 0&&t.jsx(l,{label:"Last maintenance at",value:be(a.last_gc_at)}),t.jsx(l,{label:"Store path",value:a.path})]})]})}function je({usage:e}){if(e.status==="unavailable")return t.jsx(Y,{heading:"Beads usage",reason:e.reason});const a=e.value;return t.jsxs("div",{className:"space-y-2",children:[t.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Beads usage"}),e.stale!==void 0&&t.jsx(F,{message:e.stale}),t.jsxs(j,{children:[t.jsx(l,{label:"Open",value:a.open.toString()}),t.jsx(l,{label:"Ready",value:a.ready.toString()}),t.jsx(l,{label:"In progress",value:a.in_progress.toString()})]})]})}function ye({report:e}){if(e===null)return t.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading per-rig store health."});if(!e.available&&e.rigs.length===0)return t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Per-rig store health unavailable: ",W(e.reason),"."]});const a=[...e.rigs].sort((s,r)=>Q(r.rollup)-Q(s.rollup));return t.jsxs("div",{className:"space-y-6 max-w-prose",children:[!e.available&&t.jsxs("p",{className:"text-body text-warn italic",children:["Showing the last sample; refresh failed: ",W(e.reason),"."]}),a.map(s=>t.jsx(we,{rig:s},s.rig))]})}function we({rig:e}){const a=Ne(e);return t.jsxs("div",{className:"space-y-2 border-b border-rule pb-4 last:border-b-0",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[t.jsx("span",{className:"text-body font-medium text-fg",children:e.rig}),t.jsx(G,{tone:a.tone,label:a.label})]}),t.jsxs("dl",{className:"grid grid-cols-[max-content_1fr] gap-x-6 gap-y-1",children:[t.jsx(l,{label:"Dolt server",value:_e(e),...e.doltConnected===!1?{tone:"stuck"}:{}}),e.issueCount!==null&&t.jsx(l,{label:"Live issues",value:e.issueCount.toLocaleString()})]}),e.problems.length>0&&t.jsx("ul",{className:"space-y-1",children:e.problems.map(s=>t.jsxs("li",{className:`text-label ${s.status==="error"?"text-accent":"text-warn"}`,children:[s.name,": ",s.message]},`${s.category}/${s.name}`))}),e.note!==void 0&&t.jsx("p",{className:"text-label text-fg-muted italic",children:e.note})]})}function _e(e){const a=e.doltEndpoint??"no endpoint reported";return e.doltConnected===!0?`up · ${a}`:e.doltConnected===!1?`DOWN · ${a}`:`unknown · ${a}`}function Ne(e){switch(e.rollup){case"ok":return{tone:"ok",label:"healthy"};case"warn":return{tone:"warn",label:"warnings"};case"down":return e.reachable?e.doltConnected===!1?{tone:"stuck",label:"dolt down"}:{tone:"stuck",label:"errors"}:{tone:"stuck",label:"unreachable"}}}function Q(e){return e==="down"?2:e==="warn"?1:0}function Se(e){if(e===null||e.rigs.length===0)return;const a={ok:0,warn:0,down:0};for(const s of e.rigs)a[s.rollup]+=1;return`${a.ok} ok · ${a.warn} warn · ${a.down} down`}function ke(e){if(e.rigs.some(a=>a.rollup==="down"))return{tone:"stuck",label:"attention"};if(e.rigs.some(a=>a.rollup==="warn"))return{tone:"warn",label:"warnings"};if(e.rigs.length>0)return{tone:"ok",label:"healthy"}}function W(e){switch(e){case"not_sampled_yet":return"backend just started; first sample is in flight";case"rig_list_failed":return"the supervisor rig list could not be read";case"fetch_failed":return"the dashboard backend could not be reached"}}function $e({comparison:e}){return e.status==="unavailable"?t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Comparison unavailable: ",e.reason,"."]}):t.jsxs("div",{className:"space-y-2",children:[e.stale!==void 0&&t.jsx(F,{message:e.stale}),t.jsxs("div",{className:"grid grid-cols-[1fr_max-content_max-content] gap-x-8 gap-y-3 max-w-prose",children:[t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Setting"}),t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted text-right",children:"Recommended"}),t.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted text-right",children:"Loaded"}),e.value.map(a=>t.jsx(Re,{row:a},a.label))]})]})}function Re({row:e}){const a=e.withinRecommendation?"text-fg":"text-warn";return t.jsxs("div",{className:`contents ${a}`,"data-comparison-row":e.label,children:[t.jsxs("div",{className:`text-body ${a}`,children:[e.label,!e.withinRecommendation&&t.jsx("span",{className:"text-label uppercase tracking-wider text-warn",children:" · over"})]}),t.jsx("div",{className:"text-body tnum text-fg-muted text-right",children:e.recommended}),t.jsx("div",{className:`text-body tnum font-medium text-right ${a}`,children:e.loaded})]})}function Y({heading:e,reason:a}){return t.jsxs("div",{className:"space-y-2",children:[t.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-muted",children:e}),t.jsxs("p",{className:"text-body text-fg-muted italic",children:["Unavailable: ",a,"."]})]})}function F({message:e}){return t.jsx("p",{className:"text-body text-warn italic",children:e})}function He({samples:e}){if(e.length===0)return null;const a=Math.max(...e.map(x=>x.bytes)),s=Math.min(...e.map(x=>x.bytes)),r=a-s||1,i=600,c=60,o=e.length>1?i/(e.length-1):i,d=e.map((x,S)=>{const k=S*o,$=c-(x.bytes-s)/r*c;return`${k.toFixed(1)},${$.toFixed(1)}`}).join(" ");return t.jsxs("div",{className:"space-y-3 max-w-prose",children:[t.jsx("svg",{viewBox:`0 0 ${i} ${c}`,preserveAspectRatio:"none",className:"w-full h-16","aria-label":"24 hour dolt-noms size trend",children:t.jsx("polyline",{fill:"none",stroke:"currentColor",strokeWidth:"1",className:"text-accent",points:d})}),t.jsxs("div",{className:"flex items-baseline justify-between text-label uppercase tracking-wider text-fg-muted tnum",children:[t.jsxs("span",{children:["min ",f(s)]}),t.jsxs("span",{children:["max ",f(a)]})]})]})}function Ce(e){switch(e){case"store_health_absent":return"supervisor is not reporting store_health; samples resume when it recovers";case"sample_failed":return"latest supervisor status read failed; check the backend log"}}async function Le(){try{return{status:"available",data:await N.systemHealth()}}catch(e){return{status:"unavailable",error:X(e,"dashboard host health unavailable")}}}async function Me(){const e=J();if(e===null)throw new Error("Health page loaded before an active city was resolved");try{return{status:"available",data:await de(ve).cityHealth(e)}}catch{return{status:"unavailable",error:"supervisor health unavailable"}}}function Z(e){switch(e){case"not_sampled_yet":return"supervisor status sample is warming up; data appears after the next backend sample";case"status_read_failed":return"latest supervisor status read failed; check the backend log"}}function ee(e){return`Showing the last sample; refresh failed: ${Z(e)}.`}async function Te(){try{const e=await N.supervisorStatus();return e.available?{status:"available",data:e.status,staleReason:null}:e.status!==null?{status:"available",data:e.status,staleReason:e.reason}:{status:"unavailable",error:Z(e.reason)}}catch(e){return{status:"unavailable",error:X(e,"supervisor status unavailable")}}}async function De(){try{return{status:"available",data:await N.localToolVersions()}}catch{return{status:"unavailable",error:"local tool versions unavailable"}}}async function Ae(){try{return await N.doltTrend()}catch{return{available:!1,reason:"sample_failed",samples:[]}}}async function Fe(){try{return await N.rigStoreHealth()}catch{return{available:!1,reason:"fetch_failed",rigs:[]}}}function Pe(e,a){const s=[];if(a===null)s.push("Supervisor state still loading.");else if(a.status==="available"){const o=a.data,d=o.status==="ok"?"healthy":o.status;o.city!==void 0?s.push(`Supervisor ${d} on ${o.city}, uptime ${_(o.uptime_sec)}.`):s.push(`Supervisor ${d}, uptime ${_(o.uptime_sec)}.`)}else s.push("Supervisor unreachable.");if(e===null)return s.push("Host health unavailable."),s.join(" ");const r=D(e),i=r===null?"Memory unavailable":`Memory at ${Math.round(100*(1-r))}%`,c=T(e)?`${e.host.cpu_count} CPUs averaging ${P(e).toFixed(2)} load`:"CPU/load unavailable";return s.push(`${i}; ${c}.`),s.join(" ")}function Ue(e){return e.status==="unavailable"?{tone:"stuck",label:"offline"}:e.data.status==="ok"?{tone:"ok",label:"healthy"}:{tone:"warn",label:e.data.status}}function Be(e){const a=D(e);if(a===null||!T(e)||!Ie(e.host.uptime))return{tone:"warn",label:"telemetry unavailable"};if(a<.05)return{tone:"stuck",label:"memory critical"};if(a<.1)return{tone:"warn",label:"memory low"};if(P(e)>e.host.cpu_count*1.5)return{tone:"warn",label:"load high"}}function T(e){if(e.host.load.status!=="available")return!1;const a=e.host.load.value;return L(e.host.cpu_count)&&y(a.load_avg_1)&&y(a.load_avg_5)&&y(a.load_avg_15)}function D(e){if(e.host.memory.status!=="available")return null;const a=e.host.memory.value.free_mem_bytes,s=e.host.memory.value.total_mem_bytes;return!Number.isFinite(a)||!Number.isFinite(s)||a<0||s<=0||a>s?null:a/s}function Ve(e){return D(e)===null||e.host.memory.status!=="available"?m:`${f(e.host.memory.value.free_mem_bytes)} of ${f(e.host.memory.value.total_mem_bytes)}`}function w(e){return Number.isFinite(e)&&e>0}function y(e){return Number.isFinite(e)&&e>=0}function L(e){return Number.isInteger(e)&&e>0}function q(e){return L(e)?e.toString():m}function Ee(e){if(!T(e)||e.host.load.status!=="available")return m;const a=e.host.load.value;return`${a.load_avg_1.toFixed(2)}, ${a.load_avg_5.toFixed(2)}, ${a.load_avg_15.toFixed(2)}`}function P(e){return e.host.load.status==="available"&&y(e.host.load.value.load_avg_1)?e.host.load.value.load_avg_1:0}function M(e){return e.status==="available"&&w(e.value)}function Ie(e){return e.status==="available"&&y(e.value)}function Oe(e){return M(e)&&e.status==="available"?_(e.value):m}function ze(e){return M(e)&&e.status==="available"?f(e.value):m}function Ke(e){return w(e)?_(e):m}function Qe(e){return w(e)?f(e):m}function te(e){if(e===null)return{status:"unavailable",reason:"supervisor status still loading"};if(e.status==="unavailable")return{status:"unavailable",reason:e.error};const a=e.data.store_health;return a===void 0?{status:"unavailable",reason:"supervisor did not report store_health"}:{status:"available",value:a,source:"supervisor status.store_health",...e.staleReason!==null?{stale:ee(e.staleReason)}:{}}}function We(e){return e===null?{status:"unavailable",reason:"supervisor status still loading"}:e.status==="unavailable"?{status:"unavailable",reason:e.error}:{status:"available",value:e.data.work,source:"supervisor status.work",...e.staleReason!==null?{stale:ee(e.staleReason)}:{}}}function qe(e){const a=te(e);if(a.status==="unavailable")return{status:"unavailable",reason:a.reason};const s=a.value;return{status:"available",source:"supervisor status.store_health (threshold vs actual)",...a.stale!==void 0?{stale:a.stale}:{},value:[{label:"Dolt MB-per-row ratio",recommended:`<= ${s.threshold_mb_per_row}`,loaded:String(s.ratio_mb_per_row),withinRecommendation:!s.warning}]}}function Xe(e){return typeof e=="bigint"?Number(e):e}function _(e){if(e<60)return`${e}s`;if(e<3600)return`${Math.round(e/60)}m`;if(e<86400)return`${Math.round(e/3600)}h`;const a=Math.floor(e/86400),s=Math.round(e%86400/3600);return s>0?`${a}d ${s}h`:`${a}d`}export{at as HealthPage}; diff --git a/internal/api/dashboardspa/dist/assets/LiveSessionPeek-F4FmVdxt.js b/internal/api/dashboardspa/dist/assets/LiveSessionPeek-VUsvyqKB.js similarity index 99% rename from internal/api/dashboardspa/dist/assets/LiveSessionPeek-F4FmVdxt.js rename to internal/api/dashboardspa/dist/assets/LiveSessionPeek-VUsvyqKB.js index 41905a9031..9565a1c15b 100644 --- a/internal/api/dashboardspa/dist/assets/LiveSessionPeek-F4FmVdxt.js +++ b/internal/api/dashboardspa/dist/assets/LiveSessionPeek-VUsvyqKB.js @@ -1,4 +1,4 @@ -import{r as d,ac as O,v as I,A as v,C as A,ad as L,Q as $,j as l,S as B}from"./index-DDS7Ehww.js";import{b as M,a as U,f as C}from"./time-BVuL_AnL.js";import{a as D}from"./format-fte2CeYD.js";import{P as F}from"./constants-CQJOeNM1.js";function q(t,e){const[s,r]=d.useState({status:"idle",stream:{status:"idle"}}),n=d.useRef(!1);return d.useEffect(()=>{if(n.current=!1,!t){r({status:"idle",stream:{status:"idle"}});return}let i=!1,a=null;const u=e&&typeof EventSource<"u";return r({status:"loading",stream:{status:u?"connecting":"idle"}}),O(t).then(c=>{if(!i&&(r({status:"ready",result:c,stream:{status:u?"connecting":"idle"}}),u)){a=new EventSource(I().sessionStreamUrl(G("open supervisor session stream"),t),{withCredentials:!0}),a.onopen=()=>{i||r(p=>p.status==="ready"?{...p,stream:{status:"open"}}:p)};const f=p=>{if(i)return;const h=z(p.data);h.kind==="invalid"&&H(t,n),r(_=>{const m=_.status==="ready"?_.result:c;return h.kind==="invalid"?{status:"ready",result:m,stream:{status:"degraded",error:h.error}}:h.kind==="snapshot"?{status:"ready",result:h.result,stream:{status:"open"}}:{status:"ready",result:{...m,turns:[...m.turns,h.turn],total_chars:m.total_chars+h.turn.text.length,captured_at:new Date().toISOString()},stream:{status:"open"}}})};a.onmessage=f,a.addEventListener("turn",f),a.onerror=()=>{if(i)return;const p=a?.readyState===EventSource.CLOSED?"closed":"connecting";r(h=>h.status==="ready"?{...h,stream:{status:p}}:h)}}},c=>{i||(N("load transcript",t,c),r({status:"failed",error:v(c)||"Failed to load session.",stream:{status:"idle"}}))}),()=>{i=!0,a?.close()}},[t,e]),s}function H(t,e){e.current||(e.current=!0,N("parse stream event",t,b))}function N(t,e,s){A({component:"session-stream",operation:t,message:`${e}: ${v(s)}`})}function G(t){const e=$();if(e===null)throw new Error(`${t} called before an active city was resolved`);return e}const b="Malformed session stream event.";function z(t){let e;try{e=JSON.parse(t)}catch{return{kind:"invalid",error:b}}if(!T(e))return{kind:"invalid",error:b};const s=V(e);return s?{kind:"snapshot",result:s}:typeof e.text!="string"?{kind:"invalid",error:b}:{kind:"turn",turn:{role:typeof e.role=="string"?e.role:"assistant",text:e.text}}}function V(t){if(!Array.isArray(t.turns))return null;const e=t.turns.flatMap(i=>!T(i)||typeof i.text!="string"?[]:[{role:typeof i.role=="string"?i.role:"assistant",text:i.text}]);if(e.length!==t.turns.length)return null;const s=typeof t.session_id=="string"?t.session_id:typeof t.id=="string"?t.id:"";if(!s)return null;const r=typeof t.total_chars=="number"?t.total_chars:e.reduce((i,a)=>i+a.text.length,0);return{...L({id:s,template:typeof t.template=="string"?t.template:"",provider:typeof t.provider=="string"?t.provider:"",format:t.format==="text"?"text":"conversation",turns:e},typeof t.captured_at=="string"?t.captured_at:new Date().toISOString()),total_chars:r,truncated:t.truncated===!0}}function T(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}var S=function(t,e){return Object.defineProperty?Object.defineProperty(t,"raw",{value:e}):t.raw=e,t},o;(function(t){t[t.EOS=0]="EOS",t[t.Text=1]="Text",t[t.Incomplete=2]="Incomplete",t[t.ESC=3]="ESC",t[t.Unknown=4]="Unknown",t[t.SGR=5]="SGR",t[t.OSCURL=6]="OSCURL"})(o||(o={}));class P{constructor(){this.VERSION="6.0.6",this.setup_palettes(),this._use_classes=!1,this.bold=!1,this.faint=!1,this.italic=!1,this.underline=!1,this.fg=this.bg=null,this._buffer="",this._url_allowlist={http:1,https:1},this._escape_html=!0,this.boldStyle="font-weight:bold",this.faintStyle="opacity:0.7",this.italicStyle="font-style:italic",this.underlineStyle="text-decoration:underline"}set use_classes(e){this._use_classes=e}get use_classes(){return this._use_classes}set url_allowlist(e){this._url_allowlist=e}get url_allowlist(){return this._url_allowlist}set escape_html(e){this._escape_html=e}get escape_html(){return this._escape_html}set boldStyle(e){this._boldStyle=e}get boldStyle(){return this._boldStyle}set faintStyle(e){this._faintStyle=e}get faintStyle(){return this._faintStyle}set italicStyle(e){this._italicStyle=e}get italicStyle(){return this._italicStyle}set underlineStyle(e){this._underlineStyle=e}get underlineStyle(){return this._underlineStyle}setup_palettes(){this.ansi_colors=[[{rgb:[0,0,0],class_name:"ansi-black"},{rgb:[187,0,0],class_name:"ansi-red"},{rgb:[0,187,0],class_name:"ansi-green"},{rgb:[187,187,0],class_name:"ansi-yellow"},{rgb:[0,0,187],class_name:"ansi-blue"},{rgb:[187,0,187],class_name:"ansi-magenta"},{rgb:[0,187,187],class_name:"ansi-cyan"},{rgb:[255,255,255],class_name:"ansi-white"}],[{rgb:[85,85,85],class_name:"ansi-bright-black"},{rgb:[255,85,85],class_name:"ansi-bright-red"},{rgb:[0,255,0],class_name:"ansi-bright-green"},{rgb:[255,255,85],class_name:"ansi-bright-yellow"},{rgb:[85,85,255],class_name:"ansi-bright-blue"},{rgb:[255,85,255],class_name:"ansi-bright-magenta"},{rgb:[85,255,255],class_name:"ansi-bright-cyan"},{rgb:[255,255,255],class_name:"ansi-bright-white"}]],this.palette_256=[],this.ansi_colors.forEach(r=>{r.forEach(n=>{this.palette_256.push(n)})});let e=[0,95,135,175,215,255];for(let r=0;r<6;++r)for(let n=0;n<6;++n)for(let i=0;i<6;++i){let a={rgb:[e[r],e[n],e[i]],class_name:"truecolor"};this.palette_256.push(a)}let s=8;for(let r=0;r<24;++r,s+=10){let n={rgb:[s,s,s],class_name:"truecolor"};this.palette_256.push(n)}}escape_txt_for_html(e){return this._escape_html?e.replace(/[&<>"']/gm,s=>{if(s==="&")return"&";if(s==="<")return"<";if(s===">")return">";if(s==='"')return""";if(s==="'")return"'"}):e}append_buffer(e){var s=this._buffer+e;this._buffer=s}get_next_packet(){var e={kind:o.EOS,text:"",url:""},s=this._buffer.length;if(s==0)return e;var r=this._buffer.indexOf("\x1B");if(r==-1)return e.kind=o.Text,e.text=this._buffer,this._buffer="",e;if(r>0)return e.kind=o.Text,e.text=this._buffer.slice(0,r),this._buffer=this._buffer.slice(r),e;if(r==0){if(s<3)return e.kind=o.Incomplete,e;var n=this._buffer.charAt(1);if(n!="["&&n!="]"&&n!="(")return e.kind=o.ESC,e.text=this._buffer.slice(0,1),this._buffer=this._buffer.slice(1),e;if(n=="["){this._csi_regex||(this._csi_regex=y(w||(w=S([` +import{r as d,ac as O,v as I,A as v,C as A,ad as L,Q as $,j as l,S as B}from"./index-BDHAaQRP.js";import{b as M,a as U,f as C}from"./time-BVuL_AnL.js";import{a as D}from"./format-fte2CeYD.js";import{P as F}from"./constants-D5DlRFFg.js";function q(t,e){const[s,r]=d.useState({status:"idle",stream:{status:"idle"}}),n=d.useRef(!1);return d.useEffect(()=>{if(n.current=!1,!t){r({status:"idle",stream:{status:"idle"}});return}let i=!1,a=null;const u=e&&typeof EventSource<"u";return r({status:"loading",stream:{status:u?"connecting":"idle"}}),O(t).then(c=>{if(!i&&(r({status:"ready",result:c,stream:{status:u?"connecting":"idle"}}),u)){a=new EventSource(I().sessionStreamUrl(G("open supervisor session stream"),t),{withCredentials:!0}),a.onopen=()=>{i||r(p=>p.status==="ready"?{...p,stream:{status:"open"}}:p)};const f=p=>{if(i)return;const h=z(p.data);h.kind==="invalid"&&H(t,n),r(_=>{const m=_.status==="ready"?_.result:c;return h.kind==="invalid"?{status:"ready",result:m,stream:{status:"degraded",error:h.error}}:h.kind==="snapshot"?{status:"ready",result:h.result,stream:{status:"open"}}:{status:"ready",result:{...m,turns:[...m.turns,h.turn],total_chars:m.total_chars+h.turn.text.length,captured_at:new Date().toISOString()},stream:{status:"open"}}})};a.onmessage=f,a.addEventListener("turn",f),a.onerror=()=>{if(i)return;const p=a?.readyState===EventSource.CLOSED?"closed":"connecting";r(h=>h.status==="ready"?{...h,stream:{status:p}}:h)}}},c=>{i||(N("load transcript",t,c),r({status:"failed",error:v(c)||"Failed to load session.",stream:{status:"idle"}}))}),()=>{i=!0,a?.close()}},[t,e]),s}function H(t,e){e.current||(e.current=!0,N("parse stream event",t,b))}function N(t,e,s){A({component:"session-stream",operation:t,message:`${e}: ${v(s)}`})}function G(t){const e=$();if(e===null)throw new Error(`${t} called before an active city was resolved`);return e}const b="Malformed session stream event.";function z(t){let e;try{e=JSON.parse(t)}catch{return{kind:"invalid",error:b}}if(!T(e))return{kind:"invalid",error:b};const s=V(e);return s?{kind:"snapshot",result:s}:typeof e.text!="string"?{kind:"invalid",error:b}:{kind:"turn",turn:{role:typeof e.role=="string"?e.role:"assistant",text:e.text}}}function V(t){if(!Array.isArray(t.turns))return null;const e=t.turns.flatMap(i=>!T(i)||typeof i.text!="string"?[]:[{role:typeof i.role=="string"?i.role:"assistant",text:i.text}]);if(e.length!==t.turns.length)return null;const s=typeof t.session_id=="string"?t.session_id:typeof t.id=="string"?t.id:"";if(!s)return null;const r=typeof t.total_chars=="number"?t.total_chars:e.reduce((i,a)=>i+a.text.length,0);return{...L({id:s,template:typeof t.template=="string"?t.template:"",provider:typeof t.provider=="string"?t.provider:"",format:t.format==="text"?"text":"conversation",turns:e},typeof t.captured_at=="string"?t.captured_at:new Date().toISOString()),total_chars:r,truncated:t.truncated===!0}}function T(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}var S=function(t,e){return Object.defineProperty?Object.defineProperty(t,"raw",{value:e}):t.raw=e,t},o;(function(t){t[t.EOS=0]="EOS",t[t.Text=1]="Text",t[t.Incomplete=2]="Incomplete",t[t.ESC=3]="ESC",t[t.Unknown=4]="Unknown",t[t.SGR=5]="SGR",t[t.OSCURL=6]="OSCURL"})(o||(o={}));class P{constructor(){this.VERSION="6.0.6",this.setup_palettes(),this._use_classes=!1,this.bold=!1,this.faint=!1,this.italic=!1,this.underline=!1,this.fg=this.bg=null,this._buffer="",this._url_allowlist={http:1,https:1},this._escape_html=!0,this.boldStyle="font-weight:bold",this.faintStyle="opacity:0.7",this.italicStyle="font-style:italic",this.underlineStyle="text-decoration:underline"}set use_classes(e){this._use_classes=e}get use_classes(){return this._use_classes}set url_allowlist(e){this._url_allowlist=e}get url_allowlist(){return this._url_allowlist}set escape_html(e){this._escape_html=e}get escape_html(){return this._escape_html}set boldStyle(e){this._boldStyle=e}get boldStyle(){return this._boldStyle}set faintStyle(e){this._faintStyle=e}get faintStyle(){return this._faintStyle}set italicStyle(e){this._italicStyle=e}get italicStyle(){return this._italicStyle}set underlineStyle(e){this._underlineStyle=e}get underlineStyle(){return this._underlineStyle}setup_palettes(){this.ansi_colors=[[{rgb:[0,0,0],class_name:"ansi-black"},{rgb:[187,0,0],class_name:"ansi-red"},{rgb:[0,187,0],class_name:"ansi-green"},{rgb:[187,187,0],class_name:"ansi-yellow"},{rgb:[0,0,187],class_name:"ansi-blue"},{rgb:[187,0,187],class_name:"ansi-magenta"},{rgb:[0,187,187],class_name:"ansi-cyan"},{rgb:[255,255,255],class_name:"ansi-white"}],[{rgb:[85,85,85],class_name:"ansi-bright-black"},{rgb:[255,85,85],class_name:"ansi-bright-red"},{rgb:[0,255,0],class_name:"ansi-bright-green"},{rgb:[255,255,85],class_name:"ansi-bright-yellow"},{rgb:[85,85,255],class_name:"ansi-bright-blue"},{rgb:[255,85,255],class_name:"ansi-bright-magenta"},{rgb:[85,255,255],class_name:"ansi-bright-cyan"},{rgb:[255,255,255],class_name:"ansi-bright-white"}]],this.palette_256=[],this.ansi_colors.forEach(r=>{r.forEach(n=>{this.palette_256.push(n)})});let e=[0,95,135,175,215,255];for(let r=0;r<6;++r)for(let n=0;n<6;++n)for(let i=0;i<6;++i){let a={rgb:[e[r],e[n],e[i]],class_name:"truecolor"};this.palette_256.push(a)}let s=8;for(let r=0;r<24;++r,s+=10){let n={rgb:[s,s,s],class_name:"truecolor"};this.palette_256.push(n)}}escape_txt_for_html(e){return this._escape_html?e.replace(/[&<>"']/gm,s=>{if(s==="&")return"&";if(s==="<")return"<";if(s===">")return">";if(s==='"')return""";if(s==="'")return"'"}):e}append_buffer(e){var s=this._buffer+e;this._buffer=s}get_next_packet(){var e={kind:o.EOS,text:"",url:""},s=this._buffer.length;if(s==0)return e;var r=this._buffer.indexOf("\x1B");if(r==-1)return e.kind=o.Text,e.text=this._buffer,this._buffer="",e;if(r>0)return e.kind=o.Text,e.text=this._buffer.slice(0,r),this._buffer=this._buffer.slice(r),e;if(r==0){if(s<3)return e.kind=o.Incomplete,e;var n=this._buffer.charAt(1);if(n!="["&&n!="]"&&n!="(")return e.kind=o.ESC,e.text=this._buffer.slice(0,1),this._buffer=this._buffer.slice(1),e;if(n=="["){this._csi_regex||(this._csi_regex=y(w||(w=S([` ^ # beginning of line # # First attempt diff --git a/internal/api/dashboardspa/dist/assets/Mail-BOec_zQx.js b/internal/api/dashboardspa/dist/assets/Mail-T1YOUrw8.js similarity index 98% rename from internal/api/dashboardspa/dist/assets/Mail-BOec_zQx.js rename to internal/api/dashboardspa/dist/assets/Mail-T1YOUrw8.js index 4b490ee91d..a4d420ebb8 100644 --- a/internal/api/dashboardspa/dist/assets/Mail-BOec_zQx.js +++ b/internal/api/dashboardspa/dist/assets/Mail-T1YOUrw8.js @@ -1,3 +1,3 @@ -import{j as e,r,I as re,U as L,V as qe,v as F,w as B,H as Ce,g as Me,K as ae,R as ne,S as se,B as M,i as _,a as Ue,T as Ye,W as Ae,X as Le,u as Ke,b as Ve,M as Ge,Y as be,Z as Qe,_ as Je,$ as Re,a0 as Ie}from"./index-DDS7Ehww.js";import{a as Xe,L as Ze,m as et}from"./projectOf-BjfQvzy4.js";import{a as tt,r as je}from"./routeHighlight-B30gQO2o.js";import{u as at,F as st}from"./useListFilters-HxlZke6_.js";import{T as rt}from"./Table-BMsY9n_s.js";import{M as _e,P as nt}from"./constants-CQJOeNM1.js";import{P as lt}from"./PageHeader-nOBkk_AA.js";import{F as P}from"./Field-BEMyWxxD.js";import{f as it}from"./time-BVuL_AnL.js";function q(t){const a=t.trim();if(a.length===0||!a.includes("/")&&!a.includes("\\"))return a;const i=a.split(/[\\/]/).filter(m=>m.length>0),c=i[i.length-1];if(c===void 0)return a;const n=i[i.length-2];if(n===void 0)return c;const l=c.startsWith(`${n}-`)?c.slice(n.length+1):c;return`${Xe(n)} · ${l}`}function ot({collapsed:t,onToggle:a,children:i,className:c="w-full flex items-baseline justify-between gap-4 focus-mark",glyphClassName:n}){return e.jsx("button",{type:"button",onClick:a,className:c,"aria-expanded":!t,children:i({glyph:e.jsx(ct,{collapsed:t,className:n??""})})})}function ct({collapsed:t,className:a=""}){return e.jsx("span",{"aria-hidden":!0,className:`inline-block text-fg-faint transition-transform duration-150 ease-out-quart ${a}`,style:{transform:t?"rotate(-90deg)":"rotate(0deg)"},children:"▾"})}function dt({project:t,count:a,collapsed:i,onToggle:c,collapsible:n=!0}){return n?e.jsx(ot,{collapsed:i,onToggle:c,className:"group flex items-baseline gap-2 w-full text-left focus-mark rounded-sm py-1",glyphClassName:"group-hover:text-fg-muted tnum w-3",children:({glyph:l})=>e.jsxs(e.Fragment,{children:[l,e.jsx("span",{className:"text-title font-medium text-fg group-hover:text-fg",children:t}),e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:a})]})}):e.jsxs("div",{role:"heading","aria-level":2,className:"flex items-baseline gap-2 py-1 text-label uppercase tracking-wider text-fg-faint",children:[e.jsx("span",{"aria-hidden":!0,children:"·"}),e.jsx("span",{children:t}),e.jsx("span",{"aria-hidden":!0,children:"·"})]})}function ut({groups:t,columns:a,rowKey:i,onToggleProject:c,onRowClick:n,rowProps:l,emptyMessage:m,perProjectEmpty:b,initialSort:h}){return t.length===0?e.jsx("p",{className:"py-10 text-center text-fg-muted italic",children:m}):e.jsx("div",{className:"space-y-8",children:t.map(d=>e.jsxs("section",{children:[e.jsx(dt,{project:d.project,count:d.totalInProject,collapsed:d.collapsed,onToggle:()=>c(d.projectKey),collapsible:d.collapsible}),!d.collapsed&&e.jsx(rt,{columns:a,rows:d.rows,rowKey:i,empty:b??"No items.",...n!==void 0?{onRowClick:n}:{},...l!==void 0?{rowProps:l}:{},...h!==void 0?{initialSort:h}:{}})]},d.projectKey))})}const ye="border-rule pb-6 border-b sm:shrink-0 sm:pr-6 sm:pb-0 sm:border-b-0 sm:border-r";function mt({buckets:t,loading:a,sessionsUnavailable:i,value:c,onChange:n,onReset:l,isOperator:m}){const[b,h]=r.useState(!1),[d,S]=r.useState(""),{operatorAlias:y,operatorWireAlias:u}=re(),A=L(c,y),x=r.useMemo(()=>{const f=d.trim().toLowerCase();return t.map(g=>({tier:g.tier,aliases:g.aliases.filter(v=>v.toLowerCase()===u?!1:f.length===0?!0:L(v,y).toLowerCase().includes(f)||v.toLowerCase().includes(f))})).filter(g=>g.aliases.length>0)},[t,d,y,u]),R=f=>{n(f),h(!1),S("")};return b?e.jsxs("aside",{className:`${ye} sm:w-64`,children:[e.jsx("button",{type:"button",onClick:()=>h(!1),"aria-expanded":!0,className:"text-label uppercase tracking-wider text-fg-muted hover:text-fg focus-mark rounded-sm",children:"▾ Agents"}),e.jsxs("div",{className:"mt-2 text-label uppercase tracking-wider text-fg-faint",children:[m?"Reading as":e.jsx("span",{className:"text-accent",children:"▲ Reading as"})," ",e.jsx("span",{className:`not-italic ${m?"text-fg-muted":"text-accent"}`,children:A})]}),e.jsx("div",{className:"mt-3 border-b border-rule pb-1",children:e.jsx("input",{type:"search",value:d,onChange:f=>S(f.target.value),placeholder:"Find an agent","aria-label":"Find an agent",autoFocus:!0,className:"w-full bg-transparent border-0 text-body text-fg placeholder:text-fg-faint focus:outline-none focus:ring-0 px-0 py-0.5"})}),e.jsxs("div",{className:"mt-3 max-h-[28rem] overflow-y-auto -mr-2 pr-2 space-y-4",children:[x.length===0?e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:a?"Loading aliases":"No agents match."}):x.map(f=>e.jsxs("div",{children:[e.jsx("div",{className:"text-label uppercase tracking-wider text-fg-faint mb-1",children:qe(f.tier)}),e.jsx("ul",{className:"space-y-0.5",children:f.aliases.map(g=>{const v=g.toLowerCase()===c.toLowerCase();return e.jsx("li",{children:e.jsx("button",{type:"button",onClick:()=>R(g),"aria-current":v,className:`block w-full text-left truncate text-body transition-colors duration-150 ease-out-quart focus-mark rounded-sm py-0.5 ${v?"text-fg font-semibold":"text-fg-muted hover:text-fg"}`,title:L(g,y),children:L(g,y)})},g)})})]},f.tier)),a&&x.length>0&&e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:"Loading more agents"}),!a&&i&&x.length>0&&(ft(x)?e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:"Agent list and mail history both unavailable."}):e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:"Agent list unavailable; showing mail-derived aliases only."}))]}),!m&&e.jsxs("div",{className:"mt-4 pt-3 border-t border-rule space-y-2",children:[e.jsx("button",{type:"button",onClick:l,className:"block text-label uppercase tracking-wider text-fg-muted hover:text-fg focus-mark underline decoration-dotted underline-offset-2 rounded-sm",children:"Back to operator"}),e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:"Read-only. Sends always go from the operator."})]})]}):e.jsxs("aside",{className:`${ye} sm:w-44`,children:[e.jsx("button",{type:"button",onClick:()=>h(!0),"aria-expanded":!1,className:"text-label uppercase tracking-wider text-fg-muted hover:text-fg focus-mark rounded-sm",children:"▸ Agents"}),e.jsx("div",{className:"mt-4 text-label uppercase tracking-wider text-fg-faint",children:m?"Reading as":e.jsx("span",{className:"text-accent",children:"▲ Reading as"})}),e.jsx("div",{className:`mt-1 text-body truncate ${m?"text-fg":"text-accent font-medium"}`,title:A,children:A}),!m&&e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:l,className:"mt-3 block text-label uppercase tracking-wider text-fg-muted hover:text-fg focus-mark underline decoration-dotted underline-offset-2 rounded-sm",children:"Back to operator"}),e.jsx("p",{className:"mt-2 text-label uppercase tracking-wider text-fg-faint italic",children:"Read-only. Sends go from the operator."})]})]})}function ft(t){let a=0;for(const i of t)if(a+=i.aliases.length,a>1)return!1;return a<=1}async function pt(t,a){await F().sendMail(B("send supervisor mail"),{...t,from:a})}async function ve(t){await F().markMailRead(B("mark supervisor mail read"),t.id,U(t))}async function we(t){await F().markMailUnread(B("mark supervisor mail unread"),t.id,U(t))}async function xt(t){await F().archiveMail(B("archive supervisor mail"),t.id,U(t))}async function ht(t,a,i){await F().replyMail(B("reply supervisor mail"),t.id,{...a,from:i},U(t))}function U(t){return t.rig===void 0||t.rig.length===0?void 0:{rig:t.rig}}function gt({open:t,onClose:a,onSent:i}){const{viewingAs:c}=Ce(),n=Me(),{operatorAlias:l,operatorWireAlias:m}=re(),[b,h]=r.useState(""),[d,S]=r.useState(""),[y,u]=r.useState(""),[A,x]=r.useState(!1),[R,f]=r.useState(null);r.useEffect(()=>{t||(h(""),S(""),u(""),f(null))},[t]);const g=r.useCallback(async()=>{if(!n){x(!0),f(null);try{await pt({to:b,subject:d,body:y},m),i()}catch(k){f(ae(k,"send failed"))}finally{x(!1)}}},[y,i,n,d,b,m]),v=!n&&c.isOperator&&b.length>0&&d.length>0&&y.length>0&&!A;return e.jsx(_e,{open:t,onClose:a,title:"New message",caption:"Sends from the operator. Reading-as has no effect on the sender.",widthClass:"max-w-2xl",footer:e.jsxs(e.Fragment,{children:[e.jsx(M,{tone:"quiet",size:"sm",onClick:a,children:"Cancel"}),e.jsx(M,{tone:"accent",size:"sm",disabled:!v,title:n?_:void 0,onClick:()=>{g()},children:A?"Sending":"Send"})]}),children:e.jsxs("div",{className:"space-y-4",children:[e.jsx(P,{label:"From",variant:"form",children:e.jsx("input",{type:"text",value:c.isOperator?L(l,l):`${L(l,l)} (reading-as does not change sender)`,disabled:!0,className:"w-full bg-transparent border-0 border-b border-rule pb-1 text-body text-fg-muted italic"})}),e.jsx(P,{label:"To (alias)",variant:"form",children:e.jsx("input",{type:"text",autoFocus:!0,value:b,onChange:k=>h(k.target.value),placeholder:"mayor, mechanic, scix-worker, …",className:"w-full bg-transparent border-0 border-b border-rule pb-1 text-body text-fg placeholder:text-fg-faint focus:border-accent focus:outline-none transition-colors"})}),e.jsx(P,{label:"Subject",variant:"form",children:e.jsx("input",{type:"text",value:d,onChange:k=>S(k.target.value),maxLength:200,className:"w-full bg-transparent border-0 border-b border-rule pb-1 text-body text-fg focus:border-accent focus:outline-none transition-colors"})}),e.jsx(P,{label:"Body",variant:"form",children:e.jsx("textarea",{value:y,onChange:k=>u(k.target.value),rows:10,maxLength:16*1024,className:"w-full bg-surface-tint border border-rule rounded-sm px-3 py-2 text-body text-fg focus:border-accent focus:outline-none focus:ring-1 focus:ring-accent/40 resize-y"})}),n&&e.jsx(ne,{}),!c.isOperator&&e.jsx(se,{tone:"warn",label:`Reading as ${L(c.alias,l)}. Sends from this modal are structurally locked to the operator regardless.`}),R&&e.jsx(se,{tone:"stuck",label:R})]})})}function ke({message:t,attentionSeverity:a=null}){return e.jsxs("article",{...bt(a),className:"space-y-3 pb-4 border-b border-rule last:border-0",children:[e.jsxs("header",{className:"flex items-baseline justify-between gap-3",children:[e.jsxs("div",{className:"text-label uppercase tracking-wider text-fg-muted truncate",children:[e.jsx("span",{className:"text-fg font-medium",children:q(t.from)}),e.jsx("span",{className:"mx-1.5 text-fg-faint",children:"→"}),e.jsx("span",{children:q(t.to)})]}),e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:jt(t.created_at)})]}),e.jsx("p",{className:"text-title font-semibold text-fg",children:t.subject}),e.jsx(se,{tone:"warn",label:nt}),e.jsx("pre",{className:"text-body whitespace-pre-wrap leading-relaxed text-fg overflow-x-auto",children:t.body})]})}function bt(t){return t===null?{}:{"data-attention-severity":t}}function jt(t){const a=Date.parse(t);return Number.isFinite(a)?new Date(a).toLocaleString(void 0,{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}):"·"}const Ne=[{id:"unread",label:"unread",match:t=>!t.read},{id:"read",label:"read",match:t=>t.read}],yt={id:"needs-you",label:"needs you",match:t=>!t.read&&!Je(t.from)},vt=t=>[t.from,t.to,t.subject,t.rig,t.body.split(` +import{j as e,r,I as re,U as L,V as qe,v as F,w as B,H as Ce,g as Me,K as ae,R as ne,S as se,B as M,i as _,a as Ue,T as Ye,W as Ae,X as Le,u as Ke,b as Ve,M as Ge,Y as be,Z as Qe,_ as Je,$ as Re,a0 as Ie}from"./index-BDHAaQRP.js";import{a as Xe,L as Ze,m as et}from"./projectOf-mIrvrzQE.js";import{a as tt,r as je}from"./routeHighlight-B30gQO2o.js";import{u as at,F as st}from"./useListFilters-D3eLt7Cq.js";import{T as rt}from"./Table-COJvPKIS.js";import{M as _e,P as nt}from"./constants-D5DlRFFg.js";import{P as lt}from"./PageHeader-BW5bf722.js";import{F as P}from"./Field-BSdtNgao.js";import{f as it}from"./time-BVuL_AnL.js";function q(t){const a=t.trim();if(a.length===0||!a.includes("/")&&!a.includes("\\"))return a;const i=a.split(/[\\/]/).filter(m=>m.length>0),c=i[i.length-1];if(c===void 0)return a;const n=i[i.length-2];if(n===void 0)return c;const l=c.startsWith(`${n}-`)?c.slice(n.length+1):c;return`${Xe(n)} · ${l}`}function ot({collapsed:t,onToggle:a,children:i,className:c="w-full flex items-baseline justify-between gap-4 focus-mark",glyphClassName:n}){return e.jsx("button",{type:"button",onClick:a,className:c,"aria-expanded":!t,children:i({glyph:e.jsx(ct,{collapsed:t,className:n??""})})})}function ct({collapsed:t,className:a=""}){return e.jsx("span",{"aria-hidden":!0,className:`inline-block text-fg-faint transition-transform duration-150 ease-out-quart ${a}`,style:{transform:t?"rotate(-90deg)":"rotate(0deg)"},children:"▾"})}function dt({project:t,count:a,collapsed:i,onToggle:c,collapsible:n=!0}){return n?e.jsx(ot,{collapsed:i,onToggle:c,className:"group flex items-baseline gap-2 w-full text-left focus-mark rounded-sm py-1",glyphClassName:"group-hover:text-fg-muted tnum w-3",children:({glyph:l})=>e.jsxs(e.Fragment,{children:[l,e.jsx("span",{className:"text-title font-medium text-fg group-hover:text-fg",children:t}),e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:a})]})}):e.jsxs("div",{role:"heading","aria-level":2,className:"flex items-baseline gap-2 py-1 text-label uppercase tracking-wider text-fg-faint",children:[e.jsx("span",{"aria-hidden":!0,children:"·"}),e.jsx("span",{children:t}),e.jsx("span",{"aria-hidden":!0,children:"·"})]})}function ut({groups:t,columns:a,rowKey:i,onToggleProject:c,onRowClick:n,rowProps:l,emptyMessage:m,perProjectEmpty:b,initialSort:h}){return t.length===0?e.jsx("p",{className:"py-10 text-center text-fg-muted italic",children:m}):e.jsx("div",{className:"space-y-8",children:t.map(d=>e.jsxs("section",{children:[e.jsx(dt,{project:d.project,count:d.totalInProject,collapsed:d.collapsed,onToggle:()=>c(d.projectKey),collapsible:d.collapsible}),!d.collapsed&&e.jsx(rt,{columns:a,rows:d.rows,rowKey:i,empty:b??"No items.",...n!==void 0?{onRowClick:n}:{},...l!==void 0?{rowProps:l}:{},...h!==void 0?{initialSort:h}:{}})]},d.projectKey))})}const ye="border-rule pb-6 border-b sm:shrink-0 sm:pr-6 sm:pb-0 sm:border-b-0 sm:border-r";function mt({buckets:t,loading:a,sessionsUnavailable:i,value:c,onChange:n,onReset:l,isOperator:m}){const[b,h]=r.useState(!1),[d,S]=r.useState(""),{operatorAlias:y,operatorWireAlias:u}=re(),A=L(c,y),x=r.useMemo(()=>{const f=d.trim().toLowerCase();return t.map(g=>({tier:g.tier,aliases:g.aliases.filter(v=>v.toLowerCase()===u?!1:f.length===0?!0:L(v,y).toLowerCase().includes(f)||v.toLowerCase().includes(f))})).filter(g=>g.aliases.length>0)},[t,d,y,u]),R=f=>{n(f),h(!1),S("")};return b?e.jsxs("aside",{className:`${ye} sm:w-64`,children:[e.jsx("button",{type:"button",onClick:()=>h(!1),"aria-expanded":!0,className:"text-label uppercase tracking-wider text-fg-muted hover:text-fg focus-mark rounded-sm",children:"▾ Agents"}),e.jsxs("div",{className:"mt-2 text-label uppercase tracking-wider text-fg-faint",children:[m?"Reading as":e.jsx("span",{className:"text-accent",children:"▲ Reading as"})," ",e.jsx("span",{className:`not-italic ${m?"text-fg-muted":"text-accent"}`,children:A})]}),e.jsx("div",{className:"mt-3 border-b border-rule pb-1",children:e.jsx("input",{type:"search",value:d,onChange:f=>S(f.target.value),placeholder:"Find an agent","aria-label":"Find an agent",autoFocus:!0,className:"w-full bg-transparent border-0 text-body text-fg placeholder:text-fg-faint focus:outline-none focus:ring-0 px-0 py-0.5"})}),e.jsxs("div",{className:"mt-3 max-h-[28rem] overflow-y-auto -mr-2 pr-2 space-y-4",children:[x.length===0?e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:a?"Loading aliases":"No agents match."}):x.map(f=>e.jsxs("div",{children:[e.jsx("div",{className:"text-label uppercase tracking-wider text-fg-faint mb-1",children:qe(f.tier)}),e.jsx("ul",{className:"space-y-0.5",children:f.aliases.map(g=>{const v=g.toLowerCase()===c.toLowerCase();return e.jsx("li",{children:e.jsx("button",{type:"button",onClick:()=>R(g),"aria-current":v,className:`block w-full text-left truncate text-body transition-colors duration-150 ease-out-quart focus-mark rounded-sm py-0.5 ${v?"text-fg font-semibold":"text-fg-muted hover:text-fg"}`,title:L(g,y),children:L(g,y)})},g)})})]},f.tier)),a&&x.length>0&&e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:"Loading more agents"}),!a&&i&&x.length>0&&(ft(x)?e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:"Agent list and mail history both unavailable."}):e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:"Agent list unavailable; showing mail-derived aliases only."}))]}),!m&&e.jsxs("div",{className:"mt-4 pt-3 border-t border-rule space-y-2",children:[e.jsx("button",{type:"button",onClick:l,className:"block text-label uppercase tracking-wider text-fg-muted hover:text-fg focus-mark underline decoration-dotted underline-offset-2 rounded-sm",children:"Back to operator"}),e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint italic",children:"Read-only. Sends always go from the operator."})]})]}):e.jsxs("aside",{className:`${ye} sm:w-44`,children:[e.jsx("button",{type:"button",onClick:()=>h(!0),"aria-expanded":!1,className:"text-label uppercase tracking-wider text-fg-muted hover:text-fg focus-mark rounded-sm",children:"▸ Agents"}),e.jsx("div",{className:"mt-4 text-label uppercase tracking-wider text-fg-faint",children:m?"Reading as":e.jsx("span",{className:"text-accent",children:"▲ Reading as"})}),e.jsx("div",{className:`mt-1 text-body truncate ${m?"text-fg":"text-accent font-medium"}`,title:A,children:A}),!m&&e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:l,className:"mt-3 block text-label uppercase tracking-wider text-fg-muted hover:text-fg focus-mark underline decoration-dotted underline-offset-2 rounded-sm",children:"Back to operator"}),e.jsx("p",{className:"mt-2 text-label uppercase tracking-wider text-fg-faint italic",children:"Read-only. Sends go from the operator."})]})]})}function ft(t){let a=0;for(const i of t)if(a+=i.aliases.length,a>1)return!1;return a<=1}async function pt(t,a){await F().sendMail(B("send supervisor mail"),{...t,from:a})}async function ve(t){await F().markMailRead(B("mark supervisor mail read"),t.id,U(t))}async function we(t){await F().markMailUnread(B("mark supervisor mail unread"),t.id,U(t))}async function xt(t){await F().archiveMail(B("archive supervisor mail"),t.id,U(t))}async function ht(t,a,i){await F().replyMail(B("reply supervisor mail"),t.id,{...a,from:i},U(t))}function U(t){return t.rig===void 0||t.rig.length===0?void 0:{rig:t.rig}}function gt({open:t,onClose:a,onSent:i}){const{viewingAs:c}=Ce(),n=Me(),{operatorAlias:l,operatorWireAlias:m}=re(),[b,h]=r.useState(""),[d,S]=r.useState(""),[y,u]=r.useState(""),[A,x]=r.useState(!1),[R,f]=r.useState(null);r.useEffect(()=>{t||(h(""),S(""),u(""),f(null))},[t]);const g=r.useCallback(async()=>{if(!n){x(!0),f(null);try{await pt({to:b,subject:d,body:y},m),i()}catch(k){f(ae(k,"send failed"))}finally{x(!1)}}},[y,i,n,d,b,m]),v=!n&&c.isOperator&&b.length>0&&d.length>0&&y.length>0&&!A;return e.jsx(_e,{open:t,onClose:a,title:"New message",caption:"Sends from the operator. Reading-as has no effect on the sender.",widthClass:"max-w-2xl",footer:e.jsxs(e.Fragment,{children:[e.jsx(M,{tone:"quiet",size:"sm",onClick:a,children:"Cancel"}),e.jsx(M,{tone:"accent",size:"sm",disabled:!v,title:n?_:void 0,onClick:()=>{g()},children:A?"Sending":"Send"})]}),children:e.jsxs("div",{className:"space-y-4",children:[e.jsx(P,{label:"From",variant:"form",children:e.jsx("input",{type:"text",value:c.isOperator?L(l,l):`${L(l,l)} (reading-as does not change sender)`,disabled:!0,className:"w-full bg-transparent border-0 border-b border-rule pb-1 text-body text-fg-muted italic"})}),e.jsx(P,{label:"To (alias)",variant:"form",children:e.jsx("input",{type:"text",autoFocus:!0,value:b,onChange:k=>h(k.target.value),placeholder:"mayor, mechanic, scix-worker, …",className:"w-full bg-transparent border-0 border-b border-rule pb-1 text-body text-fg placeholder:text-fg-faint focus:border-accent focus:outline-none transition-colors"})}),e.jsx(P,{label:"Subject",variant:"form",children:e.jsx("input",{type:"text",value:d,onChange:k=>S(k.target.value),maxLength:200,className:"w-full bg-transparent border-0 border-b border-rule pb-1 text-body text-fg focus:border-accent focus:outline-none transition-colors"})}),e.jsx(P,{label:"Body",variant:"form",children:e.jsx("textarea",{value:y,onChange:k=>u(k.target.value),rows:10,maxLength:16*1024,className:"w-full bg-surface-tint border border-rule rounded-sm px-3 py-2 text-body text-fg focus:border-accent focus:outline-none focus:ring-1 focus:ring-accent/40 resize-y"})}),n&&e.jsx(ne,{}),!c.isOperator&&e.jsx(se,{tone:"warn",label:`Reading as ${L(c.alias,l)}. Sends from this modal are structurally locked to the operator regardless.`}),R&&e.jsx(se,{tone:"stuck",label:R})]})})}function ke({message:t,attentionSeverity:a=null}){return e.jsxs("article",{...bt(a),className:"space-y-3 pb-4 border-b border-rule last:border-0",children:[e.jsxs("header",{className:"flex items-baseline justify-between gap-3",children:[e.jsxs("div",{className:"text-label uppercase tracking-wider text-fg-muted truncate",children:[e.jsx("span",{className:"text-fg font-medium",children:q(t.from)}),e.jsx("span",{className:"mx-1.5 text-fg-faint",children:"→"}),e.jsx("span",{children:q(t.to)})]}),e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:jt(t.created_at)})]}),e.jsx("p",{className:"text-title font-semibold text-fg",children:t.subject}),e.jsx(se,{tone:"warn",label:nt}),e.jsx("pre",{className:"text-body whitespace-pre-wrap leading-relaxed text-fg overflow-x-auto",children:t.body})]})}function bt(t){return t===null?{}:{"data-attention-severity":t}}function jt(t){const a=Date.parse(t);return Number.isFinite(a)?new Date(a).toLocaleString(void 0,{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}):"·"}const Ne=[{id:"unread",label:"unread",match:t=>!t.read},{id:"read",label:"read",match:t=>t.read}],yt={id:"needs-you",label:"needs you",match:t=>!t.read&&!Je(t.from)},vt=t=>[t.from,t.to,t.subject,t.rig,t.body.split(` `)[0]],wt=1e3;function Ft(){const t=Ue(),a=Me(),i=re(),[c]=Ye(),n=At(c.get("message")),{viewingAs:l,setAlias:m,resetToOperator:b,aliasBuckets:h,aliasesLoading:d,sessionsUnavailable:S,loadAliases:y}=Ce(),[u,A]=r.useState(()=>n===null?"inbox":"all"),[x,R]=r.useState(()=>n===null?Ae:wt),[f,g]=r.useState(Le);r.useEffect(()=>{y()},[y]);const v=Ke(),{data:k,loading:le,error:Y,refresh:$}=Ve(`mail:${u}:${l.alias}:${i.operatorWireAlias}:${x}:${f}`,()=>Ge(u,l.alias,i,x,f,v)),j=r.useMemo(()=>k?.items??[],[k]),[ie,I]=r.useState(null);r.useEffect(()=>{Y&&I(Y)},[Y]);const[w,T]=r.useState(null),[K,H]=r.useState([]),[Oe,oe]=r.useState(!1),V=r.useRef(null),[W,G]=r.useState(""),[E,ce]=r.useState(null),[Te,Q]=r.useState(!1),[O,D]=r.useState(()=>new Set),[Ee,de]=r.useState(null),J=r.useCallback(async s=>{if(T(s),H([]),G(""),I(null),!!s.thread_id){oe(!0);try{const o=await be(s.thread_id,l.alias,i,x);H(o.items)}catch(o){I(o instanceof Error?o.message:"thread failed")}finally{oe(!1)}}},[x,l.alias,i]);r.useEffect(()=>{if(n===null){V.current=null;return}if(V.current===n)return;const s=j.find(o=>o.id===n);s!==void 0&&(V.current=n,J(s))},[j,J,n]);const X=r.useCallback(async s=>{const o=w;if(o!==null&&!a){ce(s),I(null);try{if(s==="read")await ve(o),T({...o,read:!0});else if(s==="unread")await we(o),T({...o,read:!1});else if(s==="archive")await xt(o),T(null),H([]);else{const p=W.trim();if(p.length===0)return;if(await ht(o,{body:p},i.operatorWireAlias),G(""),o.thread_id){const ze=await be(o.thread_id,l.alias,i,x);H(ze.items)}}await $()}catch(p){I(ae(p,`${s} failed`))}finally{ce(null)}}},[x,a,$,W,w,l.alias,i]),ue=r.useMemo(()=>[{key:"from",label:"From",sortable:!0,sortValue:s=>q(s.from),render:s=>e.jsx("span",{className:"text-fg-muted",children:q(s.from)}),className:"w-48"},{key:"subject",label:"Subject",sortable:!0,sortValue:s=>s.subject,render:s=>e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:`truncate ${s.read?"text-fg-muted":"text-fg font-medium"}`,children:s.subject}),e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-faint mt-1 truncate",children:s.body.split(` `)[0]??""})]})},{key:"created_at",label:"When",sortable:!0,sortValue:s=>s.created_at,render:s=>e.jsx("span",{className:"tnum text-fg-muted",children:it(s.created_at,v)}),className:"w-24",align:"right"}],[v]),z=r.useMemo(()=>L(l.alias,i.operatorAlias),[l.alias,i.operatorAlias]),Z=r.useMemo(()=>u==="inbox"&&l.isOperator?Qe(j).length:0,[u,j,l.isOperator]),Pe=r.useMemo(()=>{const s=u==="all"?"all mail":u==="inbox"?"inbox":"sent";if(j.length===0)return`${$e(s)} empty for ${z}.`;const o=u==="sent"?0:j.filter(p=>!p.read).length;return u==="inbox"&&l.isOperator?o===0?`${j.length} in inbox, all read.`:Z>0?`${j.length} in inbox, ${Z} need you of ${o} unread.`:`${j.length} in inbox, ${o} unread, none need you.`:o>0?`${j.length} in ${s}, ${o} unread.`:`${j.length} in ${s}.`},[u,j,z,Z,l.isOperator]),me=r.useMemo(()=>l.isOperator?[yt,...Ne]:Ne,[l.isOperator]),N=at({viewKey:`mail:${u}`,rows:j,projectOf:et,searchOf:vt,chips:me}),fe=u!=="sent",C=r.useMemo(()=>N.groups.flatMap(s=>s.rows),[N.groups]),pe=r.useMemo(()=>C.reduce((s,o)=>O.has(o.id)?s+1:s,0),[C,O]),ee=C.length>0&&pe===C.length;r.useEffect(()=>{D(new Set)},[u,l.alias]);const xe=r.useCallback(s=>{D(o=>{const p=new Set(o);return p.has(s)?p.delete(s):p.add(s),p})},[]),Fe=r.useCallback(()=>{D(ee?new Set:new Set(C.map(s=>s.id)))},[ee,C]),he=r.useCallback(async s=>{if(a)return;const o=C.filter(p=>O.has(p.id)&&p.read!==s);if(o.length!==0){de(s?"read":"unread"),I(null);try{await Promise.all(o.map(p=>s?ve(p):we(p))),D(new Set)}catch(p){I(ae(p,`bulk mark ${s?"read":"unread"} failed`))}finally{de(null),await $()}}},[a,C,O,$]),Be=r.useMemo(()=>({key:"__select",label:"",className:"w-8",render:s=>e.jsx("input",{type:"checkbox",className:"h-3.5 w-3.5 translate-y-[2px] cursor-pointer accent-fg focus-mark",checked:O.has(s.id),onChange:()=>xe(s.id),onClick:o=>o.stopPropagation(),"aria-label":`select mail: ${s.subject}`})}),[O,xe]),He=fe?[Be,...ue]:ue,We=r.useMemo(()=>s=>tt(je(t,"mail",s.id)),[t]),ge=r.useCallback(s=>je(t,"mail",s.id),[t]),te=u==="sent"?[]:me,De=a||w===null||W.trim().length===0||E!==null||!l.isOperator;return e.jsxs("section",{children:[e.jsx(lt,{title:"Mail",synopsis:Pe,meta:e.jsxs(e.Fragment,{children:[ie&&e.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:ie}),a&&e.jsx(ne,{}),e.jsx(M,{size:"sm",onClick:()=>Q(!0),disabled:a||!l.isOperator,title:a?_:l.isOperator?"Compose a new message (sends as the operator)":"Switch back to the operator to compose",children:"Compose"}),e.jsx(M,{size:"sm",onClick:()=>{$()},disabled:le,children:le?"Refreshing":"Refresh"})]})}),e.jsxs("div",{className:"flex flex-col gap-8 sm:flex-row sm:items-start",children:[e.jsx(mt,{buckets:h,loading:d,sessionsUnavailable:S,value:l.alias,onChange:m,onReset:b,isOperator:l.isOperator}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"mb-6",children:e.jsx(kt,{box:u,onChange:A})}),e.jsxs("div",{className:"mb-6 space-y-3",children:[e.jsx(Ze,{value:N.search,onChange:N.setSearch,placeholder:"Search mail by sender, subject, rig",matchCount:N.totalMatches,totalCount:j.length,ariaLabel:"Search mail"}),te.length>0&&e.jsxs("div",{className:"flex items-baseline justify-between gap-4 flex-wrap",children:[e.jsx(st,{chips:te,activeIds:N.activeChipIds,onToggle:N.toggleChip,legend:"Read state"}),e.jsx(Se,{limit:x,onLimitChange:R,onWindowChange:g,window:f})]}),te.length===0&&e.jsx("div",{className:"flex justify-end",children:e.jsx(Se,{limit:x,onLimitChange:R,onWindowChange:g,window:f})})]}),fe&&C.length>0&&e.jsx("div",{className:"mb-6",children:e.jsx(Nt,{selectedCount:pe,allSelected:ee,onToggleAll:Fe,onMarkRead:()=>{he(!0)},onMarkUnread:()=>{he(!1)},bulkInFlight:Ee,readOnly:a})}),e.jsx(ut,{groups:N.groups,columns:He,rowKey:s=>s.id,onToggleProject:N.toggleProject,onRowClick:s=>{J(s)},rowProps:We,emptyMessage:N.search.length>0||N.activeChipIds.size>0?"No messages match the current search or filter.":`${u==="inbox"?"Inbox":"Sent"} empty for ${z}.`,perProjectEmpty:"No messages in this project.",initialSort:{key:"created_at",dir:"desc"}})]})]}),e.jsx(_e,{open:w!==null,onClose:()=>T(null),title:w?.subject??"Thread",caption:`Reading as ${z}, ${K.length} message(s)`,widthClass:"max-w-3xl",footer:w===null?null:e.jsxs(e.Fragment,{children:[e.jsx(M,{tone:"quiet",size:"sm",title:a?_:void 0,disabled:a||E!==null,onClick:()=>{X(w.read?"unread":"read")},children:w.read?"Mark unread":"Mark read"}),e.jsx(M,{tone:"quiet",size:"sm",title:a?_:void 0,disabled:a||E!==null,onClick:()=>{X("archive")},children:E==="archive"?"Archiving":"Archive"}),e.jsx(M,{tone:"accent",size:"sm",title:a?_:void 0,disabled:De,onClick:()=>{X("reply")},children:E==="reply"?"Replying":"Reply"})]}),children:e.jsxs("div",{className:"space-y-6",children:[Oe?e.jsx("p",{className:"text-fg-muted italic",children:"Loading thread."}):K.length===0&&w?e.jsx(ke,{message:w,attentionSeverity:ge(w)}):e.jsx("ol",{className:"space-y-6",children:K.map(s=>e.jsx("li",{children:e.jsx(ke,{message:s,attentionSeverity:ge(s)})},s.id))}),w!==null&&e.jsx(P,{label:"Reply",variant:"form",children:e.jsx("textarea",{value:W,onChange:s=>G(s.target.value),rows:5,maxLength:16*1024,title:a?_:void 0,disabled:a||!l.isOperator,className:"w-full bg-surface-tint border border-rule rounded-sm px-3 py-2 text-body text-fg focus:border-accent focus:outline-none focus:ring-1 focus:ring-accent/40 resize-y disabled:opacity-50"})})]})}),e.jsx(gt,{open:Te,onClose:()=>Q(!1),onSent:()=>{Q(!1),u==="sent"&&$()}})]})}function kt({box:t,onChange:a}){return e.jsx("div",{className:"flex items-baseline gap-6",children:["inbox","sent","all"].map(i=>e.jsx("button",{type:"button",onClick:()=>a(i),className:`text-title transition-colors duration-150 ease-out-quart focus-mark rounded-sm ${t===i?"text-fg font-semibold":"text-fg-muted hover:text-fg"}`,children:i==="all"?"All":$e(i)},i))})}function Nt({selectedCount:t,allSelected:a,onToggleAll:i,onMarkRead:c,onMarkUnread:n,bulkInFlight:l,readOnly:m}){const b=r.useRef(null),h=t>0;r.useEffect(()=>{b.current!==null&&(b.current.indeterminate=h&&!a)},[h,a]);const d=l!==null,S=m?_:void 0;return e.jsxs("div",{className:"flex items-baseline justify-between gap-4 flex-wrap border-b border-rule pb-3",role:"region","aria-label":"bulk mail selection",children:[e.jsxs("label",{className:"flex items-baseline gap-2 text-label uppercase tracking-wider text-fg-muted cursor-pointer",children:[e.jsx("input",{ref:b,type:"checkbox",className:"h-3.5 w-3.5 translate-y-[2px] cursor-pointer accent-fg focus-mark",checked:a,onChange:i,"aria-label":"select all mail"}),e.jsx("span",{children:h?`${t} selected`:"Select all"})]}),h&&e.jsxs("div",{className:"flex items-baseline gap-3",children:[m&&e.jsx(ne,{}),e.jsx(M,{size:"sm",tone:"quiet",onClick:c,disabled:m||d,title:S,children:l==="read"?"Marking":"Mark read"}),e.jsx(M,{size:"sm",tone:"quiet",onClick:n,disabled:m||d,title:S,children:l==="unread"?"Marking":"Mark unread"})]})]})}function Se({limit:t,onLimitChange:a,onWindowChange:i,window:c}){return e.jsxs("div",{className:"flex items-baseline gap-3 flex-wrap",children:[e.jsxs("label",{className:"flex items-baseline gap-2 text-label uppercase tracking-wider text-fg-muted",children:[e.jsx("span",{children:"Window"}),e.jsx("select",{"aria-label":"Mail time window",value:c,onChange:n=>i(Ct(n.target.value)),className:"bg-transparent border border-rule rounded-sm px-2 py-1 text-label uppercase tracking-wider text-fg-muted focus:border-accent focus:outline-none focus:ring-1 focus:ring-accent/40",children:Re.map(n=>e.jsx("option",{value:n,children:Mt(n)},n))})]}),e.jsxs("label",{className:"flex items-baseline gap-2 text-label uppercase tracking-wider text-fg-muted",children:[e.jsx("span",{children:"History"}),e.jsx("select",{"aria-label":"Mail history limit",value:t,onChange:n=>a(St(n.target.value)),className:"bg-transparent border border-rule rounded-sm px-2 py-1 text-label uppercase tracking-wider text-fg-muted focus:border-accent focus:outline-none focus:ring-1 focus:ring-accent/40",children:Ie.map(n=>e.jsxs("option",{value:n,children:["Recent ",n]},n))})]})]})}function St(t){const a=Number(t);return Ie.includes(a)?a:Ae}function Ct(t){return Re.includes(t)?t:Le}function Mt(t){return t==="24h"?"Last 24h":t==="7d"?"Last 7d":"All time"}function At(t){const a=t?.trim();return a&&a.length>0?a:null}function $e(t){return t.charAt(0).toUpperCase()+t.slice(1)}export{Ft as MailPage}; diff --git a/internal/api/dashboardspa/dist/assets/PageHeader-nOBkk_AA.js b/internal/api/dashboardspa/dist/assets/PageHeader-BW5bf722.js similarity index 89% rename from internal/api/dashboardspa/dist/assets/PageHeader-nOBkk_AA.js rename to internal/api/dashboardspa/dist/assets/PageHeader-BW5bf722.js index b4558fb981..c7610f3921 100644 --- a/internal/api/dashboardspa/dist/assets/PageHeader-nOBkk_AA.js +++ b/internal/api/dashboardspa/dist/assets/PageHeader-BW5bf722.js @@ -1 +1 @@ -import{j as e}from"./index-DDS7Ehww.js";function d({title:t,synopsis:s,meta:a,className:r=""}){return e.jsxs("header",{className:`grid grid-cols-1 items-start gap-x-6 gap-y-4 mb-10 md:grid-cols-[minmax(0,1fr)_auto] md:items-end ${r}`,children:[e.jsxs("div",{className:"min-w-0 space-y-2",children:[e.jsx("h1",{className:"text-display font-semibold tracking-tighter text-fg leading-[1.05]",children:t}),s&&e.jsx("p",{className:"text-body text-fg-muted max-w-prose",children:s})]}),a&&e.jsx("div",{className:"flex flex-wrap items-center gap-4 text-label uppercase tracking-wider md:justify-end",children:a})]})}export{d as P}; +import{j as e}from"./index-BDHAaQRP.js";function d({title:t,synopsis:s,meta:a,className:r=""}){return e.jsxs("header",{className:`grid grid-cols-1 items-start gap-x-6 gap-y-4 mb-10 md:grid-cols-[minmax(0,1fr)_auto] md:items-end ${r}`,children:[e.jsxs("div",{className:"min-w-0 space-y-2",children:[e.jsx("h1",{className:"text-display font-semibold tracking-tighter text-fg leading-[1.05]",children:t}),s&&e.jsx("p",{className:"text-body text-fg-muted max-w-prose",children:s})]}),a&&e.jsx("div",{className:"flex flex-wrap items-center gap-4 text-label uppercase tracking-wider md:justify-end",children:a})]})}export{d as P}; diff --git a/internal/api/dashboardspa/dist/assets/Runs-CdFC1a5g.js b/internal/api/dashboardspa/dist/assets/Runs-BUkrIZEc.js similarity index 98% rename from internal/api/dashboardspa/dist/assets/Runs-CdFC1a5g.js rename to internal/api/dashboardspa/dist/assets/Runs-BUkrIZEc.js index 4b17815735..154b68d537 100644 --- a/internal/api/dashboardspa/dist/assets/Runs-CdFC1a5g.js +++ b/internal/api/dashboardspa/dist/assets/Runs-BUkrIZEc.js @@ -1 +1 @@ -import{j as e,L as B,N as O,r as x,ae as D,a as M,O as U,T as z,u as V,B as w}from"./index-DDS7Ehww.js";import{b as F,r as Y}from"./routeHighlight-B30gQO2o.js";import{P as Q}from"./PageHeader-nOBkk_AA.js";import{S as q,P as G}from"./SseIndicator-CPfa0oji.js";import{f as _}from"./time-BVuL_AnL.js";import{S as K}from"./StageLadder-BZC9xxGP.js";const f=8;function W(t){return t==="blocked"?"text-accent":t==="complete"?"text-fg-muted":"text-fg"}function I({lane:t,now:n,attentionSeverity:r=null,blocked:s}){const a=Object.entries(t.statusCounts).sort((l,c)=>k(l[0]).localeCompare(k(c[0]))),{className:i="",...d}=F(r);return e.jsxs("li",{...d,className:`py-4 transition-colors duration-150 ease-out-quart ${i}`,children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx("span",{className:`text-label uppercase tracking-wider ${W(t.phase)}`,children:t.phaseLabel}),e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum tabular-nums",title:t.updatedAt.status==="available"?t.updatedAt.at:t.updatedAt.error,children:t.updatedAt.status==="available"?_(t.updatedAt.at,n):"·"})]}),e.jsx(B,{to:O(t.id,t.scope),className:"focus-mark mt-1 block text-body text-fg leading-snug hover:text-accent",children:t.title}),(t.external.status!=="unavailable"||t.formula.status==="known")&&e.jsxs("div",{className:"mt-1 flex items-baseline gap-x-4 gap-y-1 flex-wrap text-label",children:[t.external.status!=="unavailable"&&(t.external.status==="available"?e.jsx("a",{href:t.external.url,target:"_blank",rel:"noreferrer",className:"text-fg-muted uppercase tracking-wider hover:text-fg focus-mark",children:t.external.label}):e.jsx("span",{className:"text-fg-muted uppercase tracking-wider",children:t.external.label})),t.formula.status==="known"&&e.jsx("span",{className:"text-fg-faint tnum",children:t.formula.name})]}),e.jsx(K,{stages:t.stages,label:t.title}),e.jsxs("div",{className:"mt-2 flex items-baseline gap-x-4 gap-y-1 flex-wrap text-label",children:[e.jsx("span",{className:"text-fg-faint tnum",title:"run root bead",children:t.id}),t.activeAssignees.length>0&&e.jsxs("span",{className:"text-fg-muted lowercase tracking-normal",children:[e.jsx("span",{className:"uppercase tracking-wider text-fg-faint",children:"on "}),t.activeAssignees.join(", ")]}),a.length>0&&e.jsx("span",{className:"text-fg-faint uppercase tracking-wider tnum tabular-nums",children:a.map(([l,c])=>`${c} ${l.replace(/_/g," ")}`).join(" · ")})]}),s!==void 0&&e.jsxs("div",{className:"mt-2",children:[e.jsxs("p",{className:"text-body text-fg leading-snug",children:[e.jsx("span",{"aria-hidden":"true",className:"text-accent",children:"✕"})," ",s.reason]}),e.jsx("p",{className:"mt-1 text-body text-fg-muted leading-snug",children:s.remedy})]})]})}function k(t){return`${{blocked:"0",in_progress:"1",open:"2",closed:"3"}[t]??"9"}-${t}`}const X=[["prReview","PR"],["designReview","Design"],["bugfix","Bugfix"],["other","Other"]],C="runs-historical-section",S="runs-historical-list",R="runs-active-list",h=5;function J({source:t,now:n,showHistory:r,attentionSeverity:s}){if(t.status==="error")return e.jsxs("section",{children:[e.jsx(A,{summary:null}),e.jsx("p",{className:"mt-8 text-body text-fg-muted italic",children:`Run data unavailable: ${t.error}.`})]});const a=t.data;return e.jsxs("section",{children:[e.jsx(A,{summary:a}),e.jsx(Z,{summary:a,now:n,...s===void 0?{}:{attentionSeverity:s}}),e.jsx(se,{summary:a,now:n,...s===void 0?{}:{attentionSeverity:s}}),r&&e.jsx(ae,{summary:a,now:n,...s===void 0?{}:{attentionSeverity:s}})]})}function Z({summary:t,now:n,attentionSeverity:r}){const[s,a]=x.useState(!1);if(t.lanes.length===0){if(t.lanesPartial===!0)return e.jsx("p",{className:"mt-8 text-body text-fg-muted italic",children:"Run sources were partially unavailable; the lane set may be incomplete."});const l=t.totalHistorical>0?` (${t.totalHistorical} completed.)`:"";return e.jsx("p",{className:"mt-8 text-body text-fg-muted italic",children:`No active formula runs.${l}`})}const i=s?t.lanes:t.lanes.slice(0,f),d=ee(i);return e.jsxs(e.Fragment,{children:[e.jsx("div",{id:R,children:d.map(({rig:l,lanes:c})=>e.jsxs("div",{className:"mt-6",children:[e.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint",children:te(l)}),e.jsx(H,{lanes:c,now:n,...r===void 0?{}:{attentionSeverity:r}})]},l))}),t.lanes.length>f&&e.jsx("button",{type:"button",onClick:()=>a(l=>!l),"aria-expanded":s,"aria-controls":R,className:"mt-3 text-label uppercase tracking-wider text-fg-faint tnum hover:text-fg focus-mark",children:s?"Show fewer":`Show ${t.lanes.length-f} more runs`})]})}function H({lanes:t,now:n,attentionSeverity:r,listId:s}){return e.jsx("ol",{...s===void 0?{}:{id:s},className:"mt-3 divide-y divide-rule",children:t.map(a=>e.jsx(I,{lane:a,now:n,...r===void 0?{}:{attentionSeverity:r(a)}},a.id))})}function ee(t){const n=[],r=new Map;for(const s of t){const a=s.scope.status==="available"&&s.scope.kind==="rig"?s.scope.rootStoreRef:"city";let i=r.get(a);i===void 0&&(i=[],r.set(a,i),n.push(a)),i.push(s)}return n.map(s=>({rig:s,lanes:r.get(s)}))}function te(t){return t.replace(/^rig:/,"")}function se({summary:t,now:n,attentionSeverity:r}){const s=new Map(D(t.blockedLanes).map(a=>[a.id,a]));return s.size===0?null:e.jsxs("section",{"aria-label":"Blocked runs",className:"mt-12",children:[e.jsxs("h2",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:["Blocked (",s.size,")"]}),e.jsx("ol",{className:"mt-3 divide-y divide-rule",children:t.blockedLanes.map(a=>{const i=s.get(a.id);return e.jsx(I,{lane:a,now:n,...r===void 0?{}:{attentionSeverity:r(a)},...i===void 0?{}:{blocked:i}},a.id)})})]})}function ae({summary:t,now:n,attentionSeverity:r}){const[s,a]=x.useState(!1),i=t.historicalLanes,d=s?i:i.slice(0,h);return e.jsxs("section",{id:C,"aria-label":"Historical runs",className:"mt-12",children:[e.jsx("h2",{className:"text-label uppercase tracking-wider text-fg-faint",children:"Historical"}),i.length===0?e.jsx("p",{className:"mt-3 text-body text-fg-muted italic",children:"No completed runs in the current window."}):e.jsxs(e.Fragment,{children:[e.jsx(H,{lanes:d,now:n,listId:S,...r===void 0?{}:{attentionSeverity:r}}),i.length>h&&e.jsx("button",{type:"button",onClick:()=>a(l=>!l),"aria-expanded":s,"aria-controls":S,className:"mt-3 text-label uppercase tracking-wider text-fg-faint tnum hover:text-fg focus-mark",children:s?"Show fewer":`Show ${i.length-h} more`}),t.totalHistorical>i.length&&e.jsxs("p",{className:"mt-3 text-label uppercase tracking-wider text-fg-faint tnum",children:["Showing ",i.length," most-recent of ",t.totalHistorical]})]})]})}function A({summary:t}){const n=t?.runCounts.total??0,r=t?.runCounts.blocked??0;return e.jsx("header",{className:"space-y-2",children:e.jsxs("div",{className:"flex items-baseline gap-x-6 gap-y-2 flex-wrap",children:[e.jsx(g,{label:"Active",value:n,tone:"strong"}),X.map(([s,a])=>e.jsx(g,{label:a,value:t?.runCounts[s]??0,tone:"muted"},s)),r>0&&e.jsx(g,{label:"Blocked",value:r,tone:"muted"})]})})}function g({label:t,value:n,tone:r}){const s=r==="strong"?"text-fg":"text-fg-muted";return e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:t}),e.jsx("span",{className:`text-title tnum ${s}`,children:n})]})}const re=C,L="Phase grammar: intake, implementation, review, approval, finalization.",b="history",y="1";function xe(){const t=M(),{source:n,loading:r,error:s,refresh:a,sseState:i}=U(),[d,l]=z(),c=d.get(b)===y,j=V(),o=n??null,N=o?.status==="fresh"||o?.status==="fixture"||o?.status==="stale"?o.data:null,u=N?.totalHistorical??0,$=N?.lanesPartial===!0,P=x.useCallback(()=>{l(m=>{const p=new URLSearchParams(m);return c?p.delete(b):p.set(b,y),p},{replace:!1})},[c,l]),E=x.useCallback(m=>Y(t,"runs",m.id),[t]),T=ne(n),v=o?o.status==="fresh"?null:o.status==="fixture"?"fixture data":o.status==="error"?"live data unavailable":o.fetchedAt?`stale ${_(o.fetchedAt,j)} ago`:"stale":null;return e.jsxs("section",{children:[e.jsx(Q,{title:"Formula Runs",synopsis:T,className:"md:items-start",meta:e.jsxs(e.Fragment,{children:[s&&e.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:s}),v!==null&&e.jsx("span",{className:`text-label uppercase tracking-wider tnum ${o?.status==="error"?"text-accent":"text-fg-faint"}`,children:v}),e.jsxs("div",{className:"grid w-full min-w-[18rem] grid-cols-[7rem_minmax(6.5rem,1fr)] items-center gap-x-4 gap-y-3 sm:w-[34rem] sm:grid-cols-[7rem_6.5rem_10rem_7rem]",children:[e.jsx(q,{state:i}),e.jsx("span",{children:$?e.jsx(G,{glyph:"◐",label:"runs partial",title:"one or more rigs' recent runs were unavailable; the lane set may be incomplete"}):e.jsx("span",{"aria-hidden":"true",className:"invisible normal-case text-body text-warn",children:"runs partial"})}),e.jsx(w,{size:"sm",className:"w-full justify-center",onClick:P,disabled:!c&&u===0,"aria-expanded":c,...c?{"aria-controls":re}:{},"aria-label":c?"Hide historical formula runs.":u===0?"No completed formula runs in the current window.":`Show ${u} completed formula runs.`,children:c?"Hide history":u>0?`Show history (${u})`:"Show history"}),e.jsx(w,{size:"sm",className:"w-full justify-center",onClick:()=>{a()},disabled:r,children:r?"Refreshing":"Refresh"})]})]})}),n===void 0||o===null?e.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading formula runs."}):e.jsx(J,{source:o,now:j,showHistory:c,attentionSeverity:E})]})}function ne(t){return t===void 0?"Loading formula run lanes.":t.status!=="error"?`${t.data.totalActive} active runs across the supervisor's bead store. ${L}`:`Run counts unavailable: ${t.error}. ${L}`}export{xe as RunsPage}; +import{j as e,L as B,N as O,r as x,ae as D,a as M,O as U,T as z,u as V,B as w}from"./index-BDHAaQRP.js";import{b as F,r as Y}from"./routeHighlight-B30gQO2o.js";import{P as Q}from"./PageHeader-BW5bf722.js";import{S as q,P as G}from"./SseIndicator-Dw8_ai2P.js";import{f as _}from"./time-BVuL_AnL.js";import{S as K}from"./StageLadder-CoXQBCKu.js";const f=8;function W(t){return t==="blocked"?"text-accent":t==="complete"?"text-fg-muted":"text-fg"}function I({lane:t,now:n,attentionSeverity:r=null,blocked:s}){const a=Object.entries(t.statusCounts).sort((l,c)=>k(l[0]).localeCompare(k(c[0]))),{className:i="",...d}=F(r);return e.jsxs("li",{...d,className:`py-4 transition-colors duration-150 ease-out-quart ${i}`,children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx("span",{className:`text-label uppercase tracking-wider ${W(t.phase)}`,children:t.phaseLabel}),e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum tabular-nums",title:t.updatedAt.status==="available"?t.updatedAt.at:t.updatedAt.error,children:t.updatedAt.status==="available"?_(t.updatedAt.at,n):"·"})]}),e.jsx(B,{to:O(t.id,t.scope),className:"focus-mark mt-1 block text-body text-fg leading-snug hover:text-accent",children:t.title}),(t.external.status!=="unavailable"||t.formula.status==="known")&&e.jsxs("div",{className:"mt-1 flex items-baseline gap-x-4 gap-y-1 flex-wrap text-label",children:[t.external.status!=="unavailable"&&(t.external.status==="available"?e.jsx("a",{href:t.external.url,target:"_blank",rel:"noreferrer",className:"text-fg-muted uppercase tracking-wider hover:text-fg focus-mark",children:t.external.label}):e.jsx("span",{className:"text-fg-muted uppercase tracking-wider",children:t.external.label})),t.formula.status==="known"&&e.jsx("span",{className:"text-fg-faint tnum",children:t.formula.name})]}),e.jsx(K,{stages:t.stages,label:t.title}),e.jsxs("div",{className:"mt-2 flex items-baseline gap-x-4 gap-y-1 flex-wrap text-label",children:[e.jsx("span",{className:"text-fg-faint tnum",title:"run root bead",children:t.id}),t.activeAssignees.length>0&&e.jsxs("span",{className:"text-fg-muted lowercase tracking-normal",children:[e.jsx("span",{className:"uppercase tracking-wider text-fg-faint",children:"on "}),t.activeAssignees.join(", ")]}),a.length>0&&e.jsx("span",{className:"text-fg-faint uppercase tracking-wider tnum tabular-nums",children:a.map(([l,c])=>`${c} ${l.replace(/_/g," ")}`).join(" · ")})]}),s!==void 0&&e.jsxs("div",{className:"mt-2",children:[e.jsxs("p",{className:"text-body text-fg leading-snug",children:[e.jsx("span",{"aria-hidden":"true",className:"text-accent",children:"✕"})," ",s.reason]}),e.jsx("p",{className:"mt-1 text-body text-fg-muted leading-snug",children:s.remedy})]})]})}function k(t){return`${{blocked:"0",in_progress:"1",open:"2",closed:"3"}[t]??"9"}-${t}`}const X=[["prReview","PR"],["designReview","Design"],["bugfix","Bugfix"],["other","Other"]],C="runs-historical-section",S="runs-historical-list",R="runs-active-list",h=5;function J({source:t,now:n,showHistory:r,attentionSeverity:s}){if(t.status==="error")return e.jsxs("section",{children:[e.jsx(A,{summary:null}),e.jsx("p",{className:"mt-8 text-body text-fg-muted italic",children:`Run data unavailable: ${t.error}.`})]});const a=t.data;return e.jsxs("section",{children:[e.jsx(A,{summary:a}),e.jsx(Z,{summary:a,now:n,...s===void 0?{}:{attentionSeverity:s}}),e.jsx(se,{summary:a,now:n,...s===void 0?{}:{attentionSeverity:s}}),r&&e.jsx(ae,{summary:a,now:n,...s===void 0?{}:{attentionSeverity:s}})]})}function Z({summary:t,now:n,attentionSeverity:r}){const[s,a]=x.useState(!1);if(t.lanes.length===0){if(t.lanesPartial===!0)return e.jsx("p",{className:"mt-8 text-body text-fg-muted italic",children:"Run sources were partially unavailable; the lane set may be incomplete."});const l=t.totalHistorical>0?` (${t.totalHistorical} completed.)`:"";return e.jsx("p",{className:"mt-8 text-body text-fg-muted italic",children:`No active formula runs.${l}`})}const i=s?t.lanes:t.lanes.slice(0,f),d=ee(i);return e.jsxs(e.Fragment,{children:[e.jsx("div",{id:R,children:d.map(({rig:l,lanes:c})=>e.jsxs("div",{className:"mt-6",children:[e.jsx("h3",{className:"text-label uppercase tracking-wider text-fg-faint",children:te(l)}),e.jsx(H,{lanes:c,now:n,...r===void 0?{}:{attentionSeverity:r}})]},l))}),t.lanes.length>f&&e.jsx("button",{type:"button",onClick:()=>a(l=>!l),"aria-expanded":s,"aria-controls":R,className:"mt-3 text-label uppercase tracking-wider text-fg-faint tnum hover:text-fg focus-mark",children:s?"Show fewer":`Show ${t.lanes.length-f} more runs`})]})}function H({lanes:t,now:n,attentionSeverity:r,listId:s}){return e.jsx("ol",{...s===void 0?{}:{id:s},className:"mt-3 divide-y divide-rule",children:t.map(a=>e.jsx(I,{lane:a,now:n,...r===void 0?{}:{attentionSeverity:r(a)}},a.id))})}function ee(t){const n=[],r=new Map;for(const s of t){const a=s.scope.status==="available"&&s.scope.kind==="rig"?s.scope.rootStoreRef:"city";let i=r.get(a);i===void 0&&(i=[],r.set(a,i),n.push(a)),i.push(s)}return n.map(s=>({rig:s,lanes:r.get(s)}))}function te(t){return t.replace(/^rig:/,"")}function se({summary:t,now:n,attentionSeverity:r}){const s=new Map(D(t.blockedLanes).map(a=>[a.id,a]));return s.size===0?null:e.jsxs("section",{"aria-label":"Blocked runs",className:"mt-12",children:[e.jsxs("h2",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:["Blocked (",s.size,")"]}),e.jsx("ol",{className:"mt-3 divide-y divide-rule",children:t.blockedLanes.map(a=>{const i=s.get(a.id);return e.jsx(I,{lane:a,now:n,...r===void 0?{}:{attentionSeverity:r(a)},...i===void 0?{}:{blocked:i}},a.id)})})]})}function ae({summary:t,now:n,attentionSeverity:r}){const[s,a]=x.useState(!1),i=t.historicalLanes,d=s?i:i.slice(0,h);return e.jsxs("section",{id:C,"aria-label":"Historical runs",className:"mt-12",children:[e.jsx("h2",{className:"text-label uppercase tracking-wider text-fg-faint",children:"Historical"}),i.length===0?e.jsx("p",{className:"mt-3 text-body text-fg-muted italic",children:"No completed runs in the current window."}):e.jsxs(e.Fragment,{children:[e.jsx(H,{lanes:d,now:n,listId:S,...r===void 0?{}:{attentionSeverity:r}}),i.length>h&&e.jsx("button",{type:"button",onClick:()=>a(l=>!l),"aria-expanded":s,"aria-controls":S,className:"mt-3 text-label uppercase tracking-wider text-fg-faint tnum hover:text-fg focus-mark",children:s?"Show fewer":`Show ${i.length-h} more`}),t.totalHistorical>i.length&&e.jsxs("p",{className:"mt-3 text-label uppercase tracking-wider text-fg-faint tnum",children:["Showing ",i.length," most-recent of ",t.totalHistorical]})]})]})}function A({summary:t}){const n=t?.runCounts.total??0,r=t?.runCounts.blocked??0;return e.jsx("header",{className:"space-y-2",children:e.jsxs("div",{className:"flex items-baseline gap-x-6 gap-y-2 flex-wrap",children:[e.jsx(g,{label:"Active",value:n,tone:"strong"}),X.map(([s,a])=>e.jsx(g,{label:a,value:t?.runCounts[s]??0,tone:"muted"},s)),r>0&&e.jsx(g,{label:"Blocked",value:r,tone:"muted"})]})})}function g({label:t,value:n,tone:r}){const s=r==="strong"?"text-fg":"text-fg-muted";return e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"text-label uppercase tracking-wider text-fg-faint",children:t}),e.jsx("span",{className:`text-title tnum ${s}`,children:n})]})}const re=C,L="Phase grammar: intake, implementation, review, approval, finalization.",b="history",y="1";function xe(){const t=M(),{source:n,loading:r,error:s,refresh:a,sseState:i}=U(),[d,l]=z(),c=d.get(b)===y,j=V(),o=n??null,N=o?.status==="fresh"||o?.status==="fixture"||o?.status==="stale"?o.data:null,u=N?.totalHistorical??0,$=N?.lanesPartial===!0,P=x.useCallback(()=>{l(m=>{const p=new URLSearchParams(m);return c?p.delete(b):p.set(b,y),p},{replace:!1})},[c,l]),E=x.useCallback(m=>Y(t,"runs",m.id),[t]),T=ne(n),v=o?o.status==="fresh"?null:o.status==="fixture"?"fixture data":o.status==="error"?"live data unavailable":o.fetchedAt?`stale ${_(o.fetchedAt,j)} ago`:"stale":null;return e.jsxs("section",{children:[e.jsx(Q,{title:"Formula Runs",synopsis:T,className:"md:items-start",meta:e.jsxs(e.Fragment,{children:[s&&e.jsx("span",{className:"normal-case text-body text-accent",role:"alert",children:s}),v!==null&&e.jsx("span",{className:`text-label uppercase tracking-wider tnum ${o?.status==="error"?"text-accent":"text-fg-faint"}`,children:v}),e.jsxs("div",{className:"grid w-full min-w-[18rem] grid-cols-[7rem_minmax(6.5rem,1fr)] items-center gap-x-4 gap-y-3 sm:w-[34rem] sm:grid-cols-[7rem_6.5rem_10rem_7rem]",children:[e.jsx(q,{state:i}),e.jsx("span",{children:$?e.jsx(G,{glyph:"◐",label:"runs partial",title:"one or more rigs' recent runs were unavailable; the lane set may be incomplete"}):e.jsx("span",{"aria-hidden":"true",className:"invisible normal-case text-body text-warn",children:"runs partial"})}),e.jsx(w,{size:"sm",className:"w-full justify-center",onClick:P,disabled:!c&&u===0,"aria-expanded":c,...c?{"aria-controls":re}:{},"aria-label":c?"Hide historical formula runs.":u===0?"No completed formula runs in the current window.":`Show ${u} completed formula runs.`,children:c?"Hide history":u>0?`Show history (${u})`:"Show history"}),e.jsx(w,{size:"sm",className:"w-full justify-center",onClick:()=>{a()},disabled:r,children:r?"Refreshing":"Refresh"})]})]})}),n===void 0||o===null?e.jsx("p",{className:"text-body text-fg-muted italic",children:"Loading formula runs."}):e.jsx(J,{source:o,now:j,showHistory:c,attentionSeverity:E})]})}function ne(t){return t===void 0?"Loading formula run lanes.":t.status!=="error"?`${t.data.totalActive} active runs across the supervisor's bead store. ${L}`:`Run counts unavailable: ${t.error}. ${L}`}export{xe as RunsPage}; diff --git a/internal/api/dashboardspa/dist/assets/SseIndicator-CPfa0oji.js b/internal/api/dashboardspa/dist/assets/SseIndicator-Dw8_ai2P.js similarity index 88% rename from internal/api/dashboardspa/dist/assets/SseIndicator-CPfa0oji.js rename to internal/api/dashboardspa/dist/assets/SseIndicator-Dw8_ai2P.js index 37c8e8fca0..a17d0be698 100644 --- a/internal/api/dashboardspa/dist/assets/SseIndicator-CPfa0oji.js +++ b/internal/api/dashboardspa/dist/assets/SseIndicator-Dw8_ai2P.js @@ -1 +1 @@ -import{j as a,S as t}from"./index-DDS7Ehww.js";function i({label:n,title:e,show:r=!0,glyph:o}){return r?a.jsxs("span",{className:"normal-case text-body text-warn",role:"status",title:e,children:[o!==void 0&&a.jsxs("span",{"aria-hidden":"true",children:[o," "]}),n]}):null}function c({state:n}){const e=n==="open"?"ok":n==="connecting"||n==="degraded"?"warn":"stuck",r=n==="open"?"live":n==="connecting"?"connecting":n==="degraded"?"degraded":"offline";return a.jsx(t,{tone:e,label:r,title:`SSE stream: ${n}`,className:"w-28"})}export{i as P,c as S}; +import{j as a,S as t}from"./index-BDHAaQRP.js";function i({label:n,title:e,show:r=!0,glyph:o}){return r?a.jsxs("span",{className:"normal-case text-body text-warn",role:"status",title:e,children:[o!==void 0&&a.jsxs("span",{"aria-hidden":"true",children:[o," "]}),n]}):null}function c({state:n}){const e=n==="open"?"ok":n==="connecting"||n==="degraded"?"warn":"stuck",r=n==="open"?"live":n==="connecting"?"connecting":n==="degraded"?"degraded":"offline";return a.jsx(t,{tone:e,label:r,title:`SSE stream: ${n}`,className:"w-28"})}export{i as P,c as S}; diff --git a/internal/api/dashboardspa/dist/assets/StageLadder-BZC9xxGP.js b/internal/api/dashboardspa/dist/assets/StageLadder-CoXQBCKu.js similarity index 91% rename from internal/api/dashboardspa/dist/assets/StageLadder-BZC9xxGP.js rename to internal/api/dashboardspa/dist/assets/StageLadder-CoXQBCKu.js index ecb35abf04..03f3668b12 100644 --- a/internal/api/dashboardspa/dist/assets/StageLadder-BZC9xxGP.js +++ b/internal/api/dashboardspa/dist/assets/StageLadder-CoXQBCKu.js @@ -1 +1 @@ -import{j as t}from"./index-DDS7Ehww.js";const n={pending:"·",active:"⬣",complete:"◆",blocked:"✕"},c={pending:"text-fg-faint",active:"text-fg",complete:"text-fg-muted",blocked:"text-accent"},s={pending:"text-fg-muted",active:"text-fg",complete:"text-fg-muted",blocked:"text-accent"};function r({stages:a,label:l}){return a.length===0?null:t.jsx("ol",{className:"mt-2 flex items-baseline gap-x-2 flex-wrap","aria-label":`${l} stages`,children:a.map(e=>t.jsxs("li",{className:`text-label uppercase tracking-wider ${c[e.status]}`,title:`${e.label}: ${e.status}`,children:[t.jsx("span",{"aria-hidden":"true",children:n[e.status]})," ",t.jsx("span",{className:s[e.status],children:e.label})]},e.key))})}export{r as S}; +import{j as t}from"./index-BDHAaQRP.js";const n={pending:"·",active:"⬣",complete:"◆",blocked:"✕"},c={pending:"text-fg-faint",active:"text-fg",complete:"text-fg-muted",blocked:"text-accent"},s={pending:"text-fg-muted",active:"text-fg",complete:"text-fg-muted",blocked:"text-accent"};function r({stages:a,label:l}){return a.length===0?null:t.jsx("ol",{className:"mt-2 flex items-baseline gap-x-2 flex-wrap","aria-label":`${l} stages`,children:a.map(e=>t.jsxs("li",{className:`text-label uppercase tracking-wider ${c[e.status]}`,title:`${e.label}: ${e.status}`,children:[t.jsx("span",{"aria-hidden":"true",children:n[e.status]})," ",t.jsx("span",{className:s[e.status],children:e.label})]},e.key))})}export{r as S}; diff --git a/internal/api/dashboardspa/dist/assets/Table-BMsY9n_s.js b/internal/api/dashboardspa/dist/assets/Table-COJvPKIS.js similarity index 96% rename from internal/api/dashboardspa/dist/assets/Table-BMsY9n_s.js rename to internal/api/dashboardspa/dist/assets/Table-COJvPKIS.js index f845c395b0..43c909ab15 100644 --- a/internal/api/dashboardspa/dist/assets/Table-BMsY9n_s.js +++ b/internal/api/dashboardspa/dist/assets/Table-COJvPKIS.js @@ -1 +1 @@ -import{r as x,j as t}from"./index-DDS7Ehww.js";function y({columns:i,rows:d,rowKey:f,onRowClick:c,rowProps:h,empty:b,initialSort:g}){const[n,p]=x.useState(g??null),m=x.useMemo(()=>{if(n===null)return d;const e=i.find(r=>r.key===n.key);if(!e||!e.sortable)return d;const s=e.sortValue??(r=>String(e.render(r)??"")),a=n.dir==="asc"?1:-1;return[...d].sort((r,u)=>{const l=s(r),o=s(u);return l===o?0:l==null?-a:o==null?a:lo?a:0})},[d,i,n]),N=e=>{p(s=>s?.key!==e?{key:e,dir:"asc"}:{key:e,dir:s.dir==="asc"?"desc":"asc"})};return t.jsx("div",{className:"overflow-x-auto",children:t.jsxs("table",{className:"w-full text-body tnum",children:[t.jsx("thead",{children:t.jsx("tr",{className:"border-b border-rule text-label uppercase tracking-wider text-fg-muted",children:i.map(e=>{const s=n?.key===e.key,a=e.align==="right"?"text-right":"text-left";return t.jsx("th",{scope:"col",className:`pb-3 pr-6 font-medium select-none ${a} ${e.className??""}`,children:e.sortable?t.jsxs("button",{type:"button",onClick:()=>N(e.key),className:"inline-flex items-center gap-1 hover:text-fg transition-colors duration-150 ease-out-quart focus-mark rounded-sm",children:[e.label,s&&t.jsx("span",{"aria-hidden":!0,className:"text-accent",children:n?.dir==="asc"?"↑":"↓"})]}):e.label},e.key)})})}),t.jsx("tbody",{children:m.length===0?t.jsx("tr",{children:t.jsx("td",{colSpan:i.length,className:"py-10 text-center text-fg-muted italic",children:b??"No data"})}):m.map(e=>{const{className:s="",...a}=h?.(e)??{};return x.createElement("tr",{...a,key:f(e),onClick:c?()=>c(e):void 0,className:`border-b border-rule transition-colors duration-150 ease-out-quart ${c?"cursor-pointer hover:bg-surface-tint":""} ${s}`},i.map(r=>{const u=r.align==="right"?"text-right":"text-left";return t.jsx("td",{className:`py-3 pr-6 align-baseline ${u} ${r.className??""}`,children:r.render(e)},r.key)}))})})]})})}export{y as T}; +import{r as x,j as t}from"./index-BDHAaQRP.js";function y({columns:i,rows:d,rowKey:f,onRowClick:c,rowProps:h,empty:b,initialSort:g}){const[n,p]=x.useState(g??null),m=x.useMemo(()=>{if(n===null)return d;const e=i.find(r=>r.key===n.key);if(!e||!e.sortable)return d;const s=e.sortValue??(r=>String(e.render(r)??"")),a=n.dir==="asc"?1:-1;return[...d].sort((r,u)=>{const l=s(r),o=s(u);return l===o?0:l==null?-a:o==null?a:lo?a:0})},[d,i,n]),N=e=>{p(s=>s?.key!==e?{key:e,dir:"asc"}:{key:e,dir:s.dir==="asc"?"desc":"asc"})};return t.jsx("div",{className:"overflow-x-auto",children:t.jsxs("table",{className:"w-full text-body tnum",children:[t.jsx("thead",{children:t.jsx("tr",{className:"border-b border-rule text-label uppercase tracking-wider text-fg-muted",children:i.map(e=>{const s=n?.key===e.key,a=e.align==="right"?"text-right":"text-left";return t.jsx("th",{scope:"col",className:`pb-3 pr-6 font-medium select-none ${a} ${e.className??""}`,children:e.sortable?t.jsxs("button",{type:"button",onClick:()=>N(e.key),className:"inline-flex items-center gap-1 hover:text-fg transition-colors duration-150 ease-out-quart focus-mark rounded-sm",children:[e.label,s&&t.jsx("span",{"aria-hidden":!0,className:"text-accent",children:n?.dir==="asc"?"↑":"↓"})]}):e.label},e.key)})})}),t.jsx("tbody",{children:m.length===0?t.jsx("tr",{children:t.jsx("td",{colSpan:i.length,className:"py-10 text-center text-fg-muted italic",children:b??"No data"})}):m.map(e=>{const{className:s="",...a}=h?.(e)??{};return x.createElement("tr",{...a,key:f(e),onClick:c?()=>c(e):void 0,className:`border-b border-rule transition-colors duration-150 ease-out-quart ${c?"cursor-pointer hover:bg-surface-tint":""} ${s}`},i.map(r=>{const u=r.align==="right"?"text-right":"text-left";return t.jsx("td",{className:`py-3 pr-6 align-baseline ${u} ${r.className??""}`,children:r.render(e)},r.key)}))})})]})})}export{y as T}; diff --git a/internal/api/dashboardspa/dist/assets/agentReads-D6cjHIrb.js b/internal/api/dashboardspa/dist/assets/agentReads-BYWP7eVX.js similarity index 62% rename from internal/api/dashboardspa/dist/assets/agentReads-D6cjHIrb.js rename to internal/api/dashboardspa/dist/assets/agentReads-BYWP7eVX.js index d6a426b7ae..bdf1935613 100644 --- a/internal/api/dashboardspa/dist/assets/agentReads-D6cjHIrb.js +++ b/internal/api/dashboardspa/dist/assets/agentReads-BYWP7eVX.js @@ -1 +1 @@ -import{v as t,w as i}from"./index-DDS7Ehww.js";async function e(){const s=await t().listAgents(i("list supervisor agents"));return{...s,items:s.items??[]}}export{e as l}; +import{v as t,w as i}from"./index-BDHAaQRP.js";async function e(){const s=await t().listAgents(i("list supervisor agents"));return{...s,items:s.items??[]}}export{e as l}; diff --git a/internal/api/dashboardspa/dist/assets/constants-CQJOeNM1.js b/internal/api/dashboardspa/dist/assets/constants-D5DlRFFg.js similarity index 95% rename from internal/api/dashboardspa/dist/assets/constants-CQJOeNM1.js rename to internal/api/dashboardspa/dist/assets/constants-D5DlRFFg.js index 79598d058d..79787723be 100644 --- a/internal/api/dashboardspa/dist/assets/constants-CQJOeNM1.js +++ b/internal/api/dashboardspa/dist/assets/constants-D5DlRFFg.js @@ -1 +1 @@ -import{r as o,j as e}from"./index-DDS7Ehww.js";function m({open:s,onClose:t,title:i,caption:a,children:l,footer:n,widthClass:d="max-w-3xl"}){return o.useEffect(()=>{if(!s)return;const r=c=>{c.key==="Escape"&&t()};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[s,t]),s?e.jsx("div",{role:"dialog","aria-modal":"true",className:"fixed inset-0 z-50 flex items-start sm:items-center justify-center bg-fg/30 p-3 sm:p-6",onClick:t,children:e.jsxs("div",{className:`w-full ${d} bg-surface border border-rule rounded-md flex flex-col max-h-[90vh]`,onClick:r=>r.stopPropagation(),children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 px-5 py-4 border-b border-rule",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-title font-semibold text-fg truncate",children:i}),a&&e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-muted mt-1 truncate",children:a})]}),e.jsx("button",{type:"button",onClick:t,"aria-label":"Close",className:"text-fg-muted hover:text-fg transition-colors duration-150 ease-out-quart focus-mark text-lg leading-none px-1",children:"×"})]}),e.jsx("div",{className:"flex-1 overflow-auto p-5 text-body text-fg",children:l}),n&&e.jsx("div",{className:"border-t border-rule px-5 py-3 flex items-center justify-end gap-3",children:n})]})}):null}const u="Content is agent-generated and may contain misleading instructions.";export{m as M,u as P}; +import{r as o,j as e}from"./index-BDHAaQRP.js";function m({open:s,onClose:t,title:i,caption:a,children:l,footer:n,widthClass:d="max-w-3xl"}){return o.useEffect(()=>{if(!s)return;const r=c=>{c.key==="Escape"&&t()};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[s,t]),s?e.jsx("div",{role:"dialog","aria-modal":"true",className:"fixed inset-0 z-50 flex items-start sm:items-center justify-center bg-fg/30 p-3 sm:p-6",onClick:t,children:e.jsxs("div",{className:`w-full ${d} bg-surface border border-rule rounded-md flex flex-col max-h-[90vh]`,onClick:r=>r.stopPropagation(),children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 px-5 py-4 border-b border-rule",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-title font-semibold text-fg truncate",children:i}),a&&e.jsx("p",{className:"text-label uppercase tracking-wider text-fg-muted mt-1 truncate",children:a})]}),e.jsx("button",{type:"button",onClick:t,"aria-label":"Close",className:"text-fg-muted hover:text-fg transition-colors duration-150 ease-out-quart focus-mark text-lg leading-none px-1",children:"×"})]}),e.jsx("div",{className:"flex-1 overflow-auto p-5 text-body text-fg",children:l}),n&&e.jsx("div",{className:"border-t border-rule px-5 py-3 flex items-center justify-end gap-3",children:n})]})}):null}const u="Content is agent-generated and may contain misleading instructions.";export{m as M,u as P}; diff --git a/internal/api/dashboardspa/dist/assets/index-DDS7Ehww.js b/internal/api/dashboardspa/dist/assets/index-BDHAaQRP.js similarity index 81% rename from internal/api/dashboardspa/dist/assets/index-DDS7Ehww.js rename to internal/api/dashboardspa/dist/assets/index-BDHAaQRP.js index 378a930a7b..50f568a974 100644 --- a/internal/api/dashboardspa/dist/assets/index-DDS7Ehww.js +++ b/internal/api/dashboardspa/dist/assets/index-BDHAaQRP.js @@ -1,15 +1,15 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Activity-ByhthQ6l.js","assets/routeHighlight-B30gQO2o.js","assets/PageHeader-nOBkk_AA.js","assets/time-BVuL_AnL.js","assets/useVisibleRefresh-C8_1beQq.js","assets/Health-TkHQ7rEN.js","assets/format-fte2CeYD.js","assets/Agents-5svbkUmF.js","assets/context-window-Cu9zl36t.js","assets/projectOf-BjfQvzy4.js","assets/constants-CQJOeNM1.js","assets/SseIndicator-CPfa0oji.js","assets/LiveSessionPeek-F4FmVdxt.js","assets/Table-BMsY9n_s.js","assets/agentReads-D6cjHIrb.js","assets/AgentDetail-LPnb-I_r.js","assets/BeadDetailModal-DpGateYl.js","assets/Field-BEMyWxxD.js","assets/CockpitHome-DJOqblJc.js","assets/Beads-BdIAJPDE.js","assets/useListFilters-HxlZke6_.js","assets/Mail-BOec_zQx.js","assets/FormulaRunDetail-Cz_p7EMT.js","assets/StageLadder-BZC9xxGP.js","assets/Runs-CdFC1a5g.js"])))=>i.map(i=>d[i]); -function M2(t,r){for(var i=0;is[u]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))s(u);new MutationObserver(u=>{for(const f of u)if(f.type==="childList")for(const p of f.addedNodes)p.tagName==="LINK"&&p.rel==="modulepreload"&&s(p)}).observe(document,{childList:!0,subtree:!0});function i(u){const f={};return u.integrity&&(f.integrity=u.integrity),u.referrerPolicy&&(f.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?f.credentials="include":u.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function s(u){if(u.ep)return;u.ep=!0;const f=i(u);fetch(u.href,f)}})();function $m(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Vl={exports:{}},Yr={},Wl={exports:{}},he={};var Pf;function L2(){if(Pf)return he;Pf=1;var t=Symbol.for("react.element"),r=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),s=Symbol.for("react.strict_mode"),u=Symbol.for("react.profiler"),f=Symbol.for("react.provider"),p=Symbol.for("react.context"),v=Symbol.for("react.forward_ref"),x=Symbol.for("react.suspense"),I=Symbol.for("react.memo"),w=Symbol.for("react.lazy"),b=Symbol.iterator;function C(N){return N===null||typeof N!="object"?null:(N=b&&N[b]||N["@@iterator"],typeof N=="function"?N:null)}var O={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},L=Object.assign,W={};function D(N,F,ge){this.props=N,this.context=F,this.refs=W,this.updater=ge||O}D.prototype.isReactComponent={},D.prototype.setState=function(N,F){if(typeof N!="object"&&typeof N!="function"&&N!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,N,F,"setState")},D.prototype.forceUpdate=function(N){this.updater.enqueueForceUpdate(this,N,"forceUpdate")};function G(){}G.prototype=D.prototype;function ee(N,F,ge){this.props=N,this.context=F,this.refs=W,this.updater=ge||O}var J=ee.prototype=new G;J.constructor=ee,L(J,D.prototype),J.isPureReactComponent=!0;var H=Array.isArray,te=Object.prototype.hasOwnProperty,ue={current:null},ve={key:!0,ref:!0,__self:!0,__source:!0};function de(N,F,ge){var ye,xe={},Ie=null,Ce=null;if(F!=null)for(ye in F.ref!==void 0&&(Ce=F.ref),F.key!==void 0&&(Ie=""+F.key),F)te.call(F,ye)&&!ve.hasOwnProperty(ye)&&(xe[ye]=F[ye]);var be=arguments.length-2;if(be===1)xe.children=ge;else if(1>>1,F=X[N];if(0>>1;Nu(xe,Y))Ieu(Ce,xe)?(X[N]=Ce,X[Ie]=Y,N=Ie):(X[N]=xe,X[ye]=Y,N=ye);else if(Ieu(Ce,Y))X[N]=Ce,X[Ie]=Y,N=Ie;else break e}}return le}function u(X,le){var Y=X.sortIndex-le.sortIndex;return Y!==0?Y:X.id-le.id}if(typeof performance=="object"&&typeof performance.now=="function"){var f=performance;t.unstable_now=function(){return f.now()}}else{var p=Date,v=p.now();t.unstable_now=function(){return p.now()-v}}var x=[],I=[],w=1,b=null,C=3,O=!1,L=!1,W=!1,D=typeof setTimeout=="function"?setTimeout:null,G=typeof clearTimeout=="function"?clearTimeout:null,ee=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function J(X){for(var le=i(I);le!==null;){if(le.callback===null)s(I);else if(le.startTime<=X)s(I),le.sortIndex=le.expirationTime,r(x,le);else break;le=i(I)}}function H(X){if(W=!1,J(X),!L)if(i(x)!==null)L=!0,yt(te);else{var le=i(I);le!==null&&We(H,le.startTime-X)}}function te(X,le){L=!1,W&&(W=!1,G(de),de=-1),O=!0;var Y=C;try{for(J(le),b=i(x);b!==null&&(!(b.expirationTime>le)||X&&!Ne());){var N=b.callback;if(typeof N=="function"){b.callback=null,C=b.priorityLevel;var F=N(b.expirationTime<=le);le=t.unstable_now(),typeof F=="function"?b.callback=F:b===i(x)&&s(x),J(le)}else s(x);b=i(x)}if(b!==null)var ge=!0;else{var ye=i(I);ye!==null&&We(H,ye.startTime-le),ge=!1}return ge}finally{b=null,C=Y,O=!1}}var ue=!1,ve=null,de=-1,we=5,Se=-1;function Ne(){return!(t.unstable_now()-SeX||125N?(X.sortIndex=Y,r(I,X),i(x)===null&&X===i(I)&&(W?(G(de),de=-1):W=!0,We(H,Y-N))):(X.sortIndex=F,r(x,X),L||O||(L=!0,yt(te))),X},t.unstable_shouldYield=Ne,t.unstable_wrapCallback=function(X){var le=C;return function(){var Y=C;C=le;try{return X.apply(this,arguments)}finally{C=Y}}}})(Xl)),Xl}var Df;function V2(){return Df||(Df=1,Hl.exports=Z2()),Hl.exports}var Mf;function W2(){if(Mf)return St;Mf=1;var t=_u(),r=V2();function i(n){for(var o="https://reactjs.org/docs/error-decoder.html?invariant="+n,a=1;a"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),x=Object.prototype.hasOwnProperty,I=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,w={},b={};function C(n){return x.call(b,n)?!0:x.call(w,n)?!1:I.test(n)?b[n]=!0:(w[n]=!0,!1)}function O(n,o,a,l){if(a!==null&&a.type===0)return!1;switch(typeof o){case"function":case"symbol":return!0;case"boolean":return l?!1:a!==null?!a.acceptsBooleans:(n=n.toLowerCase().slice(0,5),n!=="data-"&&n!=="aria-");default:return!1}}function L(n,o,a,l){if(o===null||typeof o>"u"||O(n,o,a,l))return!0;if(l)return!1;if(a!==null)switch(a.type){case 3:return!o;case 4:return o===!1;case 5:return isNaN(o);case 6:return isNaN(o)||1>o}return!1}function W(n,o,a,l,d,m,_){this.acceptsBooleans=o===2||o===3||o===4,this.attributeName=l,this.attributeNamespace=d,this.mustUseProperty=a,this.propertyName=n,this.type=o,this.sanitizeURL=m,this.removeEmptyString=_}var D={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(n){D[n]=new W(n,0,!1,n,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(n){var o=n[0];D[o]=new W(o,1,!1,n[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(n){D[n]=new W(n,2,!1,n.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(n){D[n]=new W(n,2,!1,n,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(n){D[n]=new W(n,3,!1,n.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(n){D[n]=new W(n,3,!0,n,null,!1,!1)}),["capture","download"].forEach(function(n){D[n]=new W(n,4,!1,n,null,!1,!1)}),["cols","rows","size","span"].forEach(function(n){D[n]=new W(n,6,!1,n,null,!1,!1)}),["rowSpan","start"].forEach(function(n){D[n]=new W(n,5,!1,n.toLowerCase(),null,!1,!1)});var G=/[\-:]([a-z])/g;function ee(n){return n[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(n){var o=n.replace(G,ee);D[o]=new W(o,1,!1,n,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(n){var o=n.replace(G,ee);D[o]=new W(o,1,!1,n,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(n){var o=n.replace(G,ee);D[o]=new W(o,1,!1,n,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(n){D[n]=new W(n,1,!1,n.toLowerCase(),null,!1,!1)}),D.xlinkHref=new W("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(n){D[n]=new W(n,1,!1,n.toLowerCase(),null,!0,!0)});function J(n,o,a,l){var d=D.hasOwnProperty(o)?D[o]:null;(d!==null?d.type!==0:l||!(2i.map(i=>d[i]); +function M2(t,r){for(var i=0;is[u]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))s(u);new MutationObserver(u=>{for(const f of u)if(f.type==="childList")for(const p of f.addedNodes)p.tagName==="LINK"&&p.rel==="modulepreload"&&s(p)}).observe(document,{childList:!0,subtree:!0});function i(u){const f={};return u.integrity&&(f.integrity=u.integrity),u.referrerPolicy&&(f.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?f.credentials="include":u.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function s(u){if(u.ep)return;u.ep=!0;const f=i(u);fetch(u.href,f)}})();function $m(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Vl={exports:{}},Yr={},Wl={exports:{}},he={};var Pf;function L2(){if(Pf)return he;Pf=1;var t=Symbol.for("react.element"),r=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),s=Symbol.for("react.strict_mode"),u=Symbol.for("react.profiler"),f=Symbol.for("react.provider"),p=Symbol.for("react.context"),v=Symbol.for("react.forward_ref"),x=Symbol.for("react.suspense"),I=Symbol.for("react.memo"),w=Symbol.for("react.lazy"),b=Symbol.iterator;function C(N){return N===null||typeof N!="object"?null:(N=b&&N[b]||N["@@iterator"],typeof N=="function"?N:null)}var O={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},L=Object.assign,W={};function D(N,F,ge){this.props=N,this.context=F,this.refs=W,this.updater=ge||O}D.prototype.isReactComponent={},D.prototype.setState=function(N,F){if(typeof N!="object"&&typeof N!="function"&&N!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,N,F,"setState")},D.prototype.forceUpdate=function(N){this.updater.enqueueForceUpdate(this,N,"forceUpdate")};function G(){}G.prototype=D.prototype;function ee(N,F,ge){this.props=N,this.context=F,this.refs=W,this.updater=ge||O}var J=ee.prototype=new G;J.constructor=ee,L(J,D.prototype),J.isPureReactComponent=!0;var H=Array.isArray,te=Object.prototype.hasOwnProperty,ue={current:null},ve={key:!0,ref:!0,__self:!0,__source:!0};function pe(N,F,ge){var ye,xe={},Ie=null,Ce=null;if(F!=null)for(ye in F.ref!==void 0&&(Ce=F.ref),F.key!==void 0&&(Ie=""+F.key),F)te.call(F,ye)&&!ve.hasOwnProperty(ye)&&(xe[ye]=F[ye]);var be=arguments.length-2;if(be===1)xe.children=ge;else if(1>>1,F=X[N];if(0>>1;Nu(xe,Y))Ieu(Ce,xe)?(X[N]=Ce,X[Ie]=Y,N=Ie):(X[N]=xe,X[ye]=Y,N=ye);else if(Ieu(Ce,Y))X[N]=Ce,X[Ie]=Y,N=Ie;else break e}}return le}function u(X,le){var Y=X.sortIndex-le.sortIndex;return Y!==0?Y:X.id-le.id}if(typeof performance=="object"&&typeof performance.now=="function"){var f=performance;t.unstable_now=function(){return f.now()}}else{var p=Date,v=p.now();t.unstable_now=function(){return p.now()-v}}var x=[],I=[],w=1,b=null,C=3,O=!1,L=!1,W=!1,D=typeof setTimeout=="function"?setTimeout:null,G=typeof clearTimeout=="function"?clearTimeout:null,ee=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function J(X){for(var le=i(I);le!==null;){if(le.callback===null)s(I);else if(le.startTime<=X)s(I),le.sortIndex=le.expirationTime,r(x,le);else break;le=i(I)}}function H(X){if(W=!1,J(X),!L)if(i(x)!==null)L=!0,yt(te);else{var le=i(I);le!==null&&We(H,le.startTime-X)}}function te(X,le){L=!1,W&&(W=!1,G(pe),pe=-1),O=!0;var Y=C;try{for(J(le),b=i(x);b!==null&&(!(b.expirationTime>le)||X&&!Ne());){var N=b.callback;if(typeof N=="function"){b.callback=null,C=b.priorityLevel;var F=N(b.expirationTime<=le);le=t.unstable_now(),typeof F=="function"?b.callback=F:b===i(x)&&s(x),J(le)}else s(x);b=i(x)}if(b!==null)var ge=!0;else{var ye=i(I);ye!==null&&We(H,ye.startTime-le),ge=!1}return ge}finally{b=null,C=Y,O=!1}}var ue=!1,ve=null,pe=-1,we=5,Se=-1;function Ne(){return!(t.unstable_now()-SeX||125N?(X.sortIndex=Y,r(I,X),i(x)===null&&X===i(I)&&(W?(G(pe),pe=-1):W=!0,We(H,Y-N))):(X.sortIndex=F,r(x,X),L||O||(L=!0,yt(te))),X},t.unstable_shouldYield=Ne,t.unstable_wrapCallback=function(X){var le=C;return function(){var Y=C;C=le;try{return X.apply(this,arguments)}finally{C=Y}}}})(Xl)),Xl}var Df;function V2(){return Df||(Df=1,Hl.exports=Z2()),Hl.exports}var Mf;function W2(){if(Mf)return St;Mf=1;var t=_u(),r=V2();function i(n){for(var o="https://reactjs.org/docs/error-decoder.html?invariant="+n,a=1;a"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),x=Object.prototype.hasOwnProperty,I=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,w={},b={};function C(n){return x.call(b,n)?!0:x.call(w,n)?!1:I.test(n)?b[n]=!0:(w[n]=!0,!1)}function O(n,o,a,l){if(a!==null&&a.type===0)return!1;switch(typeof o){case"function":case"symbol":return!0;case"boolean":return l?!1:a!==null?!a.acceptsBooleans:(n=n.toLowerCase().slice(0,5),n!=="data-"&&n!=="aria-");default:return!1}}function L(n,o,a,l){if(o===null||typeof o>"u"||O(n,o,a,l))return!0;if(l)return!1;if(a!==null)switch(a.type){case 3:return!o;case 4:return o===!1;case 5:return isNaN(o);case 6:return isNaN(o)||1>o}return!1}function W(n,o,a,l,d,m,_){this.acceptsBooleans=o===2||o===3||o===4,this.attributeName=l,this.attributeNamespace=d,this.mustUseProperty=a,this.propertyName=n,this.type=o,this.sanitizeURL=m,this.removeEmptyString=_}var D={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(n){D[n]=new W(n,0,!1,n,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(n){var o=n[0];D[o]=new W(o,1,!1,n[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(n){D[n]=new W(n,2,!1,n.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(n){D[n]=new W(n,2,!1,n,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(n){D[n]=new W(n,3,!1,n.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(n){D[n]=new W(n,3,!0,n,null,!1,!1)}),["capture","download"].forEach(function(n){D[n]=new W(n,4,!1,n,null,!1,!1)}),["cols","rows","size","span"].forEach(function(n){D[n]=new W(n,6,!1,n,null,!1,!1)}),["rowSpan","start"].forEach(function(n){D[n]=new W(n,5,!1,n.toLowerCase(),null,!1,!1)});var G=/[\-:]([a-z])/g;function ee(n){return n[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(n){var o=n.replace(G,ee);D[o]=new W(o,1,!1,n,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(n){var o=n.replace(G,ee);D[o]=new W(o,1,!1,n,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(n){var o=n.replace(G,ee);D[o]=new W(o,1,!1,n,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(n){D[n]=new W(n,1,!1,n.toLowerCase(),null,!1,!1)}),D.xlinkHref=new W("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(n){D[n]=new W(n,1,!1,n.toLowerCase(),null,!0,!0)});function J(n,o,a,l){var d=D.hasOwnProperty(o)?D[o]:null;(d!==null?d.type!==0:l||!(2E||d[_]!==m[E]){var S=` -`+d[_].replace(" at new "," at ");return n.displayName&&S.includes("")&&(S=S.replace("",n.displayName)),S}while(1<=_&&0<=E);break}}}finally{ge=!1,Error.prepareStackTrace=a}return(n=n?n.displayName||n.name:"")?F(n):""}function xe(n){switch(n.tag){case 5:return F(n.type);case 16:return F("Lazy");case 13:return F("Suspense");case 19:return F("SuspenseList");case 0:case 2:case 15:return n=ye(n.type,!1),n;case 11:return n=ye(n.type.render,!1),n;case 1:return n=ye(n.type,!0),n;default:return""}}function Ie(n){if(n==null)return null;if(typeof n=="function")return n.displayName||n.name||null;if(typeof n=="string")return n;switch(n){case ve:return"Fragment";case ue:return"Portal";case we:return"Profiler";case de:return"StrictMode";case nt:return"Suspense";case Ye:return"SuspenseList"}if(typeof n=="object")switch(n.$$typeof){case Ne:return(n.displayName||"Context")+".Consumer";case Se:return(n._context.displayName||"Context")+".Provider";case Ae:var o=n.render;return n=n.displayName,n||(n=o.displayName||o.name||"",n=n!==""?"ForwardRef("+n+")":"ForwardRef"),n;case zt:return o=n.displayName||null,o!==null?o:Ie(n.type)||"Memo";case yt:o=n._payload,n=n._init;try{return Ie(n(o))}catch{}}return null}function Ce(n){var o=n.type;switch(n.tag){case 24:return"Cache";case 9:return(o.displayName||"Context")+".Consumer";case 10:return(o._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return n=o.render,n=n.displayName||n.name||"",o.displayName||(n!==""?"ForwardRef("+n+")":"ForwardRef");case 7:return"Fragment";case 5:return o;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Ie(o);case 8:return o===de?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof o=="function")return o.displayName||o.name||null;if(typeof o=="string")return o}return null}function be(n){switch(typeof n){case"boolean":case"number":case"string":case"undefined":return n;case"object":return n;default:return""}}function Oe(n){var o=n.type;return(n=n.nodeName)&&n.toLowerCase()==="input"&&(o==="checkbox"||o==="radio")}function Tt(n){var o=Oe(n)?"checked":"value",a=Object.getOwnPropertyDescriptor(n.constructor.prototype,o),l=""+n[o];if(!n.hasOwnProperty(o)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var d=a.get,m=a.set;return Object.defineProperty(n,o,{configurable:!0,get:function(){return d.call(this)},set:function(_){l=""+_,m.call(this,_)}}),Object.defineProperty(n,o,{enumerable:a.enumerable}),{getValue:function(){return l},setValue:function(_){l=""+_},stopTracking:function(){n._valueTracker=null,delete n[o]}}}}function vi(n){n._valueTracker||(n._valueTracker=Tt(n))}function Dc(n){if(!n)return!1;var o=n._valueTracker;if(!o)return!0;var a=o.getValue(),l="";return n&&(l=Oe(n)?n.checked?"true":"false":n.value),n=l,n!==a?(o.setValue(n),!0):!1}function gi(n){if(n=n||(typeof document<"u"?document:void 0),typeof n>"u")return null;try{return n.activeElement||n.body}catch{return n.body}}function Qa(n,o){var a=o.checked;return Y({},o,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:a??n._wrapperState.initialChecked})}function Mc(n,o){var a=o.defaultValue==null?"":o.defaultValue,l=o.checked!=null?o.checked:o.defaultChecked;a=be(o.value!=null?o.value:a),n._wrapperState={initialChecked:l,initialValue:a,controlled:o.type==="checkbox"||o.type==="radio"?o.checked!=null:o.value!=null}}function Lc(n,o){o=o.checked,o!=null&&J(n,"checked",o,!1)}function Ya(n,o){Lc(n,o);var a=be(o.value),l=o.type;if(a!=null)l==="number"?(a===0&&n.value===""||n.value!=a)&&(n.value=""+a):n.value!==""+a&&(n.value=""+a);else if(l==="submit"||l==="reset"){n.removeAttribute("value");return}o.hasOwnProperty("value")?es(n,o.type,a):o.hasOwnProperty("defaultValue")&&es(n,o.type,be(o.defaultValue)),o.checked==null&&o.defaultChecked!=null&&(n.defaultChecked=!!o.defaultChecked)}function qc(n,o,a){if(o.hasOwnProperty("value")||o.hasOwnProperty("defaultValue")){var l=o.type;if(!(l!=="submit"&&l!=="reset"||o.value!==void 0&&o.value!==null))return;o=""+n._wrapperState.initialValue,a||o===n.value||(n.value=o),n.defaultValue=o}a=n.name,a!==""&&(n.name=""),n.defaultChecked=!!n._wrapperState.initialChecked,a!==""&&(n.name=a)}function es(n,o,a){(o!=="number"||gi(n.ownerDocument)!==n)&&(a==null?n.defaultValue=""+n._wrapperState.initialValue:n.defaultValue!==""+a&&(n.defaultValue=""+a))}var mr=Array.isArray;function ko(n,o,a,l){if(n=n.options,o){o={};for(var d=0;d"+o.valueOf().toString()+"",o=hi.firstChild;n.firstChild;)n.removeChild(n.firstChild);for(;o.firstChild;)n.appendChild(o.firstChild)}});function vr(n,o){if(o){var a=n.firstChild;if(a&&a===n.lastChild&&a.nodeType===3){a.nodeValue=o;return}}n.textContent=o}var gr={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Uv=["Webkit","ms","Moz","O"];Object.keys(gr).forEach(function(n){Uv.forEach(function(o){o=o+n.charAt(0).toUpperCase()+n.substring(1),gr[o]=gr[n]})});function Gc(n,o,a){return o==null||typeof o=="boolean"||o===""?"":a||typeof o!="number"||o===0||gr.hasOwnProperty(n)&&gr[n]?(""+o).trim():o+"px"}function Hc(n,o){n=n.style;for(var a in o)if(o.hasOwnProperty(a)){var l=a.indexOf("--")===0,d=Gc(a,o[a],l);a==="float"&&(a="cssFloat"),l?n.setProperty(a,d):n[a]=d}}var Zv=Y({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function os(n,o){if(o){if(Zv[n]&&(o.children!=null||o.dangerouslySetInnerHTML!=null))throw Error(i(137,n));if(o.dangerouslySetInnerHTML!=null){if(o.children!=null)throw Error(i(60));if(typeof o.dangerouslySetInnerHTML!="object"||!("__html"in o.dangerouslySetInnerHTML))throw Error(i(61))}if(o.style!=null&&typeof o.style!="object")throw Error(i(62))}}function rs(n,o){if(n.indexOf("-")===-1)return typeof o.is=="string";switch(n){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var is=null;function as(n){return n=n.target||n.srcElement||window,n.correspondingUseElement&&(n=n.correspondingUseElement),n.nodeType===3?n.parentNode:n}var ss=null,Bo=null,zo=null;function Xc(n){if(n=Dr(n)){if(typeof ss!="function")throw Error(i(280));var o=n.stateNode;o&&(o=Li(o),ss(n.stateNode,n.type,o))}}function Kc(n){Bo?zo?zo.push(n):zo=[n]:Bo=n}function Jc(){if(Bo){var n=Bo,o=zo;if(zo=Bo=null,Xc(n),o)for(n=0;n>>=0,n===0?32:31-(tg(n)/ng|0)|0}var Ei=64,wi=4194304;function xr(n){switch(n&-n){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return n&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return n}}function Si(n,o){var a=n.pendingLanes;if(a===0)return 0;var l=0,d=n.suspendedLanes,m=n.pingedLanes,_=a&268435455;if(_!==0){var E=_&~d;E!==0?l=xr(E):(m&=_,m!==0&&(l=xr(m)))}else _=a&~d,_!==0?l=xr(_):m!==0&&(l=xr(m));if(l===0)return 0;if(o!==0&&o!==l&&(o&d)===0&&(d=l&-l,m=o&-o,d>=m||d===16&&(m&4194240)!==0))return o;if((l&4)!==0&&(l|=a&16),o=n.entangledLanes,o!==0)for(n=n.entanglements,o&=l;0a;a++)o.push(n);return o}function Ir(n,o,a){n.pendingLanes|=o,o!==536870912&&(n.suspendedLanes=0,n.pingedLanes=0),n=n.eventTimes,o=31-Ft(o),n[o]=a}function ag(n,o){var a=n.pendingLanes&~o;n.pendingLanes=o,n.suspendedLanes=0,n.pingedLanes=0,n.expiredLanes&=o,n.mutableReadLanes&=o,n.entangledLanes&=o,o=n.entanglements;var l=n.eventTimes;for(n=n.expirationTimes;0=Tr),bd=" ",kd=!1;function Bd(n,o){switch(n){case"keyup":return jg.indexOf(o.keyCode)!==-1;case"keydown":return o.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function zd(n){return n=n.detail,typeof n=="object"&&"data"in n?n.data:null}var Ro=!1;function Og(n,o){switch(n){case"compositionend":return zd(o);case"keypress":return o.which!==32?null:(kd=!0,bd);case"textInput":return n=o.data,n===bd&&kd?null:n;default:return null}}function $g(n,o){if(Ro)return n==="compositionend"||!bs&&Bd(n,o)?(n=_d(),Ti=_s=On=null,Ro=!1,n):null;switch(n){case"paste":return null;case"keypress":if(!(o.ctrlKey||o.altKey||o.metaKey)||o.ctrlKey&&o.altKey){if(o.char&&1=o)return{node:a,offset:o-n};n=l}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=Ad(a)}}function $d(n,o){return n&&o?n===o?!0:n&&n.nodeType===3?!1:o&&o.nodeType===3?$d(n,o.parentNode):"contains"in n?n.contains(o):n.compareDocumentPosition?!!(n.compareDocumentPosition(o)&16):!1:!1}function Dd(){for(var n=window,o=gi();o instanceof n.HTMLIFrameElement;){try{var a=typeof o.contentWindow.location.href=="string"}catch{a=!1}if(a)n=o.contentWindow;else break;o=gi(n.document)}return o}function zs(n){var o=n&&n.nodeName&&n.nodeName.toLowerCase();return o&&(o==="input"&&(n.type==="text"||n.type==="search"||n.type==="tel"||n.type==="url"||n.type==="password")||o==="textarea"||n.contentEditable==="true")}function Wg(n){var o=Dd(),a=n.focusedElem,l=n.selectionRange;if(o!==a&&a&&a.ownerDocument&&$d(a.ownerDocument.documentElement,a)){if(l!==null&&zs(a)){if(o=l.start,n=l.end,n===void 0&&(n=o),"selectionStart"in a)a.selectionStart=o,a.selectionEnd=Math.min(n,a.value.length);else if(n=(o=a.ownerDocument||document)&&o.defaultView||window,n.getSelection){n=n.getSelection();var d=a.textContent.length,m=Math.min(l.start,d);l=l.end===void 0?m:Math.min(l.end,d),!n.extend&&m>l&&(d=l,l=m,m=d),d=Od(a,m);var _=Od(a,l);d&&_&&(n.rangeCount!==1||n.anchorNode!==d.node||n.anchorOffset!==d.offset||n.focusNode!==_.node||n.focusOffset!==_.offset)&&(o=o.createRange(),o.setStart(d.node,d.offset),n.removeAllRanges(),m>l?(n.addRange(o),n.extend(_.node,_.offset)):(o.setEnd(_.node,_.offset),n.addRange(o)))}}for(o=[],n=a;n=n.parentNode;)n.nodeType===1&&o.push({element:n,left:n.scrollLeft,top:n.scrollTop});for(typeof a.focus=="function"&&a.focus(),a=0;a=document.documentMode,No=null,Ts=null,Pr=null,Cs=!1;function Md(n,o,a){var l=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;Cs||No==null||No!==gi(l)||(l=No,"selectionStart"in l&&zs(l)?l={start:l.selectionStart,end:l.selectionEnd}:(l=(l.ownerDocument&&l.ownerDocument.defaultView||window).getSelection(),l={anchorNode:l.anchorNode,anchorOffset:l.anchorOffset,focusNode:l.focusNode,focusOffset:l.focusOffset}),Pr&&Nr(Pr,l)||(Pr=l,l=$i(Ts,"onSelect"),0")&&(S=S.replace("",n.displayName)),S}while(1<=_&&0<=E);break}}}finally{ge=!1,Error.prepareStackTrace=a}return(n=n?n.displayName||n.name:"")?F(n):""}function xe(n){switch(n.tag){case 5:return F(n.type);case 16:return F("Lazy");case 13:return F("Suspense");case 19:return F("SuspenseList");case 0:case 2:case 15:return n=ye(n.type,!1),n;case 11:return n=ye(n.type.render,!1),n;case 1:return n=ye(n.type,!0),n;default:return""}}function Ie(n){if(n==null)return null;if(typeof n=="function")return n.displayName||n.name||null;if(typeof n=="string")return n;switch(n){case ve:return"Fragment";case ue:return"Portal";case we:return"Profiler";case pe:return"StrictMode";case nt:return"Suspense";case Ye:return"SuspenseList"}if(typeof n=="object")switch(n.$$typeof){case Ne:return(n.displayName||"Context")+".Consumer";case Se:return(n._context.displayName||"Context")+".Provider";case Ae:var o=n.render;return n=n.displayName,n||(n=o.displayName||o.name||"",n=n!==""?"ForwardRef("+n+")":"ForwardRef"),n;case zt:return o=n.displayName||null,o!==null?o:Ie(n.type)||"Memo";case yt:o=n._payload,n=n._init;try{return Ie(n(o))}catch{}}return null}function Ce(n){var o=n.type;switch(n.tag){case 24:return"Cache";case 9:return(o.displayName||"Context")+".Consumer";case 10:return(o._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return n=o.render,n=n.displayName||n.name||"",o.displayName||(n!==""?"ForwardRef("+n+")":"ForwardRef");case 7:return"Fragment";case 5:return o;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Ie(o);case 8:return o===pe?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof o=="function")return o.displayName||o.name||null;if(typeof o=="string")return o}return null}function be(n){switch(typeof n){case"boolean":case"number":case"string":case"undefined":return n;case"object":return n;default:return""}}function Oe(n){var o=n.type;return(n=n.nodeName)&&n.toLowerCase()==="input"&&(o==="checkbox"||o==="radio")}function Tt(n){var o=Oe(n)?"checked":"value",a=Object.getOwnPropertyDescriptor(n.constructor.prototype,o),l=""+n[o];if(!n.hasOwnProperty(o)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var d=a.get,m=a.set;return Object.defineProperty(n,o,{configurable:!0,get:function(){return d.call(this)},set:function(_){l=""+_,m.call(this,_)}}),Object.defineProperty(n,o,{enumerable:a.enumerable}),{getValue:function(){return l},setValue:function(_){l=""+_},stopTracking:function(){n._valueTracker=null,delete n[o]}}}}function vi(n){n._valueTracker||(n._valueTracker=Tt(n))}function Dc(n){if(!n)return!1;var o=n._valueTracker;if(!o)return!0;var a=o.getValue(),l="";return n&&(l=Oe(n)?n.checked?"true":"false":n.value),n=l,n!==a?(o.setValue(n),!0):!1}function gi(n){if(n=n||(typeof document<"u"?document:void 0),typeof n>"u")return null;try{return n.activeElement||n.body}catch{return n.body}}function Qa(n,o){var a=o.checked;return Y({},o,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:a??n._wrapperState.initialChecked})}function Mc(n,o){var a=o.defaultValue==null?"":o.defaultValue,l=o.checked!=null?o.checked:o.defaultChecked;a=be(o.value!=null?o.value:a),n._wrapperState={initialChecked:l,initialValue:a,controlled:o.type==="checkbox"||o.type==="radio"?o.checked!=null:o.value!=null}}function Lc(n,o){o=o.checked,o!=null&&J(n,"checked",o,!1)}function Ya(n,o){Lc(n,o);var a=be(o.value),l=o.type;if(a!=null)l==="number"?(a===0&&n.value===""||n.value!=a)&&(n.value=""+a):n.value!==""+a&&(n.value=""+a);else if(l==="submit"||l==="reset"){n.removeAttribute("value");return}o.hasOwnProperty("value")?es(n,o.type,a):o.hasOwnProperty("defaultValue")&&es(n,o.type,be(o.defaultValue)),o.checked==null&&o.defaultChecked!=null&&(n.defaultChecked=!!o.defaultChecked)}function qc(n,o,a){if(o.hasOwnProperty("value")||o.hasOwnProperty("defaultValue")){var l=o.type;if(!(l!=="submit"&&l!=="reset"||o.value!==void 0&&o.value!==null))return;o=""+n._wrapperState.initialValue,a||o===n.value||(n.value=o),n.defaultValue=o}a=n.name,a!==""&&(n.name=""),n.defaultChecked=!!n._wrapperState.initialChecked,a!==""&&(n.name=a)}function es(n,o,a){(o!=="number"||gi(n.ownerDocument)!==n)&&(a==null?n.defaultValue=""+n._wrapperState.initialValue:n.defaultValue!==""+a&&(n.defaultValue=""+a))}var mr=Array.isArray;function ko(n,o,a,l){if(n=n.options,o){o={};for(var d=0;d"+o.valueOf().toString()+"",o=hi.firstChild;n.firstChild;)n.removeChild(n.firstChild);for(;o.firstChild;)n.appendChild(o.firstChild)}});function vr(n,o){if(o){var a=n.firstChild;if(a&&a===n.lastChild&&a.nodeType===3){a.nodeValue=o;return}}n.textContent=o}var gr={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Uv=["Webkit","ms","Moz","O"];Object.keys(gr).forEach(function(n){Uv.forEach(function(o){o=o+n.charAt(0).toUpperCase()+n.substring(1),gr[o]=gr[n]})});function Gc(n,o,a){return o==null||typeof o=="boolean"||o===""?"":a||typeof o!="number"||o===0||gr.hasOwnProperty(n)&&gr[n]?(""+o).trim():o+"px"}function Hc(n,o){n=n.style;for(var a in o)if(o.hasOwnProperty(a)){var l=a.indexOf("--")===0,d=Gc(a,o[a],l);a==="float"&&(a="cssFloat"),l?n.setProperty(a,d):n[a]=d}}var Zv=Y({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function os(n,o){if(o){if(Zv[n]&&(o.children!=null||o.dangerouslySetInnerHTML!=null))throw Error(i(137,n));if(o.dangerouslySetInnerHTML!=null){if(o.children!=null)throw Error(i(60));if(typeof o.dangerouslySetInnerHTML!="object"||!("__html"in o.dangerouslySetInnerHTML))throw Error(i(61))}if(o.style!=null&&typeof o.style!="object")throw Error(i(62))}}function rs(n,o){if(n.indexOf("-")===-1)return typeof o.is=="string";switch(n){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var is=null;function as(n){return n=n.target||n.srcElement||window,n.correspondingUseElement&&(n=n.correspondingUseElement),n.nodeType===3?n.parentNode:n}var ss=null,Bo=null,zo=null;function Xc(n){if(n=Dr(n)){if(typeof ss!="function")throw Error(i(280));var o=n.stateNode;o&&(o=Li(o),ss(n.stateNode,n.type,o))}}function Kc(n){Bo?zo?zo.push(n):zo=[n]:Bo=n}function Jc(){if(Bo){var n=Bo,o=zo;if(zo=Bo=null,Xc(n),o)for(n=0;n>>=0,n===0?32:31-(tg(n)/ng|0)|0}var Ei=64,wi=4194304;function xr(n){switch(n&-n){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return n&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return n}}function Si(n,o){var a=n.pendingLanes;if(a===0)return 0;var l=0,d=n.suspendedLanes,m=n.pingedLanes,_=a&268435455;if(_!==0){var E=_&~d;E!==0?l=xr(E):(m&=_,m!==0&&(l=xr(m)))}else _=a&~d,_!==0?l=xr(_):m!==0&&(l=xr(m));if(l===0)return 0;if(o!==0&&o!==l&&(o&d)===0&&(d=l&-l,m=o&-o,d>=m||d===16&&(m&4194240)!==0))return o;if((l&4)!==0&&(l|=a&16),o=n.entangledLanes,o!==0)for(n=n.entanglements,o&=l;0a;a++)o.push(n);return o}function Ir(n,o,a){n.pendingLanes|=o,o!==536870912&&(n.suspendedLanes=0,n.pingedLanes=0),n=n.eventTimes,o=31-Ft(o),n[o]=a}function ag(n,o){var a=n.pendingLanes&~o;n.pendingLanes=o,n.suspendedLanes=0,n.pingedLanes=0,n.expiredLanes&=o,n.mutableReadLanes&=o,n.entangledLanes&=o,o=n.entanglements;var l=n.eventTimes;for(n=n.expirationTimes;0=Tr),bd=" ",kd=!1;function Bd(n,o){switch(n){case"keyup":return jg.indexOf(o.keyCode)!==-1;case"keydown":return o.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function zd(n){return n=n.detail,typeof n=="object"&&"data"in n?n.data:null}var Ro=!1;function Og(n,o){switch(n){case"compositionend":return zd(o);case"keypress":return o.which!==32?null:(kd=!0,bd);case"textInput":return n=o.data,n===bd&&kd?null:n;default:return null}}function $g(n,o){if(Ro)return n==="compositionend"||!bs&&Bd(n,o)?(n=_d(),Ti=_s=On=null,Ro=!1,n):null;switch(n){case"paste":return null;case"keypress":if(!(o.ctrlKey||o.altKey||o.metaKey)||o.ctrlKey&&o.altKey){if(o.char&&1=o)return{node:a,offset:o-n};n=l}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=Ad(a)}}function $d(n,o){return n&&o?n===o?!0:n&&n.nodeType===3?!1:o&&o.nodeType===3?$d(n,o.parentNode):"contains"in n?n.contains(o):n.compareDocumentPosition?!!(n.compareDocumentPosition(o)&16):!1:!1}function Dd(){for(var n=window,o=gi();o instanceof n.HTMLIFrameElement;){try{var a=typeof o.contentWindow.location.href=="string"}catch{a=!1}if(a)n=o.contentWindow;else break;o=gi(n.document)}return o}function zs(n){var o=n&&n.nodeName&&n.nodeName.toLowerCase();return o&&(o==="input"&&(n.type==="text"||n.type==="search"||n.type==="tel"||n.type==="url"||n.type==="password")||o==="textarea"||n.contentEditable==="true")}function Wg(n){var o=Dd(),a=n.focusedElem,l=n.selectionRange;if(o!==a&&a&&a.ownerDocument&&$d(a.ownerDocument.documentElement,a)){if(l!==null&&zs(a)){if(o=l.start,n=l.end,n===void 0&&(n=o),"selectionStart"in a)a.selectionStart=o,a.selectionEnd=Math.min(n,a.value.length);else if(n=(o=a.ownerDocument||document)&&o.defaultView||window,n.getSelection){n=n.getSelection();var d=a.textContent.length,m=Math.min(l.start,d);l=l.end===void 0?m:Math.min(l.end,d),!n.extend&&m>l&&(d=l,l=m,m=d),d=Od(a,m);var _=Od(a,l);d&&_&&(n.rangeCount!==1||n.anchorNode!==d.node||n.anchorOffset!==d.offset||n.focusNode!==_.node||n.focusOffset!==_.offset)&&(o=o.createRange(),o.setStart(d.node,d.offset),n.removeAllRanges(),m>l?(n.addRange(o),n.extend(_.node,_.offset)):(o.setEnd(_.node,_.offset),n.addRange(o)))}}for(o=[],n=a;n=n.parentNode;)n.nodeType===1&&o.push({element:n,left:n.scrollLeft,top:n.scrollTop});for(typeof a.focus=="function"&&a.focus(),a=0;a=document.documentMode,No=null,Ts=null,Pr=null,Cs=!1;function Md(n,o,a){var l=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;Cs||No==null||No!==gi(l)||(l=No,"selectionStart"in l&&zs(l)?l={start:l.selectionStart,end:l.selectionEnd}:(l=(l.ownerDocument&&l.ownerDocument.defaultView||window).getSelection(),l={anchorNode:l.anchorNode,anchorOffset:l.anchorOffset,focusNode:l.focusNode,focusOffset:l.focusOffset}),Pr&&Nr(Pr,l)||(Pr=l,l=$i(Ts,"onSelect"),0$o||(n.current=Fs[$o],Fs[$o]=null,$o--)}function Re(n,o){$o++,Fs[$o]=n.current,n.current=o}var Ln={},lt=Mn(Ln),_t=Mn(!1),so=Ln;function Do(n,o){var a=n.type.contextTypes;if(!a)return Ln;var l=n.stateNode;if(l&&l.__reactInternalMemoizedUnmaskedChildContext===o)return l.__reactInternalMemoizedMaskedChildContext;var d={},m;for(m in a)d[m]=o[m];return l&&(n=n.stateNode,n.__reactInternalMemoizedUnmaskedChildContext=o,n.__reactInternalMemoizedMaskedChildContext=d),d}function xt(n){return n=n.childContextTypes,n!=null}function qi(){je(_t),je(lt)}function ep(n,o,a){if(lt.current!==Ln)throw Error(i(168));Re(lt,o),Re(_t,a)}function tp(n,o,a){var l=n.stateNode;if(o=o.childContextTypes,typeof l.getChildContext!="function")return a;l=l.getChildContext();for(var d in l)if(!(d in o))throw Error(i(108,Ce(n)||"Unknown",d));return Y({},a,l)}function Fi(n){return n=(n=n.stateNode)&&n.__reactInternalMemoizedMergedChildContext||Ln,so=lt.current,Re(lt,n),Re(_t,_t.current),!0}function np(n,o,a){var l=n.stateNode;if(!l)throw Error(i(169));a?(n=tp(n,o,so),l.__reactInternalMemoizedMergedChildContext=n,je(_t),je(lt),Re(lt,n)):je(_t),Re(_t,a)}var vn=null,Ui=!1,Us=!1;function op(n){vn===null?vn=[n]:vn.push(n)}function r2(n){Ui=!0,op(n)}function qn(){if(!Us&&vn!==null){Us=!0;var n=0,o=ke;try{var a=vn;for(ke=1;n>=_,d-=_,gn=1<<32-Ft(o)+d|a<ce?(it=se,se=null):it=se.sibling;var Ee=q(P,se,j[ce],V);if(Ee===null){se===null&&(se=it);break}n&&se&&Ee.alternate===null&&o(P,se),B=m(Ee,B,ce),ae===null?re=Ee:ae.sibling=Ee,ae=Ee,se=it}if(ce===j.length)return a(P,se),$e&&uo(P,ce),re;if(se===null){for(;cece?(it=se,se=null):it=se.sibling;var Kn=q(P,se,Ee.value,V);if(Kn===null){se===null&&(se=it);break}n&&se&&Kn.alternate===null&&o(P,se),B=m(Kn,B,ce),ae===null?re=Kn:ae.sibling=Kn,ae=Kn,se=it}if(Ee.done)return a(P,se),$e&&uo(P,ce),re;if(se===null){for(;!Ee.done;ce++,Ee=j.next())Ee=Z(P,Ee.value,V),Ee!==null&&(B=m(Ee,B,ce),ae===null?re=Ee:ae.sibling=Ee,ae=Ee);return $e&&uo(P,ce),re}for(se=l(P,se);!Ee.done;ce++,Ee=j.next())Ee=K(se,P,ce,Ee.value,V),Ee!==null&&(n&&Ee.alternate!==null&&se.delete(Ee.key===null?ce:Ee.key),B=m(Ee,B,ce),ae===null?re=Ee:ae.sibling=Ee,ae=Ee);return n&&se.forEach(function(D2){return o(P,D2)}),$e&&uo(P,ce),re}function Xe(P,B,j,V){if(typeof j=="object"&&j!==null&&j.type===ve&&j.key===null&&(j=j.props.children),typeof j=="object"&&j!==null){switch(j.$$typeof){case te:e:{for(var re=j.key,ae=B;ae!==null;){if(ae.key===re){if(re=j.type,re===ve){if(ae.tag===7){a(P,ae.sibling),B=d(ae,j.props.children),B.return=P,P=B;break e}}else if(ae.elementType===re||typeof re=="object"&&re!==null&&re.$$typeof===yt&&up(re)===ae.type){a(P,ae.sibling),B=d(ae,j.props),B.ref=Mr(P,ae,j),B.return=P,P=B;break e}a(P,ae);break}else o(P,ae);ae=ae.sibling}j.type===ve?(B=yo(j.props.children,P.mode,V,j.key),B.return=P,P=B):(V=ha(j.type,j.key,j.props,null,P.mode,V),V.ref=Mr(P,B,j),V.return=P,P=V)}return _(P);case ue:e:{for(ae=j.key;B!==null;){if(B.key===ae)if(B.tag===4&&B.stateNode.containerInfo===j.containerInfo&&B.stateNode.implementation===j.implementation){a(P,B.sibling),B=d(B,j.children||[]),B.return=P,P=B;break e}else{a(P,B);break}else o(P,B);B=B.sibling}B=Ll(j,P.mode,V),B.return=P,P=B}return _(P);case yt:return ae=j._init,Xe(P,B,ae(j._payload),V)}if(mr(j))return ne(P,B,j,V);if(le(j))return oe(P,B,j,V);Gi(P,j)}return typeof j=="string"&&j!==""||typeof j=="number"?(j=""+j,B!==null&&B.tag===6?(a(P,B.sibling),B=d(B,j),B.return=P,P=B):(a(P,B),B=Ml(j,P.mode,V),B.return=P,P=B),_(P)):a(P,B)}return Xe}var Fo=cp(!0),dp=cp(!1),Hi=Mn(null),Xi=null,Uo=null,Xs=null;function Ks(){Xs=Uo=Xi=null}function Js(n){var o=Hi.current;je(Hi),n._currentValue=o}function Qs(n,o,a){for(;n!==null;){var l=n.alternate;if((n.childLanes&o)!==o?(n.childLanes|=o,l!==null&&(l.childLanes|=o)):l!==null&&(l.childLanes&o)!==o&&(l.childLanes|=o),n===a)break;n=n.return}}function Zo(n,o){Xi=n,Xs=Uo=null,n=n.dependencies,n!==null&&n.firstContext!==null&&((n.lanes&o)!==0&&(It=!0),n.firstContext=null)}function Ot(n){var o=n._currentValue;if(Xs!==n)if(n={context:n,memoizedValue:o,next:null},Uo===null){if(Xi===null)throw Error(i(308));Uo=n,Xi.dependencies={lanes:0,firstContext:n}}else Uo=Uo.next=n;return o}var co=null;function Ys(n){co===null?co=[n]:co.push(n)}function pp(n,o,a,l){var d=o.interleaved;return d===null?(a.next=a,Ys(o)):(a.next=d.next,d.next=a),o.interleaved=a,yn(n,l)}function yn(n,o){n.lanes|=o;var a=n.alternate;for(a!==null&&(a.lanes|=o),a=n,n=n.return;n!==null;)n.childLanes|=o,a=n.alternate,a!==null&&(a.childLanes|=o),a=n,n=n.return;return a.tag===3?a.stateNode:null}var Fn=!1;function el(n){n.updateQueue={baseState:n.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function fp(n,o){n=n.updateQueue,o.updateQueue===n&&(o.updateQueue={baseState:n.baseState,firstBaseUpdate:n.firstBaseUpdate,lastBaseUpdate:n.lastBaseUpdate,shared:n.shared,effects:n.effects})}function _n(n,o){return{eventTime:n,lane:o,tag:0,payload:null,callback:null,next:null}}function Un(n,o,a){var l=n.updateQueue;if(l===null)return null;if(l=l.shared,(_e&2)!==0){var d=l.pending;return d===null?o.next=o:(o.next=d.next,d.next=o),l.pending=o,yn(n,a)}return d=l.interleaved,d===null?(o.next=o,Ys(l)):(o.next=d.next,d.next=o),l.interleaved=o,yn(n,a)}function Ki(n,o,a){if(o=o.updateQueue,o!==null&&(o=o.shared,(a&4194240)!==0)){var l=o.lanes;l&=n.pendingLanes,a|=l,o.lanes=a,ms(n,a)}}function mp(n,o){var a=n.updateQueue,l=n.alternate;if(l!==null&&(l=l.updateQueue,a===l)){var d=null,m=null;if(a=a.firstBaseUpdate,a!==null){do{var _={eventTime:a.eventTime,lane:a.lane,tag:a.tag,payload:a.payload,callback:a.callback,next:null};m===null?d=m=_:m=m.next=_,a=a.next}while(a!==null);m===null?d=m=o:m=m.next=o}else d=m=o;a={baseState:l.baseState,firstBaseUpdate:d,lastBaseUpdate:m,shared:l.shared,effects:l.effects},n.updateQueue=a;return}n=a.lastBaseUpdate,n===null?a.firstBaseUpdate=o:n.next=o,a.lastBaseUpdate=o}function Ji(n,o,a,l){var d=n.updateQueue;Fn=!1;var m=d.firstBaseUpdate,_=d.lastBaseUpdate,E=d.shared.pending;if(E!==null){d.shared.pending=null;var S=E,A=S.next;S.next=null,_===null?m=A:_.next=A,_=S;var U=n.alternate;U!==null&&(U=U.updateQueue,E=U.lastBaseUpdate,E!==_&&(E===null?U.firstBaseUpdate=A:E.next=A,U.lastBaseUpdate=S))}if(m!==null){var Z=d.baseState;_=0,U=A=S=null,E=m;do{var q=E.lane,K=E.eventTime;if((l&q)===q){U!==null&&(U=U.next={eventTime:K,lane:0,tag:E.tag,payload:E.payload,callback:E.callback,next:null});e:{var ne=n,oe=E;switch(q=o,K=a,oe.tag){case 1:if(ne=oe.payload,typeof ne=="function"){Z=ne.call(K,Z,q);break e}Z=ne;break e;case 3:ne.flags=ne.flags&-65537|128;case 0:if(ne=oe.payload,q=typeof ne=="function"?ne.call(K,Z,q):ne,q==null)break e;Z=Y({},Z,q);break e;case 2:Fn=!0}}E.callback!==null&&E.lane!==0&&(n.flags|=64,q=d.effects,q===null?d.effects=[E]:q.push(E))}else K={eventTime:K,lane:q,tag:E.tag,payload:E.payload,callback:E.callback,next:null},U===null?(A=U=K,S=Z):U=U.next=K,_|=q;if(E=E.next,E===null){if(E=d.shared.pending,E===null)break;q=E,E=q.next,q.next=null,d.lastBaseUpdate=q,d.shared.pending=null}}while(!0);if(U===null&&(S=Z),d.baseState=S,d.firstBaseUpdate=A,d.lastBaseUpdate=U,o=d.shared.interleaved,o!==null){d=o;do _|=d.lane,d=d.next;while(d!==o)}else m===null&&(d.shared.lanes=0);mo|=_,n.lanes=_,n.memoizedState=Z}}function vp(n,o,a){if(n=o.effects,o.effects=null,n!==null)for(o=0;oa?a:4,n(!0);var l=il.transition;il.transition={};try{n(!1),o()}finally{ke=a,il.transition=l}}function jp(){return $t().memoizedState}function l2(n,o,a){var l=Gn(n);if(a={lane:l,action:a,hasEagerState:!1,eagerState:null,next:null},Ap(n))Op(o,a);else if(a=pp(n,o,a,l),a!==null){var d=vt();Ht(a,n,l,d),$p(a,o,l)}}function u2(n,o,a){var l=Gn(n),d={lane:l,action:a,hasEagerState:!1,eagerState:null,next:null};if(Ap(n))Op(o,d);else{var m=n.alternate;if(n.lanes===0&&(m===null||m.lanes===0)&&(m=o.lastRenderedReducer,m!==null))try{var _=o.lastRenderedState,E=m(_,a);if(d.hasEagerState=!0,d.eagerState=E,Ut(E,_)){var S=o.interleaved;S===null?(d.next=d,Ys(o)):(d.next=S.next,S.next=d),o.interleaved=d;return}}catch{}a=pp(n,o,d,l),a!==null&&(d=vt(),Ht(a,n,l,d),$p(a,o,l))}}function Ap(n){var o=n.alternate;return n===Fe||o!==null&&o===Fe}function Op(n,o){Ur=ea=!0;var a=n.pending;a===null?o.next=o:(o.next=a.next,a.next=o),n.pending=o}function $p(n,o,a){if((a&4194240)!==0){var l=o.lanes;l&=n.pendingLanes,a|=l,o.lanes=a,ms(n,a)}}var oa={readContext:Ot,useCallback:ut,useContext:ut,useEffect:ut,useImperativeHandle:ut,useInsertionEffect:ut,useLayoutEffect:ut,useMemo:ut,useReducer:ut,useRef:ut,useState:ut,useDebugValue:ut,useDeferredValue:ut,useTransition:ut,useMutableSource:ut,useSyncExternalStore:ut,useId:ut,unstable_isNewReconciler:!1},c2={readContext:Ot,useCallback:function(n,o){return on().memoizedState=[n,o===void 0?null:o],n},useContext:Ot,useEffect:kp,useImperativeHandle:function(n,o,a){return a=a!=null?a.concat([n]):null,ta(4194308,4,Tp.bind(null,o,n),a)},useLayoutEffect:function(n,o){return ta(4194308,4,n,o)},useInsertionEffect:function(n,o){return ta(4,2,n,o)},useMemo:function(n,o){var a=on();return o=o===void 0?null:o,n=n(),a.memoizedState=[n,o],n},useReducer:function(n,o,a){var l=on();return o=a!==void 0?a(o):o,l.memoizedState=l.baseState=o,n={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:n,lastRenderedState:o},l.queue=n,n=n.dispatch=l2.bind(null,Fe,n),[l.memoizedState,n]},useRef:function(n){var o=on();return n={current:n},o.memoizedState=n},useState:Sp,useDebugValue:pl,useDeferredValue:function(n){return on().memoizedState=n},useTransition:function(){var n=Sp(!1),o=n[0];return n=s2.bind(null,n[1]),on().memoizedState=n,[o,n]},useMutableSource:function(){},useSyncExternalStore:function(n,o,a){var l=Fe,d=on();if($e){if(a===void 0)throw Error(i(407));a=a()}else{if(a=o(),rt===null)throw Error(i(349));(fo&30)!==0||_p(l,o,a)}d.memoizedState=a;var m={value:a,getSnapshot:o};return d.queue=m,kp(Ip.bind(null,l,m,n),[n]),l.flags|=2048,Wr(9,xp.bind(null,l,m,a,o),void 0,null),a},useId:function(){var n=on(),o=rt.identifierPrefix;if($e){var a=hn,l=gn;a=(l&~(1<<32-Ft(l)-1)).toString(32)+a,o=":"+o+"R"+a,a=Zr++,0<\/script>",n=n.removeChild(n.firstChild)):typeof l.is=="string"?n=_.createElement(a,{is:l.is}):(n=_.createElement(a),a==="select"&&(_=n,l.multiple?_.multiple=!0:l.size&&(_.size=l.size))):n=_.createElementNS(n,a),n[tn]=o,n[$r]=l,of(n,o,!1,!1),o.stateNode=n;e:{switch(_=rs(a,l),a){case"dialog":Pe("cancel",n),Pe("close",n),d=l;break;case"iframe":case"object":case"embed":Pe("load",n),d=l;break;case"video":case"audio":for(d=0;dXo&&(o.flags|=128,l=!0,Gr(m,!1),o.lanes=4194304)}else{if(!l)if(n=Qi(_),n!==null){if(o.flags|=128,l=!0,a=n.updateQueue,a!==null&&(o.updateQueue=a,o.flags|=4),Gr(m,!0),m.tail===null&&m.tailMode==="hidden"&&!_.alternate&&!$e)return ct(o),null}else 2*He()-m.renderingStartTime>Xo&&a!==1073741824&&(o.flags|=128,l=!0,Gr(m,!1),o.lanes=4194304);m.isBackwards?(_.sibling=o.child,o.child=_):(a=m.last,a!==null?a.sibling=_:o.child=_,m.last=_)}return m.tail!==null?(o=m.tail,m.rendering=o,m.tail=o.sibling,m.renderingStartTime=He(),o.sibling=null,a=qe.current,Re(qe,l?a&1|2:a&1),o):(ct(o),null);case 22:case 23:return Ol(),l=o.memoizedState!==null,n!==null&&n.memoizedState!==null!==l&&(o.flags|=8192),l&&(o.mode&1)!==0?(Pt&1073741824)!==0&&(ct(o),o.subtreeFlags&6&&(o.flags|=8192)):ct(o),null;case 24:return null;case 25:return null}throw Error(i(156,o.tag))}function y2(n,o){switch(Vs(o),o.tag){case 1:return xt(o.type)&&qi(),n=o.flags,n&65536?(o.flags=n&-65537|128,o):null;case 3:return Vo(),je(_t),je(lt),rl(),n=o.flags,(n&65536)!==0&&(n&128)===0?(o.flags=n&-65537|128,o):null;case 5:return nl(o),null;case 13:if(je(qe),n=o.memoizedState,n!==null&&n.dehydrated!==null){if(o.alternate===null)throw Error(i(340));qo()}return n=o.flags,n&65536?(o.flags=n&-65537|128,o):null;case 19:return je(qe),null;case 4:return Vo(),null;case 10:return Js(o.type._context),null;case 22:case 23:return Ol(),null;case 24:return null;default:return null}}var sa=!1,dt=!1,_2=typeof WeakSet=="function"?WeakSet:Set,Q=null;function Go(n,o){var a=n.ref;if(a!==null)if(typeof a=="function")try{a(null)}catch(l){Ge(n,o,l)}else a.current=null}function Sl(n,o,a){try{a()}catch(l){Ge(n,o,l)}}var sf=!1;function x2(n,o){if(Os=Bi,n=Dd(),zs(n)){if("selectionStart"in n)var a={start:n.selectionStart,end:n.selectionEnd};else e:{a=(a=n.ownerDocument)&&a.defaultView||window;var l=a.getSelection&&a.getSelection();if(l&&l.rangeCount!==0){a=l.anchorNode;var d=l.anchorOffset,m=l.focusNode;l=l.focusOffset;try{a.nodeType,m.nodeType}catch{a=null;break e}var _=0,E=-1,S=-1,A=0,U=0,Z=n,q=null;t:for(;;){for(var K;Z!==a||d!==0&&Z.nodeType!==3||(E=_+d),Z!==m||l!==0&&Z.nodeType!==3||(S=_+l),Z.nodeType===3&&(_+=Z.nodeValue.length),(K=Z.firstChild)!==null;)q=Z,Z=K;for(;;){if(Z===n)break t;if(q===a&&++A===d&&(E=_),q===m&&++U===l&&(S=_),(K=Z.nextSibling)!==null)break;Z=q,q=Z.parentNode}Z=K}a=E===-1||S===-1?null:{start:E,end:S}}else a=null}a=a||{start:0,end:0}}else a=null;for($s={focusedElem:n,selectionRange:a},Bi=!1,Q=o;Q!==null;)if(o=Q,n=o.child,(o.subtreeFlags&1028)!==0&&n!==null)n.return=o,Q=n;else for(;Q!==null;){o=Q;try{var ne=o.alternate;if((o.flags&1024)!==0)switch(o.tag){case 0:case 11:case 15:break;case 1:if(ne!==null){var oe=ne.memoizedProps,Xe=ne.memoizedState,P=o.stateNode,B=P.getSnapshotBeforeUpdate(o.elementType===o.type?oe:Vt(o.type,oe),Xe);P.__reactInternalSnapshotBeforeUpdate=B}break;case 3:var j=o.stateNode.containerInfo;j.nodeType===1?j.textContent="":j.nodeType===9&&j.documentElement&&j.removeChild(j.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(i(163))}}catch(V){Ge(o,o.return,V)}if(n=o.sibling,n!==null){n.return=o.return,Q=n;break}Q=o.return}return ne=sf,sf=!1,ne}function Hr(n,o,a){var l=o.updateQueue;if(l=l!==null?l.lastEffect:null,l!==null){var d=l=l.next;do{if((d.tag&n)===n){var m=d.destroy;d.destroy=void 0,m!==void 0&&Sl(o,a,m)}d=d.next}while(d!==l)}}function la(n,o){if(o=o.updateQueue,o=o!==null?o.lastEffect:null,o!==null){var a=o=o.next;do{if((a.tag&n)===n){var l=a.create;a.destroy=l()}a=a.next}while(a!==o)}}function bl(n){var o=n.ref;if(o!==null){var a=n.stateNode;n.tag,n=a,typeof o=="function"?o(n):o.current=n}}function lf(n){var o=n.alternate;o!==null&&(n.alternate=null,lf(o)),n.child=null,n.deletions=null,n.sibling=null,n.tag===5&&(o=n.stateNode,o!==null&&(delete o[tn],delete o[$r],delete o[qs],delete o[n2],delete o[o2])),n.stateNode=null,n.return=null,n.dependencies=null,n.memoizedProps=null,n.memoizedState=null,n.pendingProps=null,n.stateNode=null,n.updateQueue=null}function uf(n){return n.tag===5||n.tag===3||n.tag===4}function cf(n){e:for(;;){for(;n.sibling===null;){if(n.return===null||uf(n.return))return null;n=n.return}for(n.sibling.return=n.return,n=n.sibling;n.tag!==5&&n.tag!==6&&n.tag!==18;){if(n.flags&2||n.child===null||n.tag===4)continue e;n.child.return=n,n=n.child}if(!(n.flags&2))return n.stateNode}}function kl(n,o,a){var l=n.tag;if(l===5||l===6)n=n.stateNode,o?a.nodeType===8?a.parentNode.insertBefore(n,o):a.insertBefore(n,o):(a.nodeType===8?(o=a.parentNode,o.insertBefore(n,a)):(o=a,o.appendChild(n)),a=a._reactRootContainer,a!=null||o.onclick!==null||(o.onclick=Mi));else if(l!==4&&(n=n.child,n!==null))for(kl(n,o,a),n=n.sibling;n!==null;)kl(n,o,a),n=n.sibling}function Bl(n,o,a){var l=n.tag;if(l===5||l===6)n=n.stateNode,o?a.insertBefore(n,o):a.appendChild(n);else if(l!==4&&(n=n.child,n!==null))for(Bl(n,o,a),n=n.sibling;n!==null;)Bl(n,o,a),n=n.sibling}var at=null,Wt=!1;function Zn(n,o,a){for(a=a.child;a!==null;)df(n,o,a),a=a.sibling}function df(n,o,a){if(en&&typeof en.onCommitFiberUnmount=="function")try{en.onCommitFiberUnmount(Ii,a)}catch{}switch(a.tag){case 5:dt||Go(a,o);case 6:var l=at,d=Wt;at=null,Zn(n,o,a),at=l,Wt=d,at!==null&&(Wt?(n=at,a=a.stateNode,n.nodeType===8?n.parentNode.removeChild(a):n.removeChild(a)):at.removeChild(a.stateNode));break;case 18:at!==null&&(Wt?(n=at,a=a.stateNode,n.nodeType===8?Ls(n.parentNode,a):n.nodeType===1&&Ls(n,a),kr(n)):Ls(at,a.stateNode));break;case 4:l=at,d=Wt,at=a.stateNode.containerInfo,Wt=!0,Zn(n,o,a),at=l,Wt=d;break;case 0:case 11:case 14:case 15:if(!dt&&(l=a.updateQueue,l!==null&&(l=l.lastEffect,l!==null))){d=l=l.next;do{var m=d,_=m.destroy;m=m.tag,_!==void 0&&((m&2)!==0||(m&4)!==0)&&Sl(a,o,_),d=d.next}while(d!==l)}Zn(n,o,a);break;case 1:if(!dt&&(Go(a,o),l=a.stateNode,typeof l.componentWillUnmount=="function"))try{l.props=a.memoizedProps,l.state=a.memoizedState,l.componentWillUnmount()}catch(E){Ge(a,o,E)}Zn(n,o,a);break;case 21:Zn(n,o,a);break;case 22:a.mode&1?(dt=(l=dt)||a.memoizedState!==null,Zn(n,o,a),dt=l):Zn(n,o,a);break;default:Zn(n,o,a)}}function pf(n){var o=n.updateQueue;if(o!==null){n.updateQueue=null;var a=n.stateNode;a===null&&(a=n.stateNode=new _2),o.forEach(function(l){var d=T2.bind(null,n,l);a.has(l)||(a.add(l),l.then(d,d))})}}function Gt(n,o){var a=o.deletions;if(a!==null)for(var l=0;ld&&(d=_),l&=~m}if(l=d,l=He()-l,l=(120>l?120:480>l?480:1080>l?1080:1920>l?1920:3e3>l?3e3:4320>l?4320:1960*E2(l/1960))-l,10n?16:n,Wn===null)var l=!1;else{if(n=Wn,Wn=null,fa=0,(_e&6)!==0)throw Error(i(331));var d=_e;for(_e|=4,Q=n.current;Q!==null;){var m=Q,_=m.child;if((Q.flags&16)!==0){var E=m.deletions;if(E!==null){for(var S=0;SHe()-Cl?go(n,0):Tl|=a),wt(n,o)}function bf(n,o){o===0&&((n.mode&1)===0?o=1:(o=wi,wi<<=1,(wi&130023424)===0&&(wi=4194304)));var a=vt();n=yn(n,o),n!==null&&(Ir(n,o,a),wt(n,a))}function z2(n){var o=n.memoizedState,a=0;o!==null&&(a=o.retryLane),bf(n,a)}function T2(n,o){var a=0;switch(n.tag){case 13:var l=n.stateNode,d=n.memoizedState;d!==null&&(a=d.retryLane);break;case 19:l=n.stateNode;break;default:throw Error(i(314))}l!==null&&l.delete(o),bf(n,a)}var kf;kf=function(n,o,a){if(n!==null)if(n.memoizedProps!==o.pendingProps||_t.current)It=!0;else{if((n.lanes&a)===0&&(o.flags&128)===0)return It=!1,g2(n,o,a);It=(n.flags&131072)!==0}else It=!1,$e&&(o.flags&1048576)!==0&&rp(o,Vi,o.index);switch(o.lanes=0,o.tag){case 2:var l=o.type;aa(n,o),n=o.pendingProps;var d=Do(o,lt.current);Zo(o,a),d=sl(null,o,l,n,d,a);var m=ll();return o.flags|=1,typeof d=="object"&&d!==null&&typeof d.render=="function"&&d.$$typeof===void 0?(o.tag=1,o.memoizedState=null,o.updateQueue=null,xt(l)?(m=!0,Fi(o)):m=!1,o.memoizedState=d.state!==null&&d.state!==void 0?d.state:null,el(o),d.updater=ra,o.stateNode=d,d._reactInternals=o,ml(o,l,n,a),o=yl(null,o,l,!0,m,a)):(o.tag=0,$e&&m&&Zs(o),mt(null,o,d,a),o=o.child),o;case 16:l=o.elementType;e:{switch(aa(n,o),n=o.pendingProps,d=l._init,l=d(l._payload),o.type=l,d=o.tag=R2(l),n=Vt(l,n),d){case 0:o=hl(null,o,l,n,a);break e;case 1:o=Jp(null,o,l,n,a);break e;case 11:o=Wp(null,o,l,n,a);break e;case 14:o=Gp(null,o,l,Vt(l.type,n),a);break e}throw Error(i(306,l,""))}return o;case 0:return l=o.type,d=o.pendingProps,d=o.elementType===l?d:Vt(l,d),hl(n,o,l,d,a);case 1:return l=o.type,d=o.pendingProps,d=o.elementType===l?d:Vt(l,d),Jp(n,o,l,d,a);case 3:e:{if(Qp(o),n===null)throw Error(i(387));l=o.pendingProps,m=o.memoizedState,d=m.element,fp(n,o),Ji(o,l,null,a);var _=o.memoizedState;if(l=_.element,m.isDehydrated)if(m={element:l,isDehydrated:!1,cache:_.cache,pendingSuspenseBoundaries:_.pendingSuspenseBoundaries,transitions:_.transitions},o.updateQueue.baseState=m,o.memoizedState=m,o.flags&256){d=Wo(Error(i(423)),o),o=Yp(n,o,l,a,d);break e}else if(l!==d){d=Wo(Error(i(424)),o),o=Yp(n,o,l,a,d);break e}else for(Nt=Dn(o.stateNode.containerInfo.firstChild),Rt=o,$e=!0,Zt=null,a=dp(o,null,l,a),o.child=a;a;)a.flags=a.flags&-3|4096,a=a.sibling;else{if(qo(),l===d){o=xn(n,o,a);break e}mt(n,o,l,a)}o=o.child}return o;case 5:return gp(o),n===null&&Gs(o),l=o.type,d=o.pendingProps,m=n!==null?n.memoizedProps:null,_=d.children,Ds(l,d)?_=null:m!==null&&Ds(l,m)&&(o.flags|=32),Kp(n,o),mt(n,o,_,a),o.child;case 6:return n===null&&Gs(o),null;case 13:return ef(n,o,a);case 4:return tl(o,o.stateNode.containerInfo),l=o.pendingProps,n===null?o.child=Fo(o,null,l,a):mt(n,o,l,a),o.child;case 11:return l=o.type,d=o.pendingProps,d=o.elementType===l?d:Vt(l,d),Wp(n,o,l,d,a);case 7:return mt(n,o,o.pendingProps,a),o.child;case 8:return mt(n,o,o.pendingProps.children,a),o.child;case 12:return mt(n,o,o.pendingProps.children,a),o.child;case 10:e:{if(l=o.type._context,d=o.pendingProps,m=o.memoizedProps,_=d.value,Re(Hi,l._currentValue),l._currentValue=_,m!==null)if(Ut(m.value,_)){if(m.children===d.children&&!_t.current){o=xn(n,o,a);break e}}else for(m=o.child,m!==null&&(m.return=o);m!==null;){var E=m.dependencies;if(E!==null){_=m.child;for(var S=E.firstContext;S!==null;){if(S.context===l){if(m.tag===1){S=_n(-1,a&-a),S.tag=2;var A=m.updateQueue;if(A!==null){A=A.shared;var U=A.pending;U===null?S.next=S:(S.next=U.next,U.next=S),A.pending=S}}m.lanes|=a,S=m.alternate,S!==null&&(S.lanes|=a),Qs(m.return,a,o),E.lanes|=a;break}S=S.next}}else if(m.tag===10)_=m.type===o.type?null:m.child;else if(m.tag===18){if(_=m.return,_===null)throw Error(i(341));_.lanes|=a,E=_.alternate,E!==null&&(E.lanes|=a),Qs(_,a,o),_=m.sibling}else _=m.child;if(_!==null)_.return=m;else for(_=m;_!==null;){if(_===o){_=null;break}if(m=_.sibling,m!==null){m.return=_.return,_=m;break}_=_.return}m=_}mt(n,o,d.children,a),o=o.child}return o;case 9:return d=o.type,l=o.pendingProps.children,Zo(o,a),d=Ot(d),l=l(d),o.flags|=1,mt(n,o,l,a),o.child;case 14:return l=o.type,d=Vt(l,o.pendingProps),d=Vt(l.type,d),Gp(n,o,l,d,a);case 15:return Hp(n,o,o.type,o.pendingProps,a);case 17:return l=o.type,d=o.pendingProps,d=o.elementType===l?d:Vt(l,d),aa(n,o),o.tag=1,xt(l)?(n=!0,Fi(o)):n=!1,Zo(o,a),Mp(o,l,d),ml(o,l,d,a),yl(null,o,l,!0,n,a);case 19:return nf(n,o,a);case 22:return Xp(n,o,a)}throw Error(i(156,o.tag))};function Bf(n,o){return id(n,o)}function C2(n,o,a,l){this.tag=n,this.key=a,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=o,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=l,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Mt(n,o,a,l){return new C2(n,o,a,l)}function Dl(n){return n=n.prototype,!(!n||!n.isReactComponent)}function R2(n){if(typeof n=="function")return Dl(n)?1:0;if(n!=null){if(n=n.$$typeof,n===Ae)return 11;if(n===zt)return 14}return 2}function Xn(n,o){var a=n.alternate;return a===null?(a=Mt(n.tag,o,n.key,n.mode),a.elementType=n.elementType,a.type=n.type,a.stateNode=n.stateNode,a.alternate=n,n.alternate=a):(a.pendingProps=o,a.type=n.type,a.flags=0,a.subtreeFlags=0,a.deletions=null),a.flags=n.flags&14680064,a.childLanes=n.childLanes,a.lanes=n.lanes,a.child=n.child,a.memoizedProps=n.memoizedProps,a.memoizedState=n.memoizedState,a.updateQueue=n.updateQueue,o=n.dependencies,a.dependencies=o===null?null:{lanes:o.lanes,firstContext:o.firstContext},a.sibling=n.sibling,a.index=n.index,a.ref=n.ref,a}function ha(n,o,a,l,d,m){var _=2;if(l=n,typeof n=="function")Dl(n)&&(_=1);else if(typeof n=="string")_=5;else e:switch(n){case ve:return yo(a.children,d,m,o);case de:_=8,d|=8;break;case we:return n=Mt(12,a,o,d|2),n.elementType=we,n.lanes=m,n;case nt:return n=Mt(13,a,o,d),n.elementType=nt,n.lanes=m,n;case Ye:return n=Mt(19,a,o,d),n.elementType=Ye,n.lanes=m,n;case We:return ya(a,d,m,o);default:if(typeof n=="object"&&n!==null)switch(n.$$typeof){case Se:_=10;break e;case Ne:_=9;break e;case Ae:_=11;break e;case zt:_=14;break e;case yt:_=16,l=null;break e}throw Error(i(130,n==null?n:typeof n,""))}return o=Mt(_,a,o,d),o.elementType=n,o.type=l,o.lanes=m,o}function yo(n,o,a,l){return n=Mt(7,n,l,o),n.lanes=a,n}function ya(n,o,a,l){return n=Mt(22,n,l,o),n.elementType=We,n.lanes=a,n.stateNode={isHidden:!1},n}function Ml(n,o,a){return n=Mt(6,n,null,o),n.lanes=a,n}function Ll(n,o,a){return o=Mt(4,n.children!==null?n.children:[],n.key,o),o.lanes=a,o.stateNode={containerInfo:n.containerInfo,pendingChildren:null,implementation:n.implementation},o}function N2(n,o,a,l,d){this.tag=o,this.containerInfo=n,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=fs(0),this.expirationTimes=fs(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=fs(0),this.identifierPrefix=l,this.onRecoverableError=d,this.mutableSourceEagerHydrationData=null}function ql(n,o,a,l,d,m,_,E,S){return n=new N2(n,o,a,E,S),o===1?(o=1,m===!0&&(o|=8)):o=0,m=Mt(3,null,null,o),n.current=m,m.stateNode=n,m.memoizedState={element:l,isDehydrated:a,cache:null,transitions:null,pendingSuspenseBoundaries:null},el(m),n}function P2(n,o,a){var l=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(r){console.error(r)}}return t(),Gl.exports=W2(),Gl.exports}var qf;function G2(){if(qf)return ba;qf=1;var t=Mm();return ba.createRoot=t.createRoot,ba.hydrateRoot=t.hydrateRoot,ba}var H2=G2();const X2=$m(H2);Mm();function ri(){return ri=Object.assign?Object.assign.bind():function(t){for(var r=1;r"u")throw new Error(r)}function xu(t,r){if(!t){typeof console<"u"&&console.warn(r);try{throw new Error(r)}catch{}}}function J2(){return Math.random().toString(36).substr(2,8)}function Uf(t,r){return{usr:t.state,key:t.key,idx:r}}function nu(t,r,i,s){return i===void 0&&(i=null),ri({pathname:typeof t=="string"?t:t.pathname,search:"",hash:""},typeof r=="string"?ur(r):r,{state:i,key:r&&r.key||s||J2()})}function Pa(t){let{pathname:r="/",search:i="",hash:s=""}=t;return i&&i!=="?"&&(r+=i.charAt(0)==="?"?i:"?"+i),s&&s!=="#"&&(r+=s.charAt(0)==="#"?s:"#"+s),r}function ur(t){let r={};if(t){let i=t.indexOf("#");i>=0&&(r.hash=t.substr(i),t=t.substr(0,i));let s=t.indexOf("?");s>=0&&(r.search=t.substr(s),t=t.substr(0,s)),t&&(r.pathname=t)}return r}function Q2(t,r,i,s){s===void 0&&(s={});let{window:u=document.defaultView,v5Compat:f=!1}=s,p=u.history,v=Qn.Pop,x=null,I=w();I==null&&(I=0,p.replaceState(ri({},p.state,{idx:I}),""));function w(){return(p.state||{idx:null}).idx}function b(){v=Qn.Pop;let D=w(),G=D==null?null:D-I;I=D,x&&x({action:v,location:W.location,delta:G})}function C(D,G){v=Qn.Push;let ee=nu(W.location,D,G);I=w()+1;let J=Uf(ee,I),H=W.createHref(ee);try{p.pushState(J,"",H)}catch(te){if(te instanceof DOMException&&te.name==="DataCloneError")throw te;u.location.assign(H)}f&&x&&x({action:v,location:W.location,delta:1})}function O(D,G){v=Qn.Replace;let ee=nu(W.location,D,G);I=w();let J=Uf(ee,I),H=W.createHref(ee);p.replaceState(J,"",H),f&&x&&x({action:v,location:W.location,delta:0})}function L(D){let G=u.location.origin!=="null"?u.location.origin:u.location.href,ee=typeof D=="string"?D:Pa(D);return ee=ee.replace(/ $/,"%20"),Ze(G,"No window.location.(origin|href) available to create URL for href: "+ee),new URL(ee,G)}let W={get action(){return v},get location(){return t(u,p)},listen(D){if(x)throw new Error("A history only accepts one active listener");return u.addEventListener(Ff,b),x=D,()=>{u.removeEventListener(Ff,b),x=null}},createHref(D){return r(u,D)},createURL:L,encodeLocation(D){let G=L(D);return{pathname:G.pathname,search:G.search,hash:G.hash}},push:C,replace:O,go(D){return p.go(D)}};return W}var Zf;(function(t){t.data="data",t.deferred="deferred",t.redirect="redirect",t.error="error"})(Zf||(Zf={}));function Y2(t,r,i){return i===void 0&&(i="/"),e0(t,r,i)}function e0(t,r,i,s){let u=typeof r=="string"?ur(r):r,f=rr(u.pathname||"/",i);if(f==null)return null;let p=Lm(t);t0(p);let v=null,x=p0(f);for(let I=0;v==null&&I{let x={relativePath:v===void 0?f.path||"":v,caseSensitive:f.caseSensitive===!0,childrenIndex:p,route:f};x.relativePath.startsWith("/")&&(Ze(x.relativePath.startsWith(s),'Absolute route path "'+x.relativePath+'" nested under path '+('"'+s+'" is not valid. An absolute child route path ')+"must start with the combined path of all its parent routes."),x.relativePath=x.relativePath.slice(s.length));let I=eo([s,x.relativePath]),w=i.concat(x);f.children&&f.children.length>0&&(Ze(f.index!==!0,"Index routes must not have child routes. Please remove "+('all child routes from route path "'+I+'".')),Lm(f.children,r,w,I)),!(f.path==null&&!f.index)&&r.push({path:I,score:l0(I,f.index),routesMeta:w})};return t.forEach((f,p)=>{var v;if(f.path===""||!((v=f.path)!=null&&v.includes("?")))u(f,p);else for(let x of qm(f.path))u(f,p,x)}),r}function qm(t){let r=t.split("/");if(r.length===0)return[];let[i,...s]=r,u=i.endsWith("?"),f=i.replace(/\?$/,"");if(s.length===0)return u?[f,""]:[f];let p=qm(s.join("/")),v=[];return v.push(...p.map(x=>x===""?f:[f,x].join("/"))),u&&v.push(...p),v.map(x=>t.startsWith("/")&&x===""?"/":x)}function t0(t){t.sort((r,i)=>r.score!==i.score?i.score-r.score:u0(r.routesMeta.map(s=>s.childrenIndex),i.routesMeta.map(s=>s.childrenIndex)))}const n0=/^:[\w-]+$/,o0=3,r0=2,i0=1,a0=10,s0=-2,Vf=t=>t==="*";function l0(t,r){let i=t.split("/"),s=i.length;return i.some(Vf)&&(s+=s0),r&&(s+=r0),i.filter(u=>!Vf(u)).reduce((u,f)=>u+(n0.test(f)?o0:f===""?i0:a0),s)}function u0(t,r){return t.length===r.length&&t.slice(0,-1).every((s,u)=>s===r[u])?t[t.length-1]-r[r.length-1]:0}function c0(t,r,i){let{routesMeta:s}=t,u={},f="/",p=[];for(let v=0;v{let{paramName:C,isOptional:O}=w;if(C==="*"){let W=v[b]||"";p=f.slice(0,f.length-W.length).replace(/(.)\/+$/,"$1")}const L=v[b];return O&&!L?I[C]=void 0:I[C]=(L||"").replace(/%2F/g,"/"),I},{}),pathname:f,pathnameBase:p,pattern:t}}function d0(t,r,i){r===void 0&&(r=!1),i===void 0&&(i=!0),xu(t==="*"||!t.endsWith("*")||t.endsWith("/*"),'Route path "'+t+'" will be treated as if it were '+('"'+t.replace(/\*$/,"/*")+'" because the `*` character must ')+"always follow a `/` in the pattern. To get rid of this warning, "+('please change the route path to "'+t.replace(/\*$/,"/*")+'".'));let s=[],u="^"+t.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(p,v,x)=>(s.push({paramName:v,isOptional:x!=null}),x?"/?([^\\/]+)?":"/([^\\/]+)"));return t.endsWith("*")?(s.push({paramName:"*"}),u+=t==="*"||t==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):i?u+="\\/*$":t!==""&&t!=="/"&&(u+="(?:(?=\\/|$))"),[new RegExp(u,r?void 0:"i"),s]}function p0(t){try{return t.split("/").map(r=>decodeURIComponent(r).replace(/\//g,"%2F")).join("/")}catch(r){return xu(!1,'The URL path "'+t+'" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent '+("encoding ("+r+").")),t}}function rr(t,r){if(r==="/")return t;if(!t.toLowerCase().startsWith(r.toLowerCase()))return null;let i=r.endsWith("/")?r.length-1:r.length,s=t.charAt(i);return s&&s!=="/"?null:t.slice(i)||"/"}const f0=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,m0=t=>f0.test(t);function v0(t,r){r===void 0&&(r="/");let{pathname:i,search:s="",hash:u=""}=typeof t=="string"?ur(t):t,f;if(i)if(m0(i))f=i;else{if(i.includes("//")){let p=i;i=Fm(i),xu(!1,"Pathnames cannot have embedded double slashes - normalizing "+(p+" -> "+i))}i.startsWith("/")?f=Wf(i.substring(1),"/"):f=Wf(i,r)}else f=r;return{pathname:f,search:y0(s),hash:_0(u)}}function Wf(t,r){let i=r.replace(/\/+$/,"").split("/");return t.split("/").forEach(u=>{u===".."?i.length>1&&i.pop():u!=="."&&i.push(u)}),i.length>1?i.join("/"):"/"}function Kl(t,r,i,s){return"Cannot include a '"+t+"' character in a manually specified "+("`to."+r+"` field ["+JSON.stringify(s)+"]. Please separate it out to the ")+("`to."+i+"` field. Alternatively you may provide the full path as ")+'a string in and the router will parse it for you.'}function g0(t){return t.filter((r,i)=>i===0||r.route.path&&r.route.path.length>0)}function Iu(t,r){let i=g0(t);return r?i.map((s,u)=>u===i.length-1?s.pathname:s.pathnameBase):i.map(s=>s.pathnameBase)}function Eu(t,r,i,s){s===void 0&&(s=!1);let u;typeof t=="string"?u=ur(t):(u=ri({},t),Ze(!u.pathname||!u.pathname.includes("?"),Kl("?","pathname","search",u)),Ze(!u.pathname||!u.pathname.includes("#"),Kl("#","pathname","hash",u)),Ze(!u.search||!u.search.includes("#"),Kl("#","search","hash",u)));let f=t===""||u.pathname==="",p=f?"/":u.pathname,v;if(p==null)v=i;else{let b=r.length-1;if(!s&&p.startsWith("..")){let C=p.split("/");for(;C[0]==="..";)C.shift(),b-=1;u.pathname=C.join("/")}v=b>=0?r[b]:"/"}let x=v0(u,v),I=p&&p!=="/"&&p.endsWith("/"),w=(f||p===".")&&i.endsWith("/");return!x.pathname.endsWith("/")&&(I||w)&&(x.pathname+="/"),x}const Fm=t=>t.replace(/\/\/+/g,"/"),eo=t=>Fm(t.join("/")),h0=t=>t.replace(/\/+$/,"").replace(/^\/*/,"/"),y0=t=>!t||t==="?"?"":t.startsWith("?")?t:"?"+t,_0=t=>!t||t==="#"?"":t.startsWith("#")?t:"#"+t;function x0(t){return t!=null&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.internal=="boolean"&&"data"in t}const Um=["post","put","patch","delete"];new Set(Um);const I0=["get",...Um];new Set(I0);function ii(){return ii=Object.assign?Object.assign.bind():function(t){for(var r=1;r{v.current=!0}),T.useCallback(function(I,w){if(w===void 0&&(w={}),!v.current)return;if(typeof I=="number"){s.go(I);return}let b=Eu(I,JSON.parse(p),f,w.relative==="path");t==null&&r!=="/"&&(b.pathname=b.pathname==="/"?r:eo([r,b.pathname])),(w.replace?s.replace:s.push)(b,w.state,w)},[r,s,p,f,t])}function I9(){let{matches:t}=T.useContext(zn),r=t[t.length-1];return r?r.params:{}}function Fa(t,r){let{relative:i}=r===void 0?{}:r,{future:s}=T.useContext(Bn),{matches:u}=T.useContext(zn),{pathname:f}=Tn(),p=JSON.stringify(Iu(u,s.v7_relativeSplatPath));return T.useMemo(()=>Eu(t,JSON.parse(p),f,i==="path"),[t,p,f,i])}function S0(t,r){return b0(t,r)}function b0(t,r,i,s){cr()||Ze(!1);let{navigator:u}=T.useContext(Bn),{matches:f}=T.useContext(zn),p=f[f.length-1],v=p?p.params:{};p&&p.pathname;let x=p?p.pathnameBase:"/";p&&p.route;let I=Tn(),w;if(r){var b;let D=typeof r=="string"?ur(r):r;x==="/"||(b=D.pathname)!=null&&b.startsWith(x)||Ze(!1),w=D}else w=I;let C=w.pathname||"/",O=C;if(x!=="/"){let D=x.replace(/^\//,"").split("/");O="/"+C.replace(/^\//,"").split("/").slice(D.length).join("/")}let L=Y2(t,{pathname:O}),W=C0(L&&L.map(D=>Object.assign({},D,{params:Object.assign({},v,D.params),pathname:eo([x,u.encodeLocation?u.encodeLocation(D.pathname).pathname:D.pathname]),pathnameBase:D.pathnameBase==="/"?x:eo([x,u.encodeLocation?u.encodeLocation(D.pathnameBase).pathname:D.pathnameBase])})),f,i,s);return r&&W?T.createElement(qa.Provider,{value:{location:ii({pathname:"/",search:"",hash:"",state:null,key:"default"},w),navigationType:Qn.Pop}},W):W}function k0(){let t=j0(),r=x0(t)?t.status+" "+t.statusText:t instanceof Error?t.message:JSON.stringify(t),i=t instanceof Error?t.stack:null,u={padding:"0.5rem",backgroundColor:"rgba(200,200,200, 0.5)"};return T.createElement(T.Fragment,null,T.createElement("h2",null,"Unexpected Application Error!"),T.createElement("h3",{style:{fontStyle:"italic"}},r),i?T.createElement("pre",{style:u},i):null,null)}const B0=T.createElement(k0,null);class z0 extends T.Component{constructor(r){super(r),this.state={location:r.location,revalidation:r.revalidation,error:r.error}}static getDerivedStateFromError(r){return{error:r}}static getDerivedStateFromProps(r,i){return i.location!==r.location||i.revalidation!=="idle"&&r.revalidation==="idle"?{error:r.error,location:r.location,revalidation:r.revalidation}:{error:r.error!==void 0?r.error:i.error,location:i.location,revalidation:r.revalidation||i.revalidation}}componentDidCatch(r,i){console.error("React Router caught the following error during render",r,i)}render(){return this.state.error!==void 0?T.createElement(zn.Provider,{value:this.props.routeContext},T.createElement(Vm.Provider,{value:this.state.error,children:this.props.component})):this.props.children}}function T0(t){let{routeContext:r,match:i,children:s}=t,u=T.useContext(La);return u&&u.static&&u.staticContext&&(i.route.errorElement||i.route.ErrorBoundary)&&(u.staticContext._deepestRenderedBoundaryId=i.route.id),T.createElement(zn.Provider,{value:r},s)}function C0(t,r,i,s){var u;if(r===void 0&&(r=[]),i===void 0&&(i=null),s===void 0&&(s=null),t==null){var f;if(!i)return null;if(i.errors)t=i.matches;else if((f=s)!=null&&f.v7_partialHydration&&r.length===0&&!i.initialized&&i.matches.length>0)t=i.matches;else return null}let p=t,v=(u=i)==null?void 0:u.errors;if(v!=null){let w=p.findIndex(b=>b.route.id&&v?.[b.route.id]!==void 0);w>=0||Ze(!1),p=p.slice(0,Math.min(p.length,w+1))}let x=!1,I=-1;if(i&&s&&s.v7_partialHydration)for(let w=0;w=0?p=p.slice(0,I+1):p=[p[0]];break}}}return p.reduceRight((w,b,C)=>{let O,L=!1,W=null,D=null;i&&(O=v&&b.route.id?v[b.route.id]:void 0,W=b.route.errorElement||B0,x&&(I<0&&C===0?(O0("route-fallback"),L=!0,D=null):I===C&&(L=!0,D=b.route.hydrateFallbackElement||null)));let G=r.concat(p.slice(0,C+1)),ee=()=>{let J;return O?J=W:L?J=D:b.route.Component?J=T.createElement(b.route.Component,null):b.route.element?J=b.route.element:J=w,T.createElement(T0,{match:b,routeContext:{outlet:w,matches:G,isDataRoute:i!=null},children:J})};return i&&(b.route.ErrorBoundary||b.route.errorElement||C===0)?T.createElement(z0,{location:i.location,revalidation:i.revalidation,component:W,error:O,children:ee(),routeContext:{outlet:null,matches:G,isDataRoute:!0}}):ee()},null)}var Gm=(function(t){return t.UseBlocker="useBlocker",t.UseRevalidator="useRevalidator",t.UseNavigateStable="useNavigate",t})(Gm||{}),Hm=(function(t){return t.UseBlocker="useBlocker",t.UseLoaderData="useLoaderData",t.UseActionData="useActionData",t.UseRouteError="useRouteError",t.UseNavigation="useNavigation",t.UseRouteLoaderData="useRouteLoaderData",t.UseMatches="useMatches",t.UseRevalidator="useRevalidator",t.UseNavigateStable="useNavigate",t.UseRouteId="useRouteId",t})(Hm||{});function R0(t){let r=T.useContext(La);return r||Ze(!1),r}function N0(t){let r=T.useContext(Zm);return r||Ze(!1),r}function P0(t){let r=T.useContext(zn);return r||Ze(!1),r}function Xm(t){let r=P0(),i=r.matches[r.matches.length-1];return i.route.id||Ze(!1),i.route.id}function j0(){var t;let r=T.useContext(Vm),i=N0(),s=Xm();return r!==void 0?r:(t=i.errors)==null?void 0:t[s]}function A0(){let{router:t}=R0(Gm.UseNavigateStable),r=Xm(Hm.UseNavigateStable),i=T.useRef(!1);return Wm(()=>{i.current=!0}),T.useCallback(function(u,f){f===void 0&&(f={}),i.current&&(typeof u=="number"?t.navigate(u):t.navigate(u,ii({fromRouteId:r},f)))},[t,r])}const Gf={};function O0(t,r,i){Gf[t]||(Gf[t]=!0)}function $0(t,r){t?.v7_startTransition,t?.v7_relativeSplatPath}function D0(t){let{to:r,replace:i,state:s,relative:u}=t;cr()||Ze(!1);let{future:f,static:p}=T.useContext(Bn),{matches:v}=T.useContext(zn),{pathname:x}=Tn(),I=wu(),w=Eu(r,Iu(v,f.v7_relativeSplatPath),x,u==="path"),b=JSON.stringify(w);return T.useEffect(()=>I(JSON.parse(b),{replace:i,state:s,relative:u}),[I,b,u,i,s]),null}function an(t){Ze(!1)}function M0(t){let{basename:r="/",children:i=null,location:s,navigationType:u=Qn.Pop,navigator:f,static:p=!1,future:v}=t;cr()&&Ze(!1);let x=r.replace(/^\/*/,"/"),I=T.useMemo(()=>({basename:x,navigator:f,static:p,future:ii({v7_relativeSplatPath:!1},v)}),[x,v,f,p]);typeof s=="string"&&(s=ur(s));let{pathname:w="/",search:b="",hash:C="",state:O=null,key:L="default"}=s,W=T.useMemo(()=>{let D=rr(w,x);return D==null?null:{location:{pathname:D,search:b,hash:C,state:O,key:L},navigationType:u}},[x,w,b,C,O,L,u]);return W==null?null:T.createElement(Bn.Provider,{value:I},T.createElement(qa.Provider,{children:i,value:W}))}function L0(t){let{children:r,location:i}=t;return S0(ru(r),i)}new Promise(()=>{});function ru(t,r){r===void 0&&(r=[]);let i=[];return T.Children.forEach(t,(s,u)=>{if(!T.isValidElement(s))return;let f=[...r,u];if(s.type===T.Fragment){i.push.apply(i,ru(s.props.children,f));return}s.type!==an&&Ze(!1),!s.props.index||!s.props.children||Ze(!1);let p={id:s.props.id||f.join("-"),caseSensitive:s.props.caseSensitive,element:s.props.element,Component:s.props.Component,index:s.props.index,path:s.props.path,loader:s.props.loader,action:s.props.action,errorElement:s.props.errorElement,ErrorBoundary:s.props.ErrorBoundary,hasErrorBoundary:s.props.ErrorBoundary!=null||s.props.errorElement!=null,shouldRevalidate:s.props.shouldRevalidate,handle:s.props.handle,lazy:s.props.lazy};s.props.children&&(p.children=ru(s.props.children,f)),i.push(p)}),i}function ja(){return ja=Object.assign?Object.assign.bind():function(t){for(var r=1;r{let s=t[i];return r.concat(Array.isArray(s)?s.map(u=>[i,u]):[[i,s]])},[]))}function U0(t,r){let i=iu(t);return r&&r.forEach((s,u)=>{i.has(u)||r.getAll(u).forEach(f=>{i.append(u,f)})}),i}const Z0=["onClick","relative","reloadDocument","replace","state","target","to","preventScrollReset","viewTransition"],V0=["aria-current","caseSensitive","className","end","style","to","viewTransition","children"],W0="6";try{window.__reactRouterVersion=W0}catch{}const G0=T.createContext({isTransitioning:!1}),H0="startTransition",Hf=U2[H0];function X0(t){let{basename:r,children:i,future:s,window:u}=t,f=T.useRef();f.current==null&&(f.current=K2({window:u,v5Compat:!0}));let p=f.current,[v,x]=T.useState({action:p.action,location:p.location}),{v7_startTransition:I}=s||{},w=T.useCallback(b=>{I&&Hf?Hf(()=>x(b)):x(b)},[x,I]);return T.useLayoutEffect(()=>p.listen(w),[p,w]),T.useEffect(()=>$0(s),[s]),T.createElement(M0,{basename:r,children:i,location:v.location,navigationType:v.action,navigator:p,future:s})}const K0=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u",J0=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Q0=T.forwardRef(function(r,i){let{onClick:s,relative:u,reloadDocument:f,replace:p,state:v,target:x,to:I,preventScrollReset:w,viewTransition:b}=r,C=Km(r,Z0),{basename:O}=T.useContext(Bn),L,W=!1;if(typeof I=="string"&&J0.test(I)&&(L=I,K0))try{let J=new URL(window.location.href),H=I.startsWith("//")?new URL(J.protocol+I):new URL(I),te=rr(H.pathname,O);H.origin===J.origin&&te!=null?I=te+H.search+H.hash:W=!0}catch{}let D=E0(I,{relative:u}),G=t3(I,{replace:p,state:v,target:x,preventScrollReset:w,relative:u,viewTransition:b});function ee(J){s&&s(J),J.defaultPrevented||G(J)}return T.createElement("a",ja({},C,{href:L||D,onClick:W||f?s:ee,ref:i,target:x}))}),Y0=T.forwardRef(function(r,i){let{"aria-current":s="page",caseSensitive:u=!1,className:f="",end:p=!1,style:v,to:x,viewTransition:I,children:w}=r,b=Km(r,V0),C=Fa(x,{relative:b.relative}),O=Tn(),L=T.useContext(Zm),{navigator:W,basename:D}=T.useContext(Bn),G=L!=null&&n3(C)&&I===!0,ee=W.encodeLocation?W.encodeLocation(C).pathname:C.pathname,J=O.pathname,H=L&&L.navigation&&L.navigation.location?L.navigation.location.pathname:null;u||(J=J.toLowerCase(),H=H?H.toLowerCase():null,ee=ee.toLowerCase()),H&&D&&(H=rr(H,D)||H);const te=ee!=="/"&&ee.endsWith("/")?ee.length-1:ee.length;let ue=J===ee||!p&&J.startsWith(ee)&&J.charAt(te)==="/",ve=H!=null&&(H===ee||!p&&H.startsWith(ee)&&H.charAt(ee.length)==="/"),de={isActive:ue,isPending:ve,isTransitioning:G},we=ue?s:void 0,Se;typeof f=="function"?Se=f(de):Se=[f,ue?"active":null,ve?"pending":null,G?"transitioning":null].filter(Boolean).join(" ");let Ne=typeof v=="function"?v(de):v;return T.createElement(Q0,ja({},b,{"aria-current":we,className:Se,ref:i,style:Ne,to:x,viewTransition:I}),typeof w=="function"?w(de):w)});var au;(function(t){t.UseScrollRestoration="useScrollRestoration",t.UseSubmit="useSubmit",t.UseSubmitFetcher="useSubmitFetcher",t.UseFetcher="useFetcher",t.useViewTransitionState="useViewTransitionState"})(au||(au={}));var Xf;(function(t){t.UseFetcher="useFetcher",t.UseFetchers="useFetchers",t.UseScrollRestoration="useScrollRestoration"})(Xf||(Xf={}));function e3(t){let r=T.useContext(La);return r||Ze(!1),r}function t3(t,r){let{target:i,replace:s,state:u,preventScrollReset:f,relative:p,viewTransition:v}=r===void 0?{}:r,x=wu(),I=Tn(),w=Fa(t,{relative:p});return T.useCallback(b=>{if(F0(b,i)){b.preventDefault();let C=s!==void 0?s:Pa(I)===Pa(w);x(t,{replace:C,state:u,preventScrollReset:f,relative:p,viewTransition:v})}},[I,x,w,s,u,i,t,f,p,v])}function E9(t){let r=T.useRef(iu(t)),i=T.useRef(!1),s=Tn(),u=T.useMemo(()=>U0(s.search,i.current?null:r.current),[s.search]),f=wu(),p=T.useCallback((v,x)=>{const I=iu(typeof v=="function"?v(u):v);i.current=!0,f("?"+I,x)},[f,u]);return[u,p]}function n3(t,r){r===void 0&&(r={});let i=T.useContext(G0);i==null&&Ze(!1);let{basename:s}=e3(au.useViewTransitionState),u=Fa(t,{relative:r.relative});if(!i.isTransitioning)return!1;let f=rr(i.currentLocation.pathname,s)||i.currentLocation.pathname,p=rr(i.nextLocation.pathname,s)||i.nextLocation.pathname;return ou(u.pathname,p)!=null||ou(u.pathname,f)!=null}const o3=new Set(["failed","errored","stuck","crashed"]),r3=new Set(["rate-limited","rate_limited","waiting"]),i3={"awaiting-input":"respond",errored:"reset","rate-limited":"nudge",stalled:"nudge"};function a3(t,r){const i=new Map;for(const u of r)i.set(u.agentName,u.prompt);const s=[];for(const u of t){const f=i.has(u.name),p=s3(u,f);p!==null&&s.push({name:u.name,reason:p,detail:u3(u,p,i.get(u.name)),action:i3[p]})}return s}function s3(t,r){if(r)return"awaiting-input";const i=t.state.toLowerCase();return o3.has(i)?"errored":r3.has(i)?"rate-limited":l3(t,i)?"stalled":null}function l3(t,r){return r==="detached"?!0:t.running&&t.session===void 0}function u3(t,r,i){switch(r){case"awaiting-input":return c3(i);case"errored":return`Exited ${t.state}.`;case"rate-limited":return"Throttled by a provider limit.";case"stalled":return t.state.toLowerCase()==="detached"?"Detached from its session.":"Running with no live session."}}function c3(t){if(t===void 0)return"Awaiting your decision.";const r=t.split(` +`+m.stack}return{value:n,source:o,stack:d,digest:null}}function vl(n,o,a){return{value:n,source:null,stack:a??null,digest:o??null}}function gl(n,o){try{console.error(o.value)}catch(a){setTimeout(function(){throw a})}}var f2=typeof WeakMap=="function"?WeakMap:Map;function qp(n,o,a){a=_n(-1,a),a.tag=3,a.payload={element:null};var l=o.value;return a.callback=function(){da||(da=!0,Rl=l),gl(n,o)},a}function Fp(n,o,a){a=_n(-1,a),a.tag=3;var l=n.type.getDerivedStateFromError;if(typeof l=="function"){var d=o.value;a.payload=function(){return l(d)},a.callback=function(){gl(n,o)}}var m=n.stateNode;return m!==null&&typeof m.componentDidCatch=="function"&&(a.callback=function(){gl(n,o),typeof l!="function"&&(Vn===null?Vn=new Set([this]):Vn.add(this));var _=o.stack;this.componentDidCatch(o.value,{componentStack:_!==null?_:""})}),a}function Up(n,o,a){var l=n.pingCache;if(l===null){l=n.pingCache=new f2;var d=new Set;l.set(o,d)}else d=l.get(o),d===void 0&&(d=new Set,l.set(o,d));d.has(a)||(d.add(a),n=B2.bind(null,n,o,a),o.then(n,n))}function Zp(n){do{var o;if((o=n.tag===13)&&(o=n.memoizedState,o=o!==null?o.dehydrated!==null:!0),o)return n;n=n.return}while(n!==null);return null}function Vp(n,o,a,l,d){return(n.mode&1)===0?(n===o?n.flags|=65536:(n.flags|=128,a.flags|=131072,a.flags&=-52805,a.tag===1&&(a.alternate===null?a.tag=17:(o=_n(-1,1),o.tag=2,Un(a,o,1))),a.lanes|=1),n):(n.flags|=65536,n.lanes=d,n)}var m2=H.ReactCurrentOwner,It=!1;function mt(n,o,a,l){o.child=n===null?dp(o,null,a,l):Fo(o,n.child,a,l)}function Wp(n,o,a,l,d){a=a.render;var m=o.ref;return Zo(o,d),l=sl(n,o,a,l,m,d),a=ll(),n!==null&&!It?(o.updateQueue=n.updateQueue,o.flags&=-2053,n.lanes&=~d,xn(n,o,d)):($e&&a&&Zs(o),o.flags|=1,mt(n,o,l,d),o.child)}function Gp(n,o,a,l,d){if(n===null){var m=a.type;return typeof m=="function"&&!Dl(m)&&m.defaultProps===void 0&&a.compare===null&&a.defaultProps===void 0?(o.tag=15,o.type=m,Hp(n,o,m,l,d)):(n=ha(a.type,null,l,o,o.mode,d),n.ref=o.ref,n.return=o,o.child=n)}if(m=n.child,(n.lanes&d)===0){var _=m.memoizedProps;if(a=a.compare,a=a!==null?a:Nr,a(_,l)&&n.ref===o.ref)return xn(n,o,d)}return o.flags|=1,n=Xn(m,l),n.ref=o.ref,n.return=o,o.child=n}function Hp(n,o,a,l,d){if(n!==null){var m=n.memoizedProps;if(Nr(m,l)&&n.ref===o.ref)if(It=!1,o.pendingProps=l=m,(n.lanes&d)!==0)(n.flags&131072)!==0&&(It=!0);else return o.lanes=n.lanes,xn(n,o,d)}return hl(n,o,a,l,d)}function Xp(n,o,a){var l=o.pendingProps,d=l.children,m=n!==null?n.memoizedState:null;if(l.mode==="hidden")if((o.mode&1)===0)o.memoizedState={baseLanes:0,cachePool:null,transitions:null},Re(Ho,Pt),Pt|=a;else{if((a&1073741824)===0)return n=m!==null?m.baseLanes|a:a,o.lanes=o.childLanes=1073741824,o.memoizedState={baseLanes:n,cachePool:null,transitions:null},o.updateQueue=null,Re(Ho,Pt),Pt|=n,null;o.memoizedState={baseLanes:0,cachePool:null,transitions:null},l=m!==null?m.baseLanes:a,Re(Ho,Pt),Pt|=l}else m!==null?(l=m.baseLanes|a,o.memoizedState=null):l=a,Re(Ho,Pt),Pt|=l;return mt(n,o,d,a),o.child}function Kp(n,o){var a=o.ref;(n===null&&a!==null||n!==null&&n.ref!==a)&&(o.flags|=512,o.flags|=2097152)}function hl(n,o,a,l,d){var m=xt(a)?so:lt.current;return m=Do(o,m),Zo(o,d),a=sl(n,o,a,l,m,d),l=ll(),n!==null&&!It?(o.updateQueue=n.updateQueue,o.flags&=-2053,n.lanes&=~d,xn(n,o,d)):($e&&l&&Zs(o),o.flags|=1,mt(n,o,a,d),o.child)}function Jp(n,o,a,l,d){if(xt(a)){var m=!0;Fi(o)}else m=!1;if(Zo(o,d),o.stateNode===null)aa(n,o),Mp(o,a,l),ml(o,a,l,d),l=!0;else if(n===null){var _=o.stateNode,E=o.memoizedProps;_.props=E;var S=_.context,A=a.contextType;typeof A=="object"&&A!==null?A=Ot(A):(A=xt(a)?so:lt.current,A=Do(o,A));var U=a.getDerivedStateFromProps,Z=typeof U=="function"||typeof _.getSnapshotBeforeUpdate=="function";Z||typeof _.UNSAFE_componentWillReceiveProps!="function"&&typeof _.componentWillReceiveProps!="function"||(E!==l||S!==A)&&Lp(o,_,l,A),Fn=!1;var q=o.memoizedState;_.state=q,Ji(o,l,_,d),S=o.memoizedState,E!==l||q!==S||_t.current||Fn?(typeof U=="function"&&(fl(o,a,U,l),S=o.memoizedState),(E=Fn||Dp(o,a,E,l,q,S,A))?(Z||typeof _.UNSAFE_componentWillMount!="function"&&typeof _.componentWillMount!="function"||(typeof _.componentWillMount=="function"&&_.componentWillMount(),typeof _.UNSAFE_componentWillMount=="function"&&_.UNSAFE_componentWillMount()),typeof _.componentDidMount=="function"&&(o.flags|=4194308)):(typeof _.componentDidMount=="function"&&(o.flags|=4194308),o.memoizedProps=l,o.memoizedState=S),_.props=l,_.state=S,_.context=A,l=E):(typeof _.componentDidMount=="function"&&(o.flags|=4194308),l=!1)}else{_=o.stateNode,fp(n,o),E=o.memoizedProps,A=o.type===o.elementType?E:Vt(o.type,E),_.props=A,Z=o.pendingProps,q=_.context,S=a.contextType,typeof S=="object"&&S!==null?S=Ot(S):(S=xt(a)?so:lt.current,S=Do(o,S));var K=a.getDerivedStateFromProps;(U=typeof K=="function"||typeof _.getSnapshotBeforeUpdate=="function")||typeof _.UNSAFE_componentWillReceiveProps!="function"&&typeof _.componentWillReceiveProps!="function"||(E!==Z||q!==S)&&Lp(o,_,l,S),Fn=!1,q=o.memoizedState,_.state=q,Ji(o,l,_,d);var ne=o.memoizedState;E!==Z||q!==ne||_t.current||Fn?(typeof K=="function"&&(fl(o,a,K,l),ne=o.memoizedState),(A=Fn||Dp(o,a,A,l,q,ne,S)||!1)?(U||typeof _.UNSAFE_componentWillUpdate!="function"&&typeof _.componentWillUpdate!="function"||(typeof _.componentWillUpdate=="function"&&_.componentWillUpdate(l,ne,S),typeof _.UNSAFE_componentWillUpdate=="function"&&_.UNSAFE_componentWillUpdate(l,ne,S)),typeof _.componentDidUpdate=="function"&&(o.flags|=4),typeof _.getSnapshotBeforeUpdate=="function"&&(o.flags|=1024)):(typeof _.componentDidUpdate!="function"||E===n.memoizedProps&&q===n.memoizedState||(o.flags|=4),typeof _.getSnapshotBeforeUpdate!="function"||E===n.memoizedProps&&q===n.memoizedState||(o.flags|=1024),o.memoizedProps=l,o.memoizedState=ne),_.props=l,_.state=ne,_.context=S,l=A):(typeof _.componentDidUpdate!="function"||E===n.memoizedProps&&q===n.memoizedState||(o.flags|=4),typeof _.getSnapshotBeforeUpdate!="function"||E===n.memoizedProps&&q===n.memoizedState||(o.flags|=1024),l=!1)}return yl(n,o,a,l,m,d)}function yl(n,o,a,l,d,m){Kp(n,o);var _=(o.flags&128)!==0;if(!l&&!_)return d&&np(o,a,!1),xn(n,o,m);l=o.stateNode,m2.current=o;var E=_&&typeof a.getDerivedStateFromError!="function"?null:l.render();return o.flags|=1,n!==null&&_?(o.child=Fo(o,n.child,null,m),o.child=Fo(o,null,E,m)):mt(n,o,E,m),o.memoizedState=l.state,d&&np(o,a,!0),o.child}function Qp(n){var o=n.stateNode;o.pendingContext?ep(n,o.pendingContext,o.pendingContext!==o.context):o.context&&ep(n,o.context,!1),tl(n,o.containerInfo)}function Yp(n,o,a,l,d){return qo(),Hs(d),o.flags|=256,mt(n,o,a,l),o.child}var _l={dehydrated:null,treeContext:null,retryLane:0};function xl(n){return{baseLanes:n,cachePool:null,transitions:null}}function ef(n,o,a){var l=o.pendingProps,d=qe.current,m=!1,_=(o.flags&128)!==0,E;if((E=_)||(E=n!==null&&n.memoizedState===null?!1:(d&2)!==0),E?(m=!0,o.flags&=-129):(n===null||n.memoizedState!==null)&&(d|=1),Re(qe,d&1),n===null)return Gs(o),n=o.memoizedState,n!==null&&(n=n.dehydrated,n!==null)?((o.mode&1)===0?o.lanes=1:n.data==="$!"?o.lanes=8:o.lanes=1073741824,null):(_=l.children,n=l.fallback,m?(l=o.mode,m=o.child,_={mode:"hidden",children:_},(l&1)===0&&m!==null?(m.childLanes=0,m.pendingProps=_):m=ya(_,l,0,null),n=yo(n,l,a,null),m.return=o,n.return=o,m.sibling=n,o.child=m,o.child.memoizedState=xl(a),o.memoizedState=_l,n):Il(o,_));if(d=n.memoizedState,d!==null&&(E=d.dehydrated,E!==null))return v2(n,o,_,l,E,d,a);if(m){m=l.fallback,_=o.mode,d=n.child,E=d.sibling;var S={mode:"hidden",children:l.children};return(_&1)===0&&o.child!==d?(l=o.child,l.childLanes=0,l.pendingProps=S,o.deletions=null):(l=Xn(d,S),l.subtreeFlags=d.subtreeFlags&14680064),E!==null?m=Xn(E,m):(m=yo(m,_,a,null),m.flags|=2),m.return=o,l.return=o,l.sibling=m,o.child=l,l=m,m=o.child,_=n.child.memoizedState,_=_===null?xl(a):{baseLanes:_.baseLanes|a,cachePool:null,transitions:_.transitions},m.memoizedState=_,m.childLanes=n.childLanes&~a,o.memoizedState=_l,l}return m=n.child,n=m.sibling,l=Xn(m,{mode:"visible",children:l.children}),(o.mode&1)===0&&(l.lanes=a),l.return=o,l.sibling=null,n!==null&&(a=o.deletions,a===null?(o.deletions=[n],o.flags|=16):a.push(n)),o.child=l,o.memoizedState=null,l}function Il(n,o){return o=ya({mode:"visible",children:o},n.mode,0,null),o.return=n,n.child=o}function ia(n,o,a,l){return l!==null&&Hs(l),Fo(o,n.child,null,a),n=Il(o,o.pendingProps.children),n.flags|=2,o.memoizedState=null,n}function v2(n,o,a,l,d,m,_){if(a)return o.flags&256?(o.flags&=-257,l=vl(Error(i(422))),ia(n,o,_,l)):o.memoizedState!==null?(o.child=n.child,o.flags|=128,null):(m=l.fallback,d=o.mode,l=ya({mode:"visible",children:l.children},d,0,null),m=yo(m,d,_,null),m.flags|=2,l.return=o,m.return=o,l.sibling=m,o.child=l,(o.mode&1)!==0&&Fo(o,n.child,null,_),o.child.memoizedState=xl(_),o.memoizedState=_l,m);if((o.mode&1)===0)return ia(n,o,_,null);if(d.data==="$!"){if(l=d.nextSibling&&d.nextSibling.dataset,l)var E=l.dgst;return l=E,m=Error(i(419)),l=vl(m,l,void 0),ia(n,o,_,l)}if(E=(_&n.childLanes)!==0,It||E){if(l=rt,l!==null){switch(_&-_){case 4:d=2;break;case 16:d=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:d=32;break;case 536870912:d=268435456;break;default:d=0}d=(d&(l.suspendedLanes|_))!==0?0:d,d!==0&&d!==m.retryLane&&(m.retryLane=d,yn(n,d),Ht(l,n,d,-1))}return $l(),l=vl(Error(i(421))),ia(n,o,_,l)}return d.data==="$?"?(o.flags|=128,o.child=n.child,o=z2.bind(null,n),d._reactRetry=o,null):(n=m.treeContext,Nt=Dn(d.nextSibling),Rt=o,$e=!0,Zt=null,n!==null&&(jt[At++]=gn,jt[At++]=hn,jt[At++]=lo,gn=n.id,hn=n.overflow,lo=o),o=Il(o,l.children),o.flags|=4096,o)}function tf(n,o,a){n.lanes|=o;var l=n.alternate;l!==null&&(l.lanes|=o),Qs(n.return,o,a)}function El(n,o,a,l,d){var m=n.memoizedState;m===null?n.memoizedState={isBackwards:o,rendering:null,renderingStartTime:0,last:l,tail:a,tailMode:d}:(m.isBackwards=o,m.rendering=null,m.renderingStartTime=0,m.last=l,m.tail=a,m.tailMode=d)}function nf(n,o,a){var l=o.pendingProps,d=l.revealOrder,m=l.tail;if(mt(n,o,l.children,a),l=qe.current,(l&2)!==0)l=l&1|2,o.flags|=128;else{if(n!==null&&(n.flags&128)!==0)e:for(n=o.child;n!==null;){if(n.tag===13)n.memoizedState!==null&&tf(n,a,o);else if(n.tag===19)tf(n,a,o);else if(n.child!==null){n.child.return=n,n=n.child;continue}if(n===o)break e;for(;n.sibling===null;){if(n.return===null||n.return===o)break e;n=n.return}n.sibling.return=n.return,n=n.sibling}l&=1}if(Re(qe,l),(o.mode&1)===0)o.memoizedState=null;else switch(d){case"forwards":for(a=o.child,d=null;a!==null;)n=a.alternate,n!==null&&Qi(n)===null&&(d=a),a=a.sibling;a=d,a===null?(d=o.child,o.child=null):(d=a.sibling,a.sibling=null),El(o,!1,d,a,m);break;case"backwards":for(a=null,d=o.child,o.child=null;d!==null;){if(n=d.alternate,n!==null&&Qi(n)===null){o.child=d;break}n=d.sibling,d.sibling=a,a=d,d=n}El(o,!0,a,null,m);break;case"together":El(o,!1,null,null,void 0);break;default:o.memoizedState=null}return o.child}function aa(n,o){(o.mode&1)===0&&n!==null&&(n.alternate=null,o.alternate=null,o.flags|=2)}function xn(n,o,a){if(n!==null&&(o.dependencies=n.dependencies),mo|=o.lanes,(a&o.childLanes)===0)return null;if(n!==null&&o.child!==n.child)throw Error(i(153));if(o.child!==null){for(n=o.child,a=Xn(n,n.pendingProps),o.child=a,a.return=o;n.sibling!==null;)n=n.sibling,a=a.sibling=Xn(n,n.pendingProps),a.return=o;a.sibling=null}return o.child}function g2(n,o,a){switch(o.tag){case 3:Qp(o),qo();break;case 5:gp(o);break;case 1:xt(o.type)&&Fi(o);break;case 4:tl(o,o.stateNode.containerInfo);break;case 10:var l=o.type._context,d=o.memoizedProps.value;Re(Hi,l._currentValue),l._currentValue=d;break;case 13:if(l=o.memoizedState,l!==null)return l.dehydrated!==null?(Re(qe,qe.current&1),o.flags|=128,null):(a&o.child.childLanes)!==0?ef(n,o,a):(Re(qe,qe.current&1),n=xn(n,o,a),n!==null?n.sibling:null);Re(qe,qe.current&1);break;case 19:if(l=(a&o.childLanes)!==0,(n.flags&128)!==0){if(l)return nf(n,o,a);o.flags|=128}if(d=o.memoizedState,d!==null&&(d.rendering=null,d.tail=null,d.lastEffect=null),Re(qe,qe.current),l)break;return null;case 22:case 23:return o.lanes=0,Xp(n,o,a)}return xn(n,o,a)}var of,wl,rf,af;of=function(n,o){for(var a=o.child;a!==null;){if(a.tag===5||a.tag===6)n.appendChild(a.stateNode);else if(a.tag!==4&&a.child!==null){a.child.return=a,a=a.child;continue}if(a===o)break;for(;a.sibling===null;){if(a.return===null||a.return===o)return;a=a.return}a.sibling.return=a.return,a=a.sibling}},wl=function(){},rf=function(n,o,a,l){var d=n.memoizedProps;if(d!==l){n=o.stateNode,po(nn.current);var m=null;switch(a){case"input":d=Qa(n,d),l=Qa(n,l),m=[];break;case"select":d=Y({},d,{value:void 0}),l=Y({},l,{value:void 0}),m=[];break;case"textarea":d=ts(n,d),l=ts(n,l),m=[];break;default:typeof d.onClick!="function"&&typeof l.onClick=="function"&&(n.onclick=Mi)}os(a,l);var _;a=null;for(A in d)if(!l.hasOwnProperty(A)&&d.hasOwnProperty(A)&&d[A]!=null)if(A==="style"){var E=d[A];for(_ in E)E.hasOwnProperty(_)&&(a||(a={}),a[_]="")}else A!=="dangerouslySetInnerHTML"&&A!=="children"&&A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&A!=="autoFocus"&&(u.hasOwnProperty(A)?m||(m=[]):(m=m||[]).push(A,null));for(A in l){var S=l[A];if(E=d?.[A],l.hasOwnProperty(A)&&S!==E&&(S!=null||E!=null))if(A==="style")if(E){for(_ in E)!E.hasOwnProperty(_)||S&&S.hasOwnProperty(_)||(a||(a={}),a[_]="");for(_ in S)S.hasOwnProperty(_)&&E[_]!==S[_]&&(a||(a={}),a[_]=S[_])}else a||(m||(m=[]),m.push(A,a)),a=S;else A==="dangerouslySetInnerHTML"?(S=S?S.__html:void 0,E=E?E.__html:void 0,S!=null&&E!==S&&(m=m||[]).push(A,S)):A==="children"?typeof S!="string"&&typeof S!="number"||(m=m||[]).push(A,""+S):A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&(u.hasOwnProperty(A)?(S!=null&&A==="onScroll"&&Pe("scroll",n),m||E===S||(m=[])):(m=m||[]).push(A,S))}a&&(m=m||[]).push("style",a);var A=m;(o.updateQueue=A)&&(o.flags|=4)}},af=function(n,o,a,l){a!==l&&(o.flags|=4)};function Gr(n,o){if(!$e)switch(n.tailMode){case"hidden":o=n.tail;for(var a=null;o!==null;)o.alternate!==null&&(a=o),o=o.sibling;a===null?n.tail=null:a.sibling=null;break;case"collapsed":a=n.tail;for(var l=null;a!==null;)a.alternate!==null&&(l=a),a=a.sibling;l===null?o||n.tail===null?n.tail=null:n.tail.sibling=null:l.sibling=null}}function ct(n){var o=n.alternate!==null&&n.alternate.child===n.child,a=0,l=0;if(o)for(var d=n.child;d!==null;)a|=d.lanes|d.childLanes,l|=d.subtreeFlags&14680064,l|=d.flags&14680064,d.return=n,d=d.sibling;else for(d=n.child;d!==null;)a|=d.lanes|d.childLanes,l|=d.subtreeFlags,l|=d.flags,d.return=n,d=d.sibling;return n.subtreeFlags|=l,n.childLanes=a,o}function h2(n,o,a){var l=o.pendingProps;switch(Vs(o),o.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return ct(o),null;case 1:return xt(o.type)&&qi(),ct(o),null;case 3:return l=o.stateNode,Vo(),je(_t),je(lt),rl(),l.pendingContext&&(l.context=l.pendingContext,l.pendingContext=null),(n===null||n.child===null)&&(Wi(o)?o.flags|=4:n===null||n.memoizedState.isDehydrated&&(o.flags&256)===0||(o.flags|=1024,Zt!==null&&(jl(Zt),Zt=null))),wl(n,o),ct(o),null;case 5:nl(o);var d=po(Fr.current);if(a=o.type,n!==null&&o.stateNode!=null)rf(n,o,a,l,d),n.ref!==o.ref&&(o.flags|=512,o.flags|=2097152);else{if(!l){if(o.stateNode===null)throw Error(i(166));return ct(o),null}if(n=po(nn.current),Wi(o)){l=o.stateNode,a=o.type;var m=o.memoizedProps;switch(l[tn]=o,l[$r]=m,n=(o.mode&1)!==0,a){case"dialog":Pe("cancel",l),Pe("close",l);break;case"iframe":case"object":case"embed":Pe("load",l);break;case"video":case"audio":for(d=0;d<\/script>",n=n.removeChild(n.firstChild)):typeof l.is=="string"?n=_.createElement(a,{is:l.is}):(n=_.createElement(a),a==="select"&&(_=n,l.multiple?_.multiple=!0:l.size&&(_.size=l.size))):n=_.createElementNS(n,a),n[tn]=o,n[$r]=l,of(n,o,!1,!1),o.stateNode=n;e:{switch(_=rs(a,l),a){case"dialog":Pe("cancel",n),Pe("close",n),d=l;break;case"iframe":case"object":case"embed":Pe("load",n),d=l;break;case"video":case"audio":for(d=0;dXo&&(o.flags|=128,l=!0,Gr(m,!1),o.lanes=4194304)}else{if(!l)if(n=Qi(_),n!==null){if(o.flags|=128,l=!0,a=n.updateQueue,a!==null&&(o.updateQueue=a,o.flags|=4),Gr(m,!0),m.tail===null&&m.tailMode==="hidden"&&!_.alternate&&!$e)return ct(o),null}else 2*He()-m.renderingStartTime>Xo&&a!==1073741824&&(o.flags|=128,l=!0,Gr(m,!1),o.lanes=4194304);m.isBackwards?(_.sibling=o.child,o.child=_):(a=m.last,a!==null?a.sibling=_:o.child=_,m.last=_)}return m.tail!==null?(o=m.tail,m.rendering=o,m.tail=o.sibling,m.renderingStartTime=He(),o.sibling=null,a=qe.current,Re(qe,l?a&1|2:a&1),o):(ct(o),null);case 22:case 23:return Ol(),l=o.memoizedState!==null,n!==null&&n.memoizedState!==null!==l&&(o.flags|=8192),l&&(o.mode&1)!==0?(Pt&1073741824)!==0&&(ct(o),o.subtreeFlags&6&&(o.flags|=8192)):ct(o),null;case 24:return null;case 25:return null}throw Error(i(156,o.tag))}function y2(n,o){switch(Vs(o),o.tag){case 1:return xt(o.type)&&qi(),n=o.flags,n&65536?(o.flags=n&-65537|128,o):null;case 3:return Vo(),je(_t),je(lt),rl(),n=o.flags,(n&65536)!==0&&(n&128)===0?(o.flags=n&-65537|128,o):null;case 5:return nl(o),null;case 13:if(je(qe),n=o.memoizedState,n!==null&&n.dehydrated!==null){if(o.alternate===null)throw Error(i(340));qo()}return n=o.flags,n&65536?(o.flags=n&-65537|128,o):null;case 19:return je(qe),null;case 4:return Vo(),null;case 10:return Js(o.type._context),null;case 22:case 23:return Ol(),null;case 24:return null;default:return null}}var sa=!1,dt=!1,_2=typeof WeakSet=="function"?WeakSet:Set,Q=null;function Go(n,o){var a=n.ref;if(a!==null)if(typeof a=="function")try{a(null)}catch(l){Ge(n,o,l)}else a.current=null}function Sl(n,o,a){try{a()}catch(l){Ge(n,o,l)}}var sf=!1;function x2(n,o){if(Os=Bi,n=Dd(),zs(n)){if("selectionStart"in n)var a={start:n.selectionStart,end:n.selectionEnd};else e:{a=(a=n.ownerDocument)&&a.defaultView||window;var l=a.getSelection&&a.getSelection();if(l&&l.rangeCount!==0){a=l.anchorNode;var d=l.anchorOffset,m=l.focusNode;l=l.focusOffset;try{a.nodeType,m.nodeType}catch{a=null;break e}var _=0,E=-1,S=-1,A=0,U=0,Z=n,q=null;t:for(;;){for(var K;Z!==a||d!==0&&Z.nodeType!==3||(E=_+d),Z!==m||l!==0&&Z.nodeType!==3||(S=_+l),Z.nodeType===3&&(_+=Z.nodeValue.length),(K=Z.firstChild)!==null;)q=Z,Z=K;for(;;){if(Z===n)break t;if(q===a&&++A===d&&(E=_),q===m&&++U===l&&(S=_),(K=Z.nextSibling)!==null)break;Z=q,q=Z.parentNode}Z=K}a=E===-1||S===-1?null:{start:E,end:S}}else a=null}a=a||{start:0,end:0}}else a=null;for($s={focusedElem:n,selectionRange:a},Bi=!1,Q=o;Q!==null;)if(o=Q,n=o.child,(o.subtreeFlags&1028)!==0&&n!==null)n.return=o,Q=n;else for(;Q!==null;){o=Q;try{var ne=o.alternate;if((o.flags&1024)!==0)switch(o.tag){case 0:case 11:case 15:break;case 1:if(ne!==null){var oe=ne.memoizedProps,Xe=ne.memoizedState,P=o.stateNode,B=P.getSnapshotBeforeUpdate(o.elementType===o.type?oe:Vt(o.type,oe),Xe);P.__reactInternalSnapshotBeforeUpdate=B}break;case 3:var j=o.stateNode.containerInfo;j.nodeType===1?j.textContent="":j.nodeType===9&&j.documentElement&&j.removeChild(j.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(i(163))}}catch(V){Ge(o,o.return,V)}if(n=o.sibling,n!==null){n.return=o.return,Q=n;break}Q=o.return}return ne=sf,sf=!1,ne}function Hr(n,o,a){var l=o.updateQueue;if(l=l!==null?l.lastEffect:null,l!==null){var d=l=l.next;do{if((d.tag&n)===n){var m=d.destroy;d.destroy=void 0,m!==void 0&&Sl(o,a,m)}d=d.next}while(d!==l)}}function la(n,o){if(o=o.updateQueue,o=o!==null?o.lastEffect:null,o!==null){var a=o=o.next;do{if((a.tag&n)===n){var l=a.create;a.destroy=l()}a=a.next}while(a!==o)}}function bl(n){var o=n.ref;if(o!==null){var a=n.stateNode;n.tag,n=a,typeof o=="function"?o(n):o.current=n}}function lf(n){var o=n.alternate;o!==null&&(n.alternate=null,lf(o)),n.child=null,n.deletions=null,n.sibling=null,n.tag===5&&(o=n.stateNode,o!==null&&(delete o[tn],delete o[$r],delete o[qs],delete o[n2],delete o[o2])),n.stateNode=null,n.return=null,n.dependencies=null,n.memoizedProps=null,n.memoizedState=null,n.pendingProps=null,n.stateNode=null,n.updateQueue=null}function uf(n){return n.tag===5||n.tag===3||n.tag===4}function cf(n){e:for(;;){for(;n.sibling===null;){if(n.return===null||uf(n.return))return null;n=n.return}for(n.sibling.return=n.return,n=n.sibling;n.tag!==5&&n.tag!==6&&n.tag!==18;){if(n.flags&2||n.child===null||n.tag===4)continue e;n.child.return=n,n=n.child}if(!(n.flags&2))return n.stateNode}}function kl(n,o,a){var l=n.tag;if(l===5||l===6)n=n.stateNode,o?a.nodeType===8?a.parentNode.insertBefore(n,o):a.insertBefore(n,o):(a.nodeType===8?(o=a.parentNode,o.insertBefore(n,a)):(o=a,o.appendChild(n)),a=a._reactRootContainer,a!=null||o.onclick!==null||(o.onclick=Mi));else if(l!==4&&(n=n.child,n!==null))for(kl(n,o,a),n=n.sibling;n!==null;)kl(n,o,a),n=n.sibling}function Bl(n,o,a){var l=n.tag;if(l===5||l===6)n=n.stateNode,o?a.insertBefore(n,o):a.appendChild(n);else if(l!==4&&(n=n.child,n!==null))for(Bl(n,o,a),n=n.sibling;n!==null;)Bl(n,o,a),n=n.sibling}var at=null,Wt=!1;function Zn(n,o,a){for(a=a.child;a!==null;)df(n,o,a),a=a.sibling}function df(n,o,a){if(en&&typeof en.onCommitFiberUnmount=="function")try{en.onCommitFiberUnmount(Ii,a)}catch{}switch(a.tag){case 5:dt||Go(a,o);case 6:var l=at,d=Wt;at=null,Zn(n,o,a),at=l,Wt=d,at!==null&&(Wt?(n=at,a=a.stateNode,n.nodeType===8?n.parentNode.removeChild(a):n.removeChild(a)):at.removeChild(a.stateNode));break;case 18:at!==null&&(Wt?(n=at,a=a.stateNode,n.nodeType===8?Ls(n.parentNode,a):n.nodeType===1&&Ls(n,a),kr(n)):Ls(at,a.stateNode));break;case 4:l=at,d=Wt,at=a.stateNode.containerInfo,Wt=!0,Zn(n,o,a),at=l,Wt=d;break;case 0:case 11:case 14:case 15:if(!dt&&(l=a.updateQueue,l!==null&&(l=l.lastEffect,l!==null))){d=l=l.next;do{var m=d,_=m.destroy;m=m.tag,_!==void 0&&((m&2)!==0||(m&4)!==0)&&Sl(a,o,_),d=d.next}while(d!==l)}Zn(n,o,a);break;case 1:if(!dt&&(Go(a,o),l=a.stateNode,typeof l.componentWillUnmount=="function"))try{l.props=a.memoizedProps,l.state=a.memoizedState,l.componentWillUnmount()}catch(E){Ge(a,o,E)}Zn(n,o,a);break;case 21:Zn(n,o,a);break;case 22:a.mode&1?(dt=(l=dt)||a.memoizedState!==null,Zn(n,o,a),dt=l):Zn(n,o,a);break;default:Zn(n,o,a)}}function pf(n){var o=n.updateQueue;if(o!==null){n.updateQueue=null;var a=n.stateNode;a===null&&(a=n.stateNode=new _2),o.forEach(function(l){var d=T2.bind(null,n,l);a.has(l)||(a.add(l),l.then(d,d))})}}function Gt(n,o){var a=o.deletions;if(a!==null)for(var l=0;ld&&(d=_),l&=~m}if(l=d,l=He()-l,l=(120>l?120:480>l?480:1080>l?1080:1920>l?1920:3e3>l?3e3:4320>l?4320:1960*E2(l/1960))-l,10n?16:n,Wn===null)var l=!1;else{if(n=Wn,Wn=null,fa=0,(_e&6)!==0)throw Error(i(331));var d=_e;for(_e|=4,Q=n.current;Q!==null;){var m=Q,_=m.child;if((Q.flags&16)!==0){var E=m.deletions;if(E!==null){for(var S=0;SHe()-Cl?go(n,0):Tl|=a),wt(n,o)}function bf(n,o){o===0&&((n.mode&1)===0?o=1:(o=wi,wi<<=1,(wi&130023424)===0&&(wi=4194304)));var a=vt();n=yn(n,o),n!==null&&(Ir(n,o,a),wt(n,a))}function z2(n){var o=n.memoizedState,a=0;o!==null&&(a=o.retryLane),bf(n,a)}function T2(n,o){var a=0;switch(n.tag){case 13:var l=n.stateNode,d=n.memoizedState;d!==null&&(a=d.retryLane);break;case 19:l=n.stateNode;break;default:throw Error(i(314))}l!==null&&l.delete(o),bf(n,a)}var kf;kf=function(n,o,a){if(n!==null)if(n.memoizedProps!==o.pendingProps||_t.current)It=!0;else{if((n.lanes&a)===0&&(o.flags&128)===0)return It=!1,g2(n,o,a);It=(n.flags&131072)!==0}else It=!1,$e&&(o.flags&1048576)!==0&&rp(o,Vi,o.index);switch(o.lanes=0,o.tag){case 2:var l=o.type;aa(n,o),n=o.pendingProps;var d=Do(o,lt.current);Zo(o,a),d=sl(null,o,l,n,d,a);var m=ll();return o.flags|=1,typeof d=="object"&&d!==null&&typeof d.render=="function"&&d.$$typeof===void 0?(o.tag=1,o.memoizedState=null,o.updateQueue=null,xt(l)?(m=!0,Fi(o)):m=!1,o.memoizedState=d.state!==null&&d.state!==void 0?d.state:null,el(o),d.updater=ra,o.stateNode=d,d._reactInternals=o,ml(o,l,n,a),o=yl(null,o,l,!0,m,a)):(o.tag=0,$e&&m&&Zs(o),mt(null,o,d,a),o=o.child),o;case 16:l=o.elementType;e:{switch(aa(n,o),n=o.pendingProps,d=l._init,l=d(l._payload),o.type=l,d=o.tag=R2(l),n=Vt(l,n),d){case 0:o=hl(null,o,l,n,a);break e;case 1:o=Jp(null,o,l,n,a);break e;case 11:o=Wp(null,o,l,n,a);break e;case 14:o=Gp(null,o,l,Vt(l.type,n),a);break e}throw Error(i(306,l,""))}return o;case 0:return l=o.type,d=o.pendingProps,d=o.elementType===l?d:Vt(l,d),hl(n,o,l,d,a);case 1:return l=o.type,d=o.pendingProps,d=o.elementType===l?d:Vt(l,d),Jp(n,o,l,d,a);case 3:e:{if(Qp(o),n===null)throw Error(i(387));l=o.pendingProps,m=o.memoizedState,d=m.element,fp(n,o),Ji(o,l,null,a);var _=o.memoizedState;if(l=_.element,m.isDehydrated)if(m={element:l,isDehydrated:!1,cache:_.cache,pendingSuspenseBoundaries:_.pendingSuspenseBoundaries,transitions:_.transitions},o.updateQueue.baseState=m,o.memoizedState=m,o.flags&256){d=Wo(Error(i(423)),o),o=Yp(n,o,l,a,d);break e}else if(l!==d){d=Wo(Error(i(424)),o),o=Yp(n,o,l,a,d);break e}else for(Nt=Dn(o.stateNode.containerInfo.firstChild),Rt=o,$e=!0,Zt=null,a=dp(o,null,l,a),o.child=a;a;)a.flags=a.flags&-3|4096,a=a.sibling;else{if(qo(),l===d){o=xn(n,o,a);break e}mt(n,o,l,a)}o=o.child}return o;case 5:return gp(o),n===null&&Gs(o),l=o.type,d=o.pendingProps,m=n!==null?n.memoizedProps:null,_=d.children,Ds(l,d)?_=null:m!==null&&Ds(l,m)&&(o.flags|=32),Kp(n,o),mt(n,o,_,a),o.child;case 6:return n===null&&Gs(o),null;case 13:return ef(n,o,a);case 4:return tl(o,o.stateNode.containerInfo),l=o.pendingProps,n===null?o.child=Fo(o,null,l,a):mt(n,o,l,a),o.child;case 11:return l=o.type,d=o.pendingProps,d=o.elementType===l?d:Vt(l,d),Wp(n,o,l,d,a);case 7:return mt(n,o,o.pendingProps,a),o.child;case 8:return mt(n,o,o.pendingProps.children,a),o.child;case 12:return mt(n,o,o.pendingProps.children,a),o.child;case 10:e:{if(l=o.type._context,d=o.pendingProps,m=o.memoizedProps,_=d.value,Re(Hi,l._currentValue),l._currentValue=_,m!==null)if(Ut(m.value,_)){if(m.children===d.children&&!_t.current){o=xn(n,o,a);break e}}else for(m=o.child,m!==null&&(m.return=o);m!==null;){var E=m.dependencies;if(E!==null){_=m.child;for(var S=E.firstContext;S!==null;){if(S.context===l){if(m.tag===1){S=_n(-1,a&-a),S.tag=2;var A=m.updateQueue;if(A!==null){A=A.shared;var U=A.pending;U===null?S.next=S:(S.next=U.next,U.next=S),A.pending=S}}m.lanes|=a,S=m.alternate,S!==null&&(S.lanes|=a),Qs(m.return,a,o),E.lanes|=a;break}S=S.next}}else if(m.tag===10)_=m.type===o.type?null:m.child;else if(m.tag===18){if(_=m.return,_===null)throw Error(i(341));_.lanes|=a,E=_.alternate,E!==null&&(E.lanes|=a),Qs(_,a,o),_=m.sibling}else _=m.child;if(_!==null)_.return=m;else for(_=m;_!==null;){if(_===o){_=null;break}if(m=_.sibling,m!==null){m.return=_.return,_=m;break}_=_.return}m=_}mt(n,o,d.children,a),o=o.child}return o;case 9:return d=o.type,l=o.pendingProps.children,Zo(o,a),d=Ot(d),l=l(d),o.flags|=1,mt(n,o,l,a),o.child;case 14:return l=o.type,d=Vt(l,o.pendingProps),d=Vt(l.type,d),Gp(n,o,l,d,a);case 15:return Hp(n,o,o.type,o.pendingProps,a);case 17:return l=o.type,d=o.pendingProps,d=o.elementType===l?d:Vt(l,d),aa(n,o),o.tag=1,xt(l)?(n=!0,Fi(o)):n=!1,Zo(o,a),Mp(o,l,d),ml(o,l,d,a),yl(null,o,l,!0,n,a);case 19:return nf(n,o,a);case 22:return Xp(n,o,a)}throw Error(i(156,o.tag))};function Bf(n,o){return id(n,o)}function C2(n,o,a,l){this.tag=n,this.key=a,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=o,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=l,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Mt(n,o,a,l){return new C2(n,o,a,l)}function Dl(n){return n=n.prototype,!(!n||!n.isReactComponent)}function R2(n){if(typeof n=="function")return Dl(n)?1:0;if(n!=null){if(n=n.$$typeof,n===Ae)return 11;if(n===zt)return 14}return 2}function Xn(n,o){var a=n.alternate;return a===null?(a=Mt(n.tag,o,n.key,n.mode),a.elementType=n.elementType,a.type=n.type,a.stateNode=n.stateNode,a.alternate=n,n.alternate=a):(a.pendingProps=o,a.type=n.type,a.flags=0,a.subtreeFlags=0,a.deletions=null),a.flags=n.flags&14680064,a.childLanes=n.childLanes,a.lanes=n.lanes,a.child=n.child,a.memoizedProps=n.memoizedProps,a.memoizedState=n.memoizedState,a.updateQueue=n.updateQueue,o=n.dependencies,a.dependencies=o===null?null:{lanes:o.lanes,firstContext:o.firstContext},a.sibling=n.sibling,a.index=n.index,a.ref=n.ref,a}function ha(n,o,a,l,d,m){var _=2;if(l=n,typeof n=="function")Dl(n)&&(_=1);else if(typeof n=="string")_=5;else e:switch(n){case ve:return yo(a.children,d,m,o);case pe:_=8,d|=8;break;case we:return n=Mt(12,a,o,d|2),n.elementType=we,n.lanes=m,n;case nt:return n=Mt(13,a,o,d),n.elementType=nt,n.lanes=m,n;case Ye:return n=Mt(19,a,o,d),n.elementType=Ye,n.lanes=m,n;case We:return ya(a,d,m,o);default:if(typeof n=="object"&&n!==null)switch(n.$$typeof){case Se:_=10;break e;case Ne:_=9;break e;case Ae:_=11;break e;case zt:_=14;break e;case yt:_=16,l=null;break e}throw Error(i(130,n==null?n:typeof n,""))}return o=Mt(_,a,o,d),o.elementType=n,o.type=l,o.lanes=m,o}function yo(n,o,a,l){return n=Mt(7,n,l,o),n.lanes=a,n}function ya(n,o,a,l){return n=Mt(22,n,l,o),n.elementType=We,n.lanes=a,n.stateNode={isHidden:!1},n}function Ml(n,o,a){return n=Mt(6,n,null,o),n.lanes=a,n}function Ll(n,o,a){return o=Mt(4,n.children!==null?n.children:[],n.key,o),o.lanes=a,o.stateNode={containerInfo:n.containerInfo,pendingChildren:null,implementation:n.implementation},o}function N2(n,o,a,l,d){this.tag=o,this.containerInfo=n,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=fs(0),this.expirationTimes=fs(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=fs(0),this.identifierPrefix=l,this.onRecoverableError=d,this.mutableSourceEagerHydrationData=null}function ql(n,o,a,l,d,m,_,E,S){return n=new N2(n,o,a,E,S),o===1?(o=1,m===!0&&(o|=8)):o=0,m=Mt(3,null,null,o),n.current=m,m.stateNode=n,m.memoizedState={element:l,isDehydrated:a,cache:null,transitions:null,pendingSuspenseBoundaries:null},el(m),n}function P2(n,o,a){var l=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(r){console.error(r)}}return t(),Gl.exports=W2(),Gl.exports}var qf;function G2(){if(qf)return ba;qf=1;var t=Mm();return ba.createRoot=t.createRoot,ba.hydrateRoot=t.hydrateRoot,ba}var H2=G2();const X2=$m(H2);Mm();function ri(){return ri=Object.assign?Object.assign.bind():function(t){for(var r=1;r"u")throw new Error(r)}function xu(t,r){if(!t){typeof console<"u"&&console.warn(r);try{throw new Error(r)}catch{}}}function J2(){return Math.random().toString(36).substr(2,8)}function Uf(t,r){return{usr:t.state,key:t.key,idx:r}}function nu(t,r,i,s){return i===void 0&&(i=null),ri({pathname:typeof t=="string"?t:t.pathname,search:"",hash:""},typeof r=="string"?ur(r):r,{state:i,key:r&&r.key||s||J2()})}function Pa(t){let{pathname:r="/",search:i="",hash:s=""}=t;return i&&i!=="?"&&(r+=i.charAt(0)==="?"?i:"?"+i),s&&s!=="#"&&(r+=s.charAt(0)==="#"?s:"#"+s),r}function ur(t){let r={};if(t){let i=t.indexOf("#");i>=0&&(r.hash=t.substr(i),t=t.substr(0,i));let s=t.indexOf("?");s>=0&&(r.search=t.substr(s),t=t.substr(0,s)),t&&(r.pathname=t)}return r}function Q2(t,r,i,s){s===void 0&&(s={});let{window:u=document.defaultView,v5Compat:f=!1}=s,p=u.history,v=Qn.Pop,x=null,I=w();I==null&&(I=0,p.replaceState(ri({},p.state,{idx:I}),""));function w(){return(p.state||{idx:null}).idx}function b(){v=Qn.Pop;let D=w(),G=D==null?null:D-I;I=D,x&&x({action:v,location:W.location,delta:G})}function C(D,G){v=Qn.Push;let ee=nu(W.location,D,G);I=w()+1;let J=Uf(ee,I),H=W.createHref(ee);try{p.pushState(J,"",H)}catch(te){if(te instanceof DOMException&&te.name==="DataCloneError")throw te;u.location.assign(H)}f&&x&&x({action:v,location:W.location,delta:1})}function O(D,G){v=Qn.Replace;let ee=nu(W.location,D,G);I=w();let J=Uf(ee,I),H=W.createHref(ee);p.replaceState(J,"",H),f&&x&&x({action:v,location:W.location,delta:0})}function L(D){let G=u.location.origin!=="null"?u.location.origin:u.location.href,ee=typeof D=="string"?D:Pa(D);return ee=ee.replace(/ $/,"%20"),Ze(G,"No window.location.(origin|href) available to create URL for href: "+ee),new URL(ee,G)}let W={get action(){return v},get location(){return t(u,p)},listen(D){if(x)throw new Error("A history only accepts one active listener");return u.addEventListener(Ff,b),x=D,()=>{u.removeEventListener(Ff,b),x=null}},createHref(D){return r(u,D)},createURL:L,encodeLocation(D){let G=L(D);return{pathname:G.pathname,search:G.search,hash:G.hash}},push:C,replace:O,go(D){return p.go(D)}};return W}var Zf;(function(t){t.data="data",t.deferred="deferred",t.redirect="redirect",t.error="error"})(Zf||(Zf={}));function Y2(t,r,i){return i===void 0&&(i="/"),e0(t,r,i)}function e0(t,r,i,s){let u=typeof r=="string"?ur(r):r,f=rr(u.pathname||"/",i);if(f==null)return null;let p=Lm(t);t0(p);let v=null,x=p0(f);for(let I=0;v==null&&I{let x={relativePath:v===void 0?f.path||"":v,caseSensitive:f.caseSensitive===!0,childrenIndex:p,route:f};x.relativePath.startsWith("/")&&(Ze(x.relativePath.startsWith(s),'Absolute route path "'+x.relativePath+'" nested under path '+('"'+s+'" is not valid. An absolute child route path ')+"must start with the combined path of all its parent routes."),x.relativePath=x.relativePath.slice(s.length));let I=eo([s,x.relativePath]),w=i.concat(x);f.children&&f.children.length>0&&(Ze(f.index!==!0,"Index routes must not have child routes. Please remove "+('all child routes from route path "'+I+'".')),Lm(f.children,r,w,I)),!(f.path==null&&!f.index)&&r.push({path:I,score:l0(I,f.index),routesMeta:w})};return t.forEach((f,p)=>{var v;if(f.path===""||!((v=f.path)!=null&&v.includes("?")))u(f,p);else for(let x of qm(f.path))u(f,p,x)}),r}function qm(t){let r=t.split("/");if(r.length===0)return[];let[i,...s]=r,u=i.endsWith("?"),f=i.replace(/\?$/,"");if(s.length===0)return u?[f,""]:[f];let p=qm(s.join("/")),v=[];return v.push(...p.map(x=>x===""?f:[f,x].join("/"))),u&&v.push(...p),v.map(x=>t.startsWith("/")&&x===""?"/":x)}function t0(t){t.sort((r,i)=>r.score!==i.score?i.score-r.score:u0(r.routesMeta.map(s=>s.childrenIndex),i.routesMeta.map(s=>s.childrenIndex)))}const n0=/^:[\w-]+$/,o0=3,r0=2,i0=1,a0=10,s0=-2,Vf=t=>t==="*";function l0(t,r){let i=t.split("/"),s=i.length;return i.some(Vf)&&(s+=s0),r&&(s+=r0),i.filter(u=>!Vf(u)).reduce((u,f)=>u+(n0.test(f)?o0:f===""?i0:a0),s)}function u0(t,r){return t.length===r.length&&t.slice(0,-1).every((s,u)=>s===r[u])?t[t.length-1]-r[r.length-1]:0}function c0(t,r,i){let{routesMeta:s}=t,u={},f="/",p=[];for(let v=0;v{let{paramName:C,isOptional:O}=w;if(C==="*"){let W=v[b]||"";p=f.slice(0,f.length-W.length).replace(/(.)\/+$/,"$1")}const L=v[b];return O&&!L?I[C]=void 0:I[C]=(L||"").replace(/%2F/g,"/"),I},{}),pathname:f,pathnameBase:p,pattern:t}}function d0(t,r,i){r===void 0&&(r=!1),i===void 0&&(i=!0),xu(t==="*"||!t.endsWith("*")||t.endsWith("/*"),'Route path "'+t+'" will be treated as if it were '+('"'+t.replace(/\*$/,"/*")+'" because the `*` character must ')+"always follow a `/` in the pattern. To get rid of this warning, "+('please change the route path to "'+t.replace(/\*$/,"/*")+'".'));let s=[],u="^"+t.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(p,v,x)=>(s.push({paramName:v,isOptional:x!=null}),x?"/?([^\\/]+)?":"/([^\\/]+)"));return t.endsWith("*")?(s.push({paramName:"*"}),u+=t==="*"||t==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):i?u+="\\/*$":t!==""&&t!=="/"&&(u+="(?:(?=\\/|$))"),[new RegExp(u,r?void 0:"i"),s]}function p0(t){try{return t.split("/").map(r=>decodeURIComponent(r).replace(/\//g,"%2F")).join("/")}catch(r){return xu(!1,'The URL path "'+t+'" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent '+("encoding ("+r+").")),t}}function rr(t,r){if(r==="/")return t;if(!t.toLowerCase().startsWith(r.toLowerCase()))return null;let i=r.endsWith("/")?r.length-1:r.length,s=t.charAt(i);return s&&s!=="/"?null:t.slice(i)||"/"}const f0=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,m0=t=>f0.test(t);function v0(t,r){r===void 0&&(r="/");let{pathname:i,search:s="",hash:u=""}=typeof t=="string"?ur(t):t,f;if(i)if(m0(i))f=i;else{if(i.includes("//")){let p=i;i=Fm(i),xu(!1,"Pathnames cannot have embedded double slashes - normalizing "+(p+" -> "+i))}i.startsWith("/")?f=Wf(i.substring(1),"/"):f=Wf(i,r)}else f=r;return{pathname:f,search:y0(s),hash:_0(u)}}function Wf(t,r){let i=r.replace(/\/+$/,"").split("/");return t.split("/").forEach(u=>{u===".."?i.length>1&&i.pop():u!=="."&&i.push(u)}),i.length>1?i.join("/"):"/"}function Kl(t,r,i,s){return"Cannot include a '"+t+"' character in a manually specified "+("`to."+r+"` field ["+JSON.stringify(s)+"]. Please separate it out to the ")+("`to."+i+"` field. Alternatively you may provide the full path as ")+'a string in and the router will parse it for you.'}function g0(t){return t.filter((r,i)=>i===0||r.route.path&&r.route.path.length>0)}function Iu(t,r){let i=g0(t);return r?i.map((s,u)=>u===i.length-1?s.pathname:s.pathnameBase):i.map(s=>s.pathnameBase)}function Eu(t,r,i,s){s===void 0&&(s=!1);let u;typeof t=="string"?u=ur(t):(u=ri({},t),Ze(!u.pathname||!u.pathname.includes("?"),Kl("?","pathname","search",u)),Ze(!u.pathname||!u.pathname.includes("#"),Kl("#","pathname","hash",u)),Ze(!u.search||!u.search.includes("#"),Kl("#","search","hash",u)));let f=t===""||u.pathname==="",p=f?"/":u.pathname,v;if(p==null)v=i;else{let b=r.length-1;if(!s&&p.startsWith("..")){let C=p.split("/");for(;C[0]==="..";)C.shift(),b-=1;u.pathname=C.join("/")}v=b>=0?r[b]:"/"}let x=v0(u,v),I=p&&p!=="/"&&p.endsWith("/"),w=(f||p===".")&&i.endsWith("/");return!x.pathname.endsWith("/")&&(I||w)&&(x.pathname+="/"),x}const Fm=t=>t.replace(/\/\/+/g,"/"),eo=t=>Fm(t.join("/")),h0=t=>t.replace(/\/+$/,"").replace(/^\/*/,"/"),y0=t=>!t||t==="?"?"":t.startsWith("?")?t:"?"+t,_0=t=>!t||t==="#"?"":t.startsWith("#")?t:"#"+t;function x0(t){return t!=null&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.internal=="boolean"&&"data"in t}const Um=["post","put","patch","delete"];new Set(Um);const I0=["get",...Um];new Set(I0);function ii(){return ii=Object.assign?Object.assign.bind():function(t){for(var r=1;r{v.current=!0}),T.useCallback(function(I,w){if(w===void 0&&(w={}),!v.current)return;if(typeof I=="number"){s.go(I);return}let b=Eu(I,JSON.parse(p),f,w.relative==="path");t==null&&r!=="/"&&(b.pathname=b.pathname==="/"?r:eo([r,b.pathname])),(w.replace?s.replace:s.push)(b,w.state,w)},[r,s,p,f,t])}function b9(){let{matches:t}=T.useContext(zn),r=t[t.length-1];return r?r.params:{}}function Fa(t,r){let{relative:i}=r===void 0?{}:r,{future:s}=T.useContext(Bn),{matches:u}=T.useContext(zn),{pathname:f}=Tn(),p=JSON.stringify(Iu(u,s.v7_relativeSplatPath));return T.useMemo(()=>Eu(t,JSON.parse(p),f,i==="path"),[t,p,f,i])}function S0(t,r){return b0(t,r)}function b0(t,r,i,s){cr()||Ze(!1);let{navigator:u}=T.useContext(Bn),{matches:f}=T.useContext(zn),p=f[f.length-1],v=p?p.params:{};p&&p.pathname;let x=p?p.pathnameBase:"/";p&&p.route;let I=Tn(),w;if(r){var b;let D=typeof r=="string"?ur(r):r;x==="/"||(b=D.pathname)!=null&&b.startsWith(x)||Ze(!1),w=D}else w=I;let C=w.pathname||"/",O=C;if(x!=="/"){let D=x.replace(/^\//,"").split("/");O="/"+C.replace(/^\//,"").split("/").slice(D.length).join("/")}let L=Y2(t,{pathname:O}),W=C0(L&&L.map(D=>Object.assign({},D,{params:Object.assign({},v,D.params),pathname:eo([x,u.encodeLocation?u.encodeLocation(D.pathname).pathname:D.pathname]),pathnameBase:D.pathnameBase==="/"?x:eo([x,u.encodeLocation?u.encodeLocation(D.pathnameBase).pathname:D.pathnameBase])})),f,i,s);return r&&W?T.createElement(qa.Provider,{value:{location:ii({pathname:"/",search:"",hash:"",state:null,key:"default"},w),navigationType:Qn.Pop}},W):W}function k0(){let t=j0(),r=x0(t)?t.status+" "+t.statusText:t instanceof Error?t.message:JSON.stringify(t),i=t instanceof Error?t.stack:null,u={padding:"0.5rem",backgroundColor:"rgba(200,200,200, 0.5)"};return T.createElement(T.Fragment,null,T.createElement("h2",null,"Unexpected Application Error!"),T.createElement("h3",{style:{fontStyle:"italic"}},r),i?T.createElement("pre",{style:u},i):null,null)}const B0=T.createElement(k0,null);class z0 extends T.Component{constructor(r){super(r),this.state={location:r.location,revalidation:r.revalidation,error:r.error}}static getDerivedStateFromError(r){return{error:r}}static getDerivedStateFromProps(r,i){return i.location!==r.location||i.revalidation!=="idle"&&r.revalidation==="idle"?{error:r.error,location:r.location,revalidation:r.revalidation}:{error:r.error!==void 0?r.error:i.error,location:i.location,revalidation:r.revalidation||i.revalidation}}componentDidCatch(r,i){console.error("React Router caught the following error during render",r,i)}render(){return this.state.error!==void 0?T.createElement(zn.Provider,{value:this.props.routeContext},T.createElement(Vm.Provider,{value:this.state.error,children:this.props.component})):this.props.children}}function T0(t){let{routeContext:r,match:i,children:s}=t,u=T.useContext(La);return u&&u.static&&u.staticContext&&(i.route.errorElement||i.route.ErrorBoundary)&&(u.staticContext._deepestRenderedBoundaryId=i.route.id),T.createElement(zn.Provider,{value:r},s)}function C0(t,r,i,s){var u;if(r===void 0&&(r=[]),i===void 0&&(i=null),s===void 0&&(s=null),t==null){var f;if(!i)return null;if(i.errors)t=i.matches;else if((f=s)!=null&&f.v7_partialHydration&&r.length===0&&!i.initialized&&i.matches.length>0)t=i.matches;else return null}let p=t,v=(u=i)==null?void 0:u.errors;if(v!=null){let w=p.findIndex(b=>b.route.id&&v?.[b.route.id]!==void 0);w>=0||Ze(!1),p=p.slice(0,Math.min(p.length,w+1))}let x=!1,I=-1;if(i&&s&&s.v7_partialHydration)for(let w=0;w=0?p=p.slice(0,I+1):p=[p[0]];break}}}return p.reduceRight((w,b,C)=>{let O,L=!1,W=null,D=null;i&&(O=v&&b.route.id?v[b.route.id]:void 0,W=b.route.errorElement||B0,x&&(I<0&&C===0?(O0("route-fallback"),L=!0,D=null):I===C&&(L=!0,D=b.route.hydrateFallbackElement||null)));let G=r.concat(p.slice(0,C+1)),ee=()=>{let J;return O?J=W:L?J=D:b.route.Component?J=T.createElement(b.route.Component,null):b.route.element?J=b.route.element:J=w,T.createElement(T0,{match:b,routeContext:{outlet:w,matches:G,isDataRoute:i!=null},children:J})};return i&&(b.route.ErrorBoundary||b.route.errorElement||C===0)?T.createElement(z0,{location:i.location,revalidation:i.revalidation,component:W,error:O,children:ee(),routeContext:{outlet:null,matches:G,isDataRoute:!0}}):ee()},null)}var Gm=(function(t){return t.UseBlocker="useBlocker",t.UseRevalidator="useRevalidator",t.UseNavigateStable="useNavigate",t})(Gm||{}),Hm=(function(t){return t.UseBlocker="useBlocker",t.UseLoaderData="useLoaderData",t.UseActionData="useActionData",t.UseRouteError="useRouteError",t.UseNavigation="useNavigation",t.UseRouteLoaderData="useRouteLoaderData",t.UseMatches="useMatches",t.UseRevalidator="useRevalidator",t.UseNavigateStable="useNavigate",t.UseRouteId="useRouteId",t})(Hm||{});function R0(t){let r=T.useContext(La);return r||Ze(!1),r}function N0(t){let r=T.useContext(Zm);return r||Ze(!1),r}function P0(t){let r=T.useContext(zn);return r||Ze(!1),r}function Xm(t){let r=P0(),i=r.matches[r.matches.length-1];return i.route.id||Ze(!1),i.route.id}function j0(){var t;let r=T.useContext(Vm),i=N0(),s=Xm();return r!==void 0?r:(t=i.errors)==null?void 0:t[s]}function A0(){let{router:t}=R0(Gm.UseNavigateStable),r=Xm(Hm.UseNavigateStable),i=T.useRef(!1);return Wm(()=>{i.current=!0}),T.useCallback(function(u,f){f===void 0&&(f={}),i.current&&(typeof u=="number"?t.navigate(u):t.navigate(u,ii({fromRouteId:r},f)))},[t,r])}const Gf={};function O0(t,r,i){Gf[t]||(Gf[t]=!0)}function $0(t,r){t?.v7_startTransition,t?.v7_relativeSplatPath}function D0(t){let{to:r,replace:i,state:s,relative:u}=t;cr()||Ze(!1);let{future:f,static:p}=T.useContext(Bn),{matches:v}=T.useContext(zn),{pathname:x}=Tn(),I=wu(),w=Eu(r,Iu(v,f.v7_relativeSplatPath),x,u==="path"),b=JSON.stringify(w);return T.useEffect(()=>I(JSON.parse(b),{replace:i,state:s,relative:u}),[I,b,u,i,s]),null}function an(t){Ze(!1)}function M0(t){let{basename:r="/",children:i=null,location:s,navigationType:u=Qn.Pop,navigator:f,static:p=!1,future:v}=t;cr()&&Ze(!1);let x=r.replace(/^\/*/,"/"),I=T.useMemo(()=>({basename:x,navigator:f,static:p,future:ii({v7_relativeSplatPath:!1},v)}),[x,v,f,p]);typeof s=="string"&&(s=ur(s));let{pathname:w="/",search:b="",hash:C="",state:O=null,key:L="default"}=s,W=T.useMemo(()=>{let D=rr(w,x);return D==null?null:{location:{pathname:D,search:b,hash:C,state:O,key:L},navigationType:u}},[x,w,b,C,O,L,u]);return W==null?null:T.createElement(Bn.Provider,{value:I},T.createElement(qa.Provider,{children:i,value:W}))}function L0(t){let{children:r,location:i}=t;return S0(ru(r),i)}new Promise(()=>{});function ru(t,r){r===void 0&&(r=[]);let i=[];return T.Children.forEach(t,(s,u)=>{if(!T.isValidElement(s))return;let f=[...r,u];if(s.type===T.Fragment){i.push.apply(i,ru(s.props.children,f));return}s.type!==an&&Ze(!1),!s.props.index||!s.props.children||Ze(!1);let p={id:s.props.id||f.join("-"),caseSensitive:s.props.caseSensitive,element:s.props.element,Component:s.props.Component,index:s.props.index,path:s.props.path,loader:s.props.loader,action:s.props.action,errorElement:s.props.errorElement,ErrorBoundary:s.props.ErrorBoundary,hasErrorBoundary:s.props.ErrorBoundary!=null||s.props.errorElement!=null,shouldRevalidate:s.props.shouldRevalidate,handle:s.props.handle,lazy:s.props.lazy};s.props.children&&(p.children=ru(s.props.children,f)),i.push(p)}),i}function ja(){return ja=Object.assign?Object.assign.bind():function(t){for(var r=1;r{let s=t[i];return r.concat(Array.isArray(s)?s.map(u=>[i,u]):[[i,s]])},[]))}function U0(t,r){let i=iu(t);return r&&r.forEach((s,u)=>{i.has(u)||r.getAll(u).forEach(f=>{i.append(u,f)})}),i}const Z0=["onClick","relative","reloadDocument","replace","state","target","to","preventScrollReset","viewTransition"],V0=["aria-current","caseSensitive","className","end","style","to","viewTransition","children"],W0="6";try{window.__reactRouterVersion=W0}catch{}const G0=T.createContext({isTransitioning:!1}),H0="startTransition",Hf=U2[H0];function X0(t){let{basename:r,children:i,future:s,window:u}=t,f=T.useRef();f.current==null&&(f.current=K2({window:u,v5Compat:!0}));let p=f.current,[v,x]=T.useState({action:p.action,location:p.location}),{v7_startTransition:I}=s||{},w=T.useCallback(b=>{I&&Hf?Hf(()=>x(b)):x(b)},[x,I]);return T.useLayoutEffect(()=>p.listen(w),[p,w]),T.useEffect(()=>$0(s),[s]),T.createElement(M0,{basename:r,children:i,location:v.location,navigationType:v.action,navigator:p,future:s})}const K0=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u",J0=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Q0=T.forwardRef(function(r,i){let{onClick:s,relative:u,reloadDocument:f,replace:p,state:v,target:x,to:I,preventScrollReset:w,viewTransition:b}=r,C=Km(r,Z0),{basename:O}=T.useContext(Bn),L,W=!1;if(typeof I=="string"&&J0.test(I)&&(L=I,K0))try{let J=new URL(window.location.href),H=I.startsWith("//")?new URL(J.protocol+I):new URL(I),te=rr(H.pathname,O);H.origin===J.origin&&te!=null?I=te+H.search+H.hash:W=!0}catch{}let D=E0(I,{relative:u}),G=t3(I,{replace:p,state:v,target:x,preventScrollReset:w,relative:u,viewTransition:b});function ee(J){s&&s(J),J.defaultPrevented||G(J)}return T.createElement("a",ja({},C,{href:L||D,onClick:W||f?s:ee,ref:i,target:x}))}),Y0=T.forwardRef(function(r,i){let{"aria-current":s="page",caseSensitive:u=!1,className:f="",end:p=!1,style:v,to:x,viewTransition:I,children:w}=r,b=Km(r,V0),C=Fa(x,{relative:b.relative}),O=Tn(),L=T.useContext(Zm),{navigator:W,basename:D}=T.useContext(Bn),G=L!=null&&n3(C)&&I===!0,ee=W.encodeLocation?W.encodeLocation(C).pathname:C.pathname,J=O.pathname,H=L&&L.navigation&&L.navigation.location?L.navigation.location.pathname:null;u||(J=J.toLowerCase(),H=H?H.toLowerCase():null,ee=ee.toLowerCase()),H&&D&&(H=rr(H,D)||H);const te=ee!=="/"&&ee.endsWith("/")?ee.length-1:ee.length;let ue=J===ee||!p&&J.startsWith(ee)&&J.charAt(te)==="/",ve=H!=null&&(H===ee||!p&&H.startsWith(ee)&&H.charAt(ee.length)==="/"),pe={isActive:ue,isPending:ve,isTransitioning:G},we=ue?s:void 0,Se;typeof f=="function"?Se=f(pe):Se=[f,ue?"active":null,ve?"pending":null,G?"transitioning":null].filter(Boolean).join(" ");let Ne=typeof v=="function"?v(pe):v;return T.createElement(Q0,ja({},b,{"aria-current":we,className:Se,ref:i,style:Ne,to:x,viewTransition:I}),typeof w=="function"?w(pe):w)});var au;(function(t){t.UseScrollRestoration="useScrollRestoration",t.UseSubmit="useSubmit",t.UseSubmitFetcher="useSubmitFetcher",t.UseFetcher="useFetcher",t.useViewTransitionState="useViewTransitionState"})(au||(au={}));var Xf;(function(t){t.UseFetcher="useFetcher",t.UseFetchers="useFetchers",t.UseScrollRestoration="useScrollRestoration"})(Xf||(Xf={}));function e3(t){let r=T.useContext(La);return r||Ze(!1),r}function t3(t,r){let{target:i,replace:s,state:u,preventScrollReset:f,relative:p,viewTransition:v}=r===void 0?{}:r,x=wu(),I=Tn(),w=Fa(t,{relative:p});return T.useCallback(b=>{if(F0(b,i)){b.preventDefault();let C=s!==void 0?s:Pa(I)===Pa(w);x(t,{replace:C,state:u,preventScrollReset:f,relative:p,viewTransition:v})}},[I,x,w,s,u,i,t,f,p,v])}function k9(t){let r=T.useRef(iu(t)),i=T.useRef(!1),s=Tn(),u=T.useMemo(()=>U0(s.search,i.current?null:r.current),[s.search]),f=wu(),p=T.useCallback((v,x)=>{const I=iu(typeof v=="function"?v(u):v);i.current=!0,f("?"+I,x)},[f,u]);return[u,p]}function n3(t,r){r===void 0&&(r={});let i=T.useContext(G0);i==null&&Ze(!1);let{basename:s}=e3(au.useViewTransitionState),u=Fa(t,{relative:r.relative});if(!i.isTransitioning)return!1;let f=rr(i.currentLocation.pathname,s)||i.currentLocation.pathname,p=rr(i.nextLocation.pathname,s)||i.nextLocation.pathname;return ou(u.pathname,p)!=null||ou(u.pathname,f)!=null}const o3=new Set(["failed","errored","stuck","crashed"]),r3=new Set(["rate-limited","rate_limited","waiting"]),i3={"awaiting-input":"respond",errored:"reset","rate-limited":"nudge",stalled:"nudge"};function a3(t,r){const i=new Map;for(const u of r)i.set(u.agentName,u.prompt);const s=[];for(const u of t){const f=i.has(u.name),p=s3(u,f);p!==null&&s.push({name:u.name,reason:p,detail:u3(u,p,i.get(u.name)),action:i3[p]})}return s}function s3(t,r){if(r)return"awaiting-input";const i=t.state.toLowerCase();return o3.has(i)?"errored":r3.has(i)?"rate-limited":l3(t,i)?"stalled":null}function l3(t,r){return r==="detached"?!0:t.running&&t.session===void 0}function u3(t,r,i){switch(r){case"awaiting-input":return c3(i);case"errored":return`Exited ${t.state}.`;case"rate-limited":return"Throttled by a provider limit.";case"stalled":return t.state.toLowerCase()==="detached"?"Detached from its session.":"Running with no live session."}}function c3(t){if(t===void 0)return"Awaiting your decision.";const r=t.split(` `,1)[0]?.trim()??"";return r.length>0?r:"Awaiting your decision."}function d3(t){return t.filter(r=>r.phase==="blocked").map(r=>({id:r.id,title:r.title,reason:p3(r),remedy:f3(r),scope:r.scope}))}function p3(t){const r=m3(t);if(r!==null)return`Blocked at ${r}`;const i=t.statusCounts.blocked??0;return i>0?`${i} blocked step${i===1?"":"s"}`:"Blocked, awaiting operator"}function f3(t){return t.activeAssignees.length===0?"No worker assigned. Claim or dispatch one.":"Open run detail to review the blocked step."}function m3(t){if(t.progress.status==="active_step"||t.progress.status==="stage_only"){const r=t.progress.stage;if(r.status==="available")return r.label}return null}const Jm=/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/i,v3={bead:"bead.",session:"session."};function Yo(t){return t instanceof Error?t.message:typeof t=="string"?t:"unknown error"}function g3(t){if(!t)return"";let r=t.length;for(;r>0&&t.charCodeAt(r-1)===47;)r--;const i=t.slice(0,r);return i.slice(i.lastIndexOf("/")+1)||i}const h3="polecat";function y3(t){return g3(t).toLowerCase().includes(h3)}function _3(t){return t.filter(r=>!r.read&&!y3(r.from))}var Kf;function $(t,r,i){function s(v,x){if(v._zod||Object.defineProperty(v,"_zod",{value:{def:x,constr:p,traits:new Set},enumerable:!1}),v._zod.traits.has(t))return;v._zod.traits.add(t),r(v,x);const I=p.prototype,w=Object.keys(I);for(let b=0;bi?.Parent&&v instanceof i.Parent?!0:v?._zod?.traits?.has(t)}),Object.defineProperty(p,"name",{value:t}),p}class er extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}class Qm extends Error{constructor(r){super(`Encountered unidirectional transform during encode: ${r}`),this.name="ZodEncodeError"}}(Kf=globalThis).__zod_globalConfig??(Kf.__zod_globalConfig={});const Su=globalThis.__zod_globalConfig;function bn(t){return Su}function Ym(t){const r=Object.values(t).filter(s=>typeof s=="number");return Object.entries(t).filter(([s,u])=>r.indexOf(+s)===-1).map(([s,u])=>u)}function su(t,r){return typeof r=="bigint"?r.toString():r}function Ua(t){return{get value(){{const r=t();return Object.defineProperty(this,"value",{value:r}),r}}}}function bu(t){return t==null}function ku(t){const r=t.startsWith("^")?1:0,i=t.endsWith("$")?t.length-1:t.length;return t.slice(r,i)}function x3(t,r){const i=t/r,s=Math.round(i),u=Number.EPSILON*Math.max(Math.abs(i),1);return Math.abs(i-s){};function ai(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}const E3=Ua(()=>{if(Su.jitless||typeof navigator<"u"&&navigator?.userAgent?.includes("Cloudflare"))return!1;try{const t=Function;return new t(""),!0}catch{return!1}});function ir(t){if(ai(t)===!1)return!1;const r=t.constructor;if(r===void 0||typeof r!="function")return!0;const i=r.prototype;return!(ai(i)===!1||Object.prototype.hasOwnProperty.call(i,"isPrototypeOf")===!1)}function t7(t){return ir(t)?{...t}:Array.isArray(t)?[...t]:t instanceof Map?new Map(t):t instanceof Set?new Set(t):t}const w3=new Set(["string","number","symbol"]);function ar(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ro(t,r,i){const s=new t._zod.constr(r??t._zod.def);return(!r||i?.parent)&&(s._zod.parent=t),s}function ie(t){const r=t;if(!r)return{};if(typeof r=="string")return{error:()=>r};if(r?.message!==void 0){if(r?.error!==void 0)throw new Error("Cannot specify both `message` and `error` params");r.error=r.message}return delete r.message,typeof r.error=="string"?{...r,error:()=>r.error}:r}function S3(t){return Object.keys(t).filter(r=>t[r]._zod.optin==="optional"&&t[r]._zod.optout==="optional")}const b3={safeint:[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-34028234663852886e22,34028234663852886e22],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]};function k3(t,r){const i=t._zod.def,s=i.checks;if(s&&s.length>0)throw new Error(".pick() cannot be used on object schemas containing refinements");const f=oo(t._zod.def,{get shape(){const p={};for(const v in r){if(!(v in i.shape))throw new Error(`Unrecognized key: "${v}"`);r[v]&&(p[v]=i.shape[v])}return wo(this,"shape",p),p},checks:[]});return ro(t,f)}function B3(t,r){const i=t._zod.def,s=i.checks;if(s&&s.length>0)throw new Error(".omit() cannot be used on object schemas containing refinements");const f=oo(t._zod.def,{get shape(){const p={...t._zod.def.shape};for(const v in r){if(!(v in i.shape))throw new Error(`Unrecognized key: "${v}"`);r[v]&&delete p[v]}return wo(this,"shape",p),p},checks:[]});return ro(t,f)}function z3(t,r){if(!ir(r))throw new Error("Invalid input to extend: expected a plain object");const i=t._zod.def.checks;if(i&&i.length>0){const f=t._zod.def.shape;for(const p in r)if(Object.getOwnPropertyDescriptor(f,p)!==void 0)throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.")}const u=oo(t._zod.def,{get shape(){const f={...t._zod.def.shape,...r};return wo(this,"shape",f),f}});return ro(t,u)}function T3(t,r){if(!ir(r))throw new Error("Invalid input to safeExtend: expected a plain object");const i=oo(t._zod.def,{get shape(){const s={...t._zod.def.shape,...r};return wo(this,"shape",s),s}});return ro(t,i)}function C3(t,r){if(t._zod.def.checks?.length)throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");const i=oo(t._zod.def,{get shape(){const s={...t._zod.def.shape,...r._zod.def.shape};return wo(this,"shape",s),s},get catchall(){return r._zod.def.catchall},checks:r._zod.def.checks??[]});return ro(t,i)}function R3(t,r,i){const u=r._zod.def.checks;if(u&&u.length>0)throw new Error(".partial() cannot be used on object schemas containing refinements");const p=oo(r._zod.def,{get shape(){const v=r._zod.def.shape,x={...v};if(i)for(const I in i){if(!(I in v))throw new Error(`Unrecognized key: "${I}"`);i[I]&&(x[I]=t?new t({type:"optional",innerType:v[I]}):v[I])}else for(const I in v)x[I]=t?new t({type:"optional",innerType:v[I]}):v[I];return wo(this,"shape",x),x},checks:[]});return ro(r,p)}function N3(t,r,i){const s=oo(r._zod.def,{get shape(){const u=r._zod.def.shape,f={...u};if(i)for(const p in i){if(!(p in f))throw new Error(`Unrecognized key: "${p}"`);i[p]&&(f[p]=new t({type:"nonoptional",innerType:u[p]}))}else for(const p in u)f[p]=new t({type:"nonoptional",innerType:u[p]});return wo(this,"shape",f),f}});return ro(r,s)}function Jo(t,r=0){if(t.aborted===!0)return!0;for(let i=r;i{var s;return(s=i).path??(s.path=[]),i.path.unshift(t),i})}function ka(t){return typeof t=="string"?t:t?.message}function kn(t,r,i){const s=t.message?t.message:ka(t.inst?._zod.def?.error?.(t))??ka(r?.error?.(t))??ka(i.customError?.(t))??ka(i.localeError?.(t))??"Invalid input",{inst:u,continue:f,input:p,...v}=t;return v.path??(v.path=[]),v.message=s,r?.reportInput&&(v.input=p),v}function Bu(t){return Array.isArray(t)?"array":typeof t=="string"?"string":"unknown"}function si(...t){const[r,i,s]=t;return typeof r=="string"?{message:r,code:"custom",input:i,inst:s}:{...r}}const n7=(t,r)=>{t.name="$ZodError",Object.defineProperty(t,"_zod",{value:t._zod,enumerable:!1}),Object.defineProperty(t,"issues",{value:r,enumerable:!1}),t.message=JSON.stringify(r,su,2),Object.defineProperty(t,"toString",{value:()=>t.message,enumerable:!1})},o7=$("$ZodError",n7),r7=$("$ZodError",n7,{Parent:Error});function j3(t,r=i=>i.message){const i={},s=[];for(const u of t.issues)u.path.length>0?(i[u.path[0]]=i[u.path[0]]||[],i[u.path[0]].push(r(u))):s.push(r(u));return{formErrors:s,fieldErrors:i}}function A3(t,r=i=>i.message){const i={_errors:[]},s=(u,f=[])=>{for(const p of u.issues)if(p.code==="invalid_union"&&p.errors.length)p.errors.map(v=>s({issues:v},[...f,...p.path]));else if(p.code==="invalid_key")s({issues:p.issues},[...f,...p.path]);else if(p.code==="invalid_element")s({issues:p.issues},[...f,...p.path]);else{const v=[...f,...p.path];if(v.length===0)i._errors.push(r(p));else{let x=i,I=0;for(;I(r,i,s,u)=>{const f=s?{...s,async:!1}:{async:!1},p=r._zod.run({value:i,issues:[]},f);if(p instanceof Promise)throw new er;if(p.issues.length){const v=new(u?.Err??t)(p.issues.map(x=>kn(x,f,bn())));throw e7(v,u?.callee),v}return p.value},Tu=t=>async(r,i,s,u)=>{const f=s?{...s,async:!0}:{async:!0};let p=r._zod.run({value:i,issues:[]},f);if(p instanceof Promise&&(p=await p),p.issues.length){const v=new(u?.Err??t)(p.issues.map(x=>kn(x,f,bn())));throw e7(v,u?.callee),v}return p.value},Za=t=>(r,i,s)=>{const u=s?{...s,async:!1}:{async:!1},f=r._zod.run({value:i,issues:[]},u);if(f instanceof Promise)throw new er;return f.issues.length?{success:!1,error:new(t??o7)(f.issues.map(p=>kn(p,u,bn())))}:{success:!0,data:f.value}},O3=Za(r7),Va=t=>async(r,i,s)=>{const u=s?{...s,async:!0}:{async:!0};let f=r._zod.run({value:i,issues:[]},u);return f instanceof Promise&&(f=await f),f.issues.length?{success:!1,error:new t(f.issues.map(p=>kn(p,u,bn())))}:{success:!0,data:f.value}},$3=Va(r7),D3=t=>(r,i,s)=>{const u=s?{...s,direction:"backward"}:{direction:"backward"};return zu(t)(r,i,u)},M3=t=>(r,i,s)=>zu(t)(r,i,s),L3=t=>async(r,i,s)=>{const u=s?{...s,direction:"backward"}:{direction:"backward"};return Tu(t)(r,i,u)},q3=t=>async(r,i,s)=>Tu(t)(r,i,s),F3=t=>(r,i,s)=>{const u=s?{...s,direction:"backward"}:{direction:"backward"};return Za(t)(r,i,u)},U3=t=>(r,i,s)=>Za(t)(r,i,s),Z3=t=>async(r,i,s)=>{const u=s?{...s,direction:"backward"}:{direction:"backward"};return Va(t)(r,i,u)},V3=t=>async(r,i,s)=>Va(t)(r,i,s),W3=/^[cC][0-9a-z]{6,}$/,G3=/^[0-9a-z]+$/,H3=/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/,X3=/^[0-9a-vA-V]{20}$/,K3=/^[A-Za-z0-9]{27}$/,J3=/^[a-zA-Z0-9_-]{21}$/,Q3=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,Y3=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,Yf=t=>t?new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${t}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,eh=/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/,th="^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$";function nh(){return new RegExp(th,"u")}const oh=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,rh=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/,ih=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,ah=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,sh=/^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,i7=/^[A-Za-z0-9_-]*$/,lh=/^https?$/,uh=/^\+[1-9]\d{6,14}$/,a7="(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))",ch=new RegExp(`^${a7}$`);function s7(t){const r="(?:[01]\\d|2[0-3]):[0-5]\\d";return typeof t.precision=="number"?t.precision===-1?`${r}`:t.precision===0?`${r}:[0-5]\\d`:`${r}:[0-5]\\d\\.\\d{${t.precision}}`:`${r}(?::[0-5]\\d(?:\\.\\d+)?)?`}function dh(t){return new RegExp(`^${s7(t)}$`)}function ph(t){const r=s7({precision:t.precision}),i=["Z"];t.local&&i.push(""),t.offset&&i.push("([+-](?:[01]\\d|2[0-3]):[0-5]\\d)");const s=`${r}(?:${i.join("|")})`;return new RegExp(`^${a7}T(?:${s})$`)}const fh=t=>{const r=t?`[\\s\\S]{${t?.minimum??0},${t?.maximum??""}}`:"[\\s\\S]*";return new RegExp(`^${r}$`)},mh=/^-?\d+n?$/,vh=/^-?\d+$/,l7=/^-?\d+(?:\.\d+)?$/,gh=/^(?:true|false)$/i,hh=/^[^A-Z]*$/,yh=/^[^a-z]*$/,Bt=$("$ZodCheck",(t,r)=>{var i;t._zod??(t._zod={}),t._zod.def=r,(i=t._zod).onattach??(i.onattach=[])}),u7={number:"number",bigint:"bigint",object:"date"},c7=$("$ZodCheckLessThan",(t,r)=>{Bt.init(t,r);const i=u7[typeof r.value];t._zod.onattach.push(s=>{const u=s._zod.bag,f=(r.inclusive?u.maximum:u.exclusiveMaximum)??Number.POSITIVE_INFINITY;r.value{(r.inclusive?s.value<=r.value:s.value{Bt.init(t,r);const i=u7[typeof r.value];t._zod.onattach.push(s=>{const u=s._zod.bag,f=(r.inclusive?u.minimum:u.exclusiveMinimum)??Number.NEGATIVE_INFINITY;r.value>f&&(r.inclusive?u.minimum=r.value:u.exclusiveMinimum=r.value)}),t._zod.check=s=>{(r.inclusive?s.value>=r.value:s.value>r.value)||s.issues.push({origin:i,code:"too_small",minimum:typeof r.value=="object"?r.value.getTime():r.value,input:s.value,inclusive:r.inclusive,inst:t,continue:!r.abort})}}),_h=$("$ZodCheckMultipleOf",(t,r)=>{Bt.init(t,r),t._zod.onattach.push(i=>{var s;(s=i._zod.bag).multipleOf??(s.multipleOf=r.value)}),t._zod.check=i=>{if(typeof i.value!=typeof r.value)throw new Error("Cannot mix number and bigint in multiple_of check.");(typeof i.value=="bigint"?i.value%r.value===BigInt(0):x3(i.value,r.value)===0)||i.issues.push({origin:typeof i.value,code:"not_multiple_of",divisor:r.value,input:i.value,inst:t,continue:!r.abort})}}),xh=$("$ZodCheckNumberFormat",(t,r)=>{Bt.init(t,r),r.format=r.format||"float64";const i=r.format?.includes("int"),s=i?"int":"number",[u,f]=b3[r.format];t._zod.onattach.push(p=>{const v=p._zod.bag;v.format=r.format,v.minimum=u,v.maximum=f,i&&(v.pattern=vh)}),t._zod.check=p=>{const v=p.value;if(i){if(!Number.isInteger(v)){p.issues.push({expected:s,format:r.format,code:"invalid_type",continue:!1,input:v,inst:t});return}if(!Number.isSafeInteger(v)){v>0?p.issues.push({input:v,code:"too_big",maximum:Number.MAX_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:t,origin:s,inclusive:!0,continue:!r.abort}):p.issues.push({input:v,code:"too_small",minimum:Number.MIN_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:t,origin:s,inclusive:!0,continue:!r.abort});return}}vf&&p.issues.push({origin:"number",input:v,code:"too_big",maximum:f,inclusive:!0,inst:t,continue:!r.abort})}}),Ih=$("$ZodCheckMaxLength",(t,r)=>{var i;Bt.init(t,r),(i=t._zod.def).when??(i.when=s=>{const u=s.value;return!bu(u)&&u.length!==void 0}),t._zod.onattach.push(s=>{const u=s._zod.bag.maximum??Number.POSITIVE_INFINITY;r.maximum{const u=s.value;if(u.length<=r.maximum)return;const p=Bu(u);s.issues.push({origin:p,code:"too_big",maximum:r.maximum,inclusive:!0,input:u,inst:t,continue:!r.abort})}}),Eh=$("$ZodCheckMinLength",(t,r)=>{var i;Bt.init(t,r),(i=t._zod.def).when??(i.when=s=>{const u=s.value;return!bu(u)&&u.length!==void 0}),t._zod.onattach.push(s=>{const u=s._zod.bag.minimum??Number.NEGATIVE_INFINITY;r.minimum>u&&(s._zod.bag.minimum=r.minimum)}),t._zod.check=s=>{const u=s.value;if(u.length>=r.minimum)return;const p=Bu(u);s.issues.push({origin:p,code:"too_small",minimum:r.minimum,inclusive:!0,input:u,inst:t,continue:!r.abort})}}),wh=$("$ZodCheckLengthEquals",(t,r)=>{var i;Bt.init(t,r),(i=t._zod.def).when??(i.when=s=>{const u=s.value;return!bu(u)&&u.length!==void 0}),t._zod.onattach.push(s=>{const u=s._zod.bag;u.minimum=r.length,u.maximum=r.length,u.length=r.length}),t._zod.check=s=>{const u=s.value,f=u.length;if(f===r.length)return;const p=Bu(u),v=f>r.length;s.issues.push({origin:p,...v?{code:"too_big",maximum:r.length}:{code:"too_small",minimum:r.length},inclusive:!0,exact:!0,input:s.value,inst:t,continue:!r.abort})}}),Wa=$("$ZodCheckStringFormat",(t,r)=>{var i,s;Bt.init(t,r),t._zod.onattach.push(u=>{const f=u._zod.bag;f.format=r.format,r.pattern&&(f.patterns??(f.patterns=new Set),f.patterns.add(r.pattern))}),r.pattern?(i=t._zod).check??(i.check=u=>{r.pattern.lastIndex=0,!r.pattern.test(u.value)&&u.issues.push({origin:"string",code:"invalid_format",format:r.format,input:u.value,...r.pattern?{pattern:r.pattern.toString()}:{},inst:t,continue:!r.abort})}):(s=t._zod).check??(s.check=()=>{})}),Sh=$("$ZodCheckRegex",(t,r)=>{Wa.init(t,r),t._zod.check=i=>{r.pattern.lastIndex=0,!r.pattern.test(i.value)&&i.issues.push({origin:"string",code:"invalid_format",format:"regex",input:i.value,pattern:r.pattern.toString(),inst:t,continue:!r.abort})}}),bh=$("$ZodCheckLowerCase",(t,r)=>{r.pattern??(r.pattern=hh),Wa.init(t,r)}),kh=$("$ZodCheckUpperCase",(t,r)=>{r.pattern??(r.pattern=yh),Wa.init(t,r)}),Bh=$("$ZodCheckIncludes",(t,r)=>{Bt.init(t,r);const i=ar(r.includes),s=new RegExp(typeof r.position=="number"?`^.{${r.position}}${i}`:i);r.pattern=s,t._zod.onattach.push(u=>{const f=u._zod.bag;f.patterns??(f.patterns=new Set),f.patterns.add(s)}),t._zod.check=u=>{u.value.includes(r.includes,r.position)||u.issues.push({origin:"string",code:"invalid_format",format:"includes",includes:r.includes,input:u.value,inst:t,continue:!r.abort})}}),zh=$("$ZodCheckStartsWith",(t,r)=>{Bt.init(t,r);const i=new RegExp(`^${ar(r.prefix)}.*`);r.pattern??(r.pattern=i),t._zod.onattach.push(s=>{const u=s._zod.bag;u.patterns??(u.patterns=new Set),u.patterns.add(i)}),t._zod.check=s=>{s.value.startsWith(r.prefix)||s.issues.push({origin:"string",code:"invalid_format",format:"starts_with",prefix:r.prefix,input:s.value,inst:t,continue:!r.abort})}}),Th=$("$ZodCheckEndsWith",(t,r)=>{Bt.init(t,r);const i=new RegExp(`.*${ar(r.suffix)}$`);r.pattern??(r.pattern=i),t._zod.onattach.push(s=>{const u=s._zod.bag;u.patterns??(u.patterns=new Set),u.patterns.add(i)}),t._zod.check=s=>{s.value.endsWith(r.suffix)||s.issues.push({origin:"string",code:"invalid_format",format:"ends_with",suffix:r.suffix,input:s.value,inst:t,continue:!r.abort})}}),Ch=$("$ZodCheckOverwrite",(t,r)=>{Bt.init(t,r),t._zod.check=i=>{i.value=r.tx(i.value)}});class Rh{constructor(r=[]){this.content=[],this.indent=0,this&&(this.args=r)}indented(r){this.indent+=1,r(this),this.indent-=1}write(r){if(typeof r=="function"){r(this,{execution:"sync"}),r(this,{execution:"async"});return}const s=r.split(` `).filter(p=>p),u=Math.min(...s.map(p=>p.length-p.trimStart().length)),f=s.map(p=>p.slice(u)).map(p=>" ".repeat(this.indent*2)+p);for(const p of f)this.content.push(p)}compile(){const r=Function,i=this?.args,u=[...(this?.content??[""]).map(f=>` ${f}`)];return new r(...i,u.join(` -`))}}const Nh={major:4,minor:4,patch:3},De=$("$ZodType",(t,r)=>{var i;t??(t={}),t._zod.def=r,t._zod.bag=t._zod.bag||{},t._zod.version=Nh;const s=[...t._zod.def.checks??[]];t._zod.traits.has("$ZodCheck")&&s.unshift(t);for(const u of s)for(const f of u._zod.onattach)f(t);if(s.length===0)(i=t._zod).deferred??(i.deferred=[]),t._zod.deferred?.push(()=>{t._zod.run=t._zod.parse});else{const u=(p,v,x)=>{let I=Jo(p),w;for(const b of v){if(b._zod.def.when){if(P3(p)||!b._zod.def.when(p))continue}else if(I)continue;const C=p.issues.length,O=b._zod.check(p);if(O instanceof Promise&&x?.async===!1)throw new er;if(w||O instanceof Promise)w=(w??Promise.resolve()).then(async()=>{await O,p.issues.length!==C&&(I||(I=Jo(p,C)))});else{if(p.issues.length===C)continue;I||(I=Jo(p,C))}}return w?w.then(()=>p):p},f=(p,v,x)=>{if(Jo(p))return p.aborted=!0,p;const I=u(v,s,x);if(I instanceof Promise){if(x.async===!1)throw new er;return I.then(w=>t._zod.parse(w,x))}return t._zod.parse(I,x)};t._zod.run=(p,v)=>{if(v.skipChecks)return t._zod.parse(p,v);if(v.direction==="backward"){const I=t._zod.parse({value:p.value,issues:[]},{...v,skipChecks:!0});return I instanceof Promise?I.then(w=>f(w,p,v)):f(I,p,v)}const x=t._zod.parse(p,v);if(x instanceof Promise){if(v.async===!1)throw new er;return x.then(I=>u(I,s,v))}return u(x,s,v)}}ze(t,"~standard",()=>({validate:u=>{try{const f=O3(t,u);return f.success?{value:f.data}:{issues:f.error?.issues}}catch{return $3(t,u).then(p=>p.success?{value:p.data}:{issues:p.error?.issues})}},vendor:"zod",version:1}))}),Cu=$("$ZodString",(t,r)=>{De.init(t,r),t._zod.pattern=[...t?._zod.bag?.patterns??[]].pop()??fh(t._zod.bag),t._zod.parse=(i,s)=>{if(r.coerce)try{i.value=String(i.value)}catch{}return typeof i.value=="string"||i.issues.push({expected:"string",code:"invalid_type",input:i.value,inst:t}),i}}),Me=$("$ZodStringFormat",(t,r)=>{Wa.init(t,r),Cu.init(t,r)}),Ph=$("$ZodGUID",(t,r)=>{r.pattern??(r.pattern=Y3),Me.init(t,r)}),jh=$("$ZodUUID",(t,r)=>{if(r.version){const s={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[r.version];if(s===void 0)throw new Error(`Invalid UUID version: "${r.version}"`);r.pattern??(r.pattern=Yf(s))}else r.pattern??(r.pattern=Yf());Me.init(t,r)}),Ah=$("$ZodEmail",(t,r)=>{r.pattern??(r.pattern=eh),Me.init(t,r)}),Oh=$("$ZodURL",(t,r)=>{Me.init(t,r),t._zod.check=i=>{try{const s=i.value.trim();if(!r.normalize&&r.protocol?.source===lh.source&&!/^https?:\/\//i.test(s)){i.issues.push({code:"invalid_format",format:"url",note:"Invalid URL format",input:i.value,inst:t,continue:!r.abort});return}const u=new URL(s);r.hostname&&(r.hostname.lastIndex=0,r.hostname.test(u.hostname)||i.issues.push({code:"invalid_format",format:"url",note:"Invalid hostname",pattern:r.hostname.source,input:i.value,inst:t,continue:!r.abort})),r.protocol&&(r.protocol.lastIndex=0,r.protocol.test(u.protocol.endsWith(":")?u.protocol.slice(0,-1):u.protocol)||i.issues.push({code:"invalid_format",format:"url",note:"Invalid protocol",pattern:r.protocol.source,input:i.value,inst:t,continue:!r.abort})),r.normalize?i.value=u.href:i.value=s;return}catch{i.issues.push({code:"invalid_format",format:"url",input:i.value,inst:t,continue:!r.abort})}}}),$h=$("$ZodEmoji",(t,r)=>{r.pattern??(r.pattern=nh()),Me.init(t,r)}),Dh=$("$ZodNanoID",(t,r)=>{r.pattern??(r.pattern=J3),Me.init(t,r)}),Mh=$("$ZodCUID",(t,r)=>{r.pattern??(r.pattern=W3),Me.init(t,r)}),Lh=$("$ZodCUID2",(t,r)=>{r.pattern??(r.pattern=G3),Me.init(t,r)}),qh=$("$ZodULID",(t,r)=>{r.pattern??(r.pattern=H3),Me.init(t,r)}),Fh=$("$ZodXID",(t,r)=>{r.pattern??(r.pattern=X3),Me.init(t,r)}),Uh=$("$ZodKSUID",(t,r)=>{r.pattern??(r.pattern=K3),Me.init(t,r)}),Zh=$("$ZodISODateTime",(t,r)=>{r.pattern??(r.pattern=ph(r)),Me.init(t,r)}),Vh=$("$ZodISODate",(t,r)=>{r.pattern??(r.pattern=ch),Me.init(t,r)}),Wh=$("$ZodISOTime",(t,r)=>{r.pattern??(r.pattern=dh(r)),Me.init(t,r)}),Gh=$("$ZodISODuration",(t,r)=>{r.pattern??(r.pattern=Q3),Me.init(t,r)}),Hh=$("$ZodIPv4",(t,r)=>{r.pattern??(r.pattern=oh),Me.init(t,r),t._zod.bag.format="ipv4"}),Xh=$("$ZodIPv6",(t,r)=>{r.pattern??(r.pattern=rh),Me.init(t,r),t._zod.bag.format="ipv6",t._zod.check=i=>{try{new URL(`http://[${i.value}]`)}catch{i.issues.push({code:"invalid_format",format:"ipv6",input:i.value,inst:t,continue:!r.abort})}}}),Kh=$("$ZodCIDRv4",(t,r)=>{r.pattern??(r.pattern=ih),Me.init(t,r)}),Jh=$("$ZodCIDRv6",(t,r)=>{r.pattern??(r.pattern=ah),Me.init(t,r),t._zod.check=i=>{const s=i.value.split("/");try{if(s.length!==2)throw new Error;const[u,f]=s;if(!f)throw new Error;const p=Number(f);if(`${p}`!==f)throw new Error;if(p<0||p>128)throw new Error;new URL(`http://[${u}]`)}catch{i.issues.push({code:"invalid_format",format:"cidrv6",input:i.value,inst:t,continue:!r.abort})}}});function p7(t){if(t==="")return!0;if(/\s/.test(t)||t.length%4!==0)return!1;try{return atob(t),!0}catch{return!1}}const Qh=$("$ZodBase64",(t,r)=>{r.pattern??(r.pattern=sh),Me.init(t,r),t._zod.bag.contentEncoding="base64",t._zod.check=i=>{p7(i.value)||i.issues.push({code:"invalid_format",format:"base64",input:i.value,inst:t,continue:!r.abort})}});function Yh(t){if(!i7.test(t))return!1;const r=t.replace(/[-_]/g,s=>s==="-"?"+":"/"),i=r.padEnd(Math.ceil(r.length/4)*4,"=");return p7(i)}const ey=$("$ZodBase64URL",(t,r)=>{r.pattern??(r.pattern=i7),Me.init(t,r),t._zod.bag.contentEncoding="base64url",t._zod.check=i=>{Yh(i.value)||i.issues.push({code:"invalid_format",format:"base64url",input:i.value,inst:t,continue:!r.abort})}}),ty=$("$ZodE164",(t,r)=>{r.pattern??(r.pattern=uh),Me.init(t,r)});function ny(t,r=null){try{const i=t.split(".");if(i.length!==3)return!1;const[s]=i;if(!s)return!1;const u=JSON.parse(atob(s));return!("typ"in u&&u?.typ!=="JWT"||!u.alg||r&&(!("alg"in u)||u.alg!==r))}catch{return!1}}const oy=$("$ZodJWT",(t,r)=>{Me.init(t,r),t._zod.check=i=>{ny(i.value,r.alg)||i.issues.push({code:"invalid_format",format:"jwt",input:i.value,inst:t,continue:!r.abort})}}),f7=$("$ZodNumber",(t,r)=>{De.init(t,r),t._zod.pattern=t._zod.bag.pattern??l7,t._zod.parse=(i,s)=>{if(r.coerce)try{i.value=Number(i.value)}catch{}const u=i.value;if(typeof u=="number"&&!Number.isNaN(u)&&Number.isFinite(u))return i;const f=typeof u=="number"?Number.isNaN(u)?"NaN":Number.isFinite(u)?void 0:"Infinity":void 0;return i.issues.push({expected:"number",code:"invalid_type",input:u,inst:t,...f?{received:f}:{}}),i}}),ry=$("$ZodNumberFormat",(t,r)=>{xh.init(t,r),f7.init(t,r)}),iy=$("$ZodBoolean",(t,r)=>{De.init(t,r),t._zod.pattern=gh,t._zod.parse=(i,s)=>{if(r.coerce)try{i.value=!!i.value}catch{}const u=i.value;return typeof u=="boolean"||i.issues.push({expected:"boolean",code:"invalid_type",input:u,inst:t}),i}}),ay=$("$ZodBigInt",(t,r)=>{De.init(t,r),t._zod.pattern=mh,t._zod.parse=(i,s)=>{if(r.coerce)try{i.value=BigInt(i.value)}catch{}return typeof i.value=="bigint"||i.issues.push({expected:"bigint",code:"invalid_type",input:i.value,inst:t}),i}}),sy=$("$ZodUnknown",(t,r)=>{De.init(t,r),t._zod.parse=i=>i}),ly=$("$ZodNever",(t,r)=>{De.init(t,r),t._zod.parse=(i,s)=>(i.issues.push({expected:"never",code:"invalid_type",input:i.value,inst:t}),i)});function em(t,r,i){t.issues.length&&r.issues.push(...Qo(i,t.issues)),r.value[i]=t.value}const uy=$("$ZodArray",(t,r)=>{De.init(t,r),t._zod.parse=(i,s)=>{const u=i.value;if(!Array.isArray(u))return i.issues.push({expected:"array",code:"invalid_type",input:u,inst:t}),i;i.value=Array(u.length);const f=[];for(let p=0;pem(I,i,p))):em(x,i,p)}return f.length?Promise.all(f).then(()=>i):i}});function Aa(t,r,i,s,u,f){const p=i in s;if(t.issues.length){if(u&&f&&!p)return;r.issues.push(...Qo(i,t.issues))}if(!p&&!u){t.issues.length||r.issues.push({code:"invalid_type",expected:"nonoptional",input:void 0,path:[i]});return}t.value===void 0?p&&(r.value[i]=void 0):r.value[i]=t.value}function m7(t){const r=Object.keys(t.shape);for(const s of r)if(!t.shape?.[s]?._zod?.traits?.has("$ZodType"))throw new Error(`Invalid element at key "${s}": expected a Zod schema`);const i=S3(t.shape);return{...t,keys:r,keySet:new Set(r),numKeys:r.length,optionalKeys:new Set(i)}}function v7(t,r,i,s,u,f){const p=[],v=u.keySet,x=u.catchall._zod,I=x.def.type,w=x.optin==="optional",b=x.optout==="optional";for(const C in r){if(C==="__proto__"||v.has(C))continue;if(I==="never"){p.push(C);continue}const O=x.run({value:r[C],issues:[]},s);O instanceof Promise?t.push(O.then(L=>Aa(L,i,C,r,w,b))):Aa(O,i,C,r,w,b)}return p.length&&i.issues.push({code:"unrecognized_keys",keys:p,input:r,inst:f}),t.length?Promise.all(t).then(()=>i):i}const cy=$("$ZodObject",(t,r)=>{if(De.init(t,r),!Object.getOwnPropertyDescriptor(r,"shape")?.get){const v=r.shape;Object.defineProperty(r,"shape",{get:()=>{const x={...v};return Object.defineProperty(r,"shape",{value:x}),x}})}const s=Ua(()=>m7(r));ze(t._zod,"propValues",()=>{const v=r.shape,x={};for(const I in v){const w=v[I]._zod;if(w.values){x[I]??(x[I]=new Set);for(const b of w.values)x[I].add(b)}}return x});const u=ai,f=r.catchall;let p;t._zod.parse=(v,x)=>{p??(p=s.value);const I=v.value;if(!u(I))return v.issues.push({expected:"object",code:"invalid_type",input:I,inst:t}),v;v.value={};const w=[],b=p.shape;for(const C of p.keys){const O=b[C],L=O._zod.optin==="optional",W=O._zod.optout==="optional",D=O._zod.run({value:I[C],issues:[]},x);D instanceof Promise?w.push(D.then(G=>Aa(G,v,C,I,L,W))):Aa(D,v,C,I,L,W)}return f?v7(w,I,v,x,s.value,t):w.length?Promise.all(w).then(()=>v):v}}),dy=$("$ZodObjectJIT",(t,r)=>{cy.init(t,r);const i=t._zod.parse,s=Ua(()=>m7(r)),u=C=>{const O=new Rh(["shape","payload","ctx"]),L=s.value,W=J=>{const H=Qf(J);return`shape[${H}]._zod.run({ value: input[${H}], issues: [] }, ctx)`};O.write("const input = payload.value;");const D=Object.create(null);let G=0;for(const J of L.keys)D[J]=`key_${G++}`;O.write("const newResult = {};");for(const J of L.keys){const H=D[J],te=Qf(J),ue=C[J],ve=ue?._zod?.optin==="optional",de=ue?._zod?.optout==="optional";O.write(`const ${H} = ${W(J)};`),ve&&de?O.write(` +`))}}const Nh={major:4,minor:4,patch:3},De=$("$ZodType",(t,r)=>{var i;t??(t={}),t._zod.def=r,t._zod.bag=t._zod.bag||{},t._zod.version=Nh;const s=[...t._zod.def.checks??[]];t._zod.traits.has("$ZodCheck")&&s.unshift(t);for(const u of s)for(const f of u._zod.onattach)f(t);if(s.length===0)(i=t._zod).deferred??(i.deferred=[]),t._zod.deferred?.push(()=>{t._zod.run=t._zod.parse});else{const u=(p,v,x)=>{let I=Jo(p),w;for(const b of v){if(b._zod.def.when){if(P3(p)||!b._zod.def.when(p))continue}else if(I)continue;const C=p.issues.length,O=b._zod.check(p);if(O instanceof Promise&&x?.async===!1)throw new er;if(w||O instanceof Promise)w=(w??Promise.resolve()).then(async()=>{await O,p.issues.length!==C&&(I||(I=Jo(p,C)))});else{if(p.issues.length===C)continue;I||(I=Jo(p,C))}}return w?w.then(()=>p):p},f=(p,v,x)=>{if(Jo(p))return p.aborted=!0,p;const I=u(v,s,x);if(I instanceof Promise){if(x.async===!1)throw new er;return I.then(w=>t._zod.parse(w,x))}return t._zod.parse(I,x)};t._zod.run=(p,v)=>{if(v.skipChecks)return t._zod.parse(p,v);if(v.direction==="backward"){const I=t._zod.parse({value:p.value,issues:[]},{...v,skipChecks:!0});return I instanceof Promise?I.then(w=>f(w,p,v)):f(I,p,v)}const x=t._zod.parse(p,v);if(x instanceof Promise){if(v.async===!1)throw new er;return x.then(I=>u(I,s,v))}return u(x,s,v)}}ze(t,"~standard",()=>({validate:u=>{try{const f=O3(t,u);return f.success?{value:f.data}:{issues:f.error?.issues}}catch{return $3(t,u).then(p=>p.success?{value:p.data}:{issues:p.error?.issues})}},vendor:"zod",version:1}))}),Cu=$("$ZodString",(t,r)=>{De.init(t,r),t._zod.pattern=[...t?._zod.bag?.patterns??[]].pop()??fh(t._zod.bag),t._zod.parse=(i,s)=>{if(r.coerce)try{i.value=String(i.value)}catch{}return typeof i.value=="string"||i.issues.push({expected:"string",code:"invalid_type",input:i.value,inst:t}),i}}),Me=$("$ZodStringFormat",(t,r)=>{Wa.init(t,r),Cu.init(t,r)}),Ph=$("$ZodGUID",(t,r)=>{r.pattern??(r.pattern=Y3),Me.init(t,r)}),jh=$("$ZodUUID",(t,r)=>{if(r.version){const s={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[r.version];if(s===void 0)throw new Error(`Invalid UUID version: "${r.version}"`);r.pattern??(r.pattern=Yf(s))}else r.pattern??(r.pattern=Yf());Me.init(t,r)}),Ah=$("$ZodEmail",(t,r)=>{r.pattern??(r.pattern=eh),Me.init(t,r)}),Oh=$("$ZodURL",(t,r)=>{Me.init(t,r),t._zod.check=i=>{try{const s=i.value.trim();if(!r.normalize&&r.protocol?.source===lh.source&&!/^https?:\/\//i.test(s)){i.issues.push({code:"invalid_format",format:"url",note:"Invalid URL format",input:i.value,inst:t,continue:!r.abort});return}const u=new URL(s);r.hostname&&(r.hostname.lastIndex=0,r.hostname.test(u.hostname)||i.issues.push({code:"invalid_format",format:"url",note:"Invalid hostname",pattern:r.hostname.source,input:i.value,inst:t,continue:!r.abort})),r.protocol&&(r.protocol.lastIndex=0,r.protocol.test(u.protocol.endsWith(":")?u.protocol.slice(0,-1):u.protocol)||i.issues.push({code:"invalid_format",format:"url",note:"Invalid protocol",pattern:r.protocol.source,input:i.value,inst:t,continue:!r.abort})),r.normalize?i.value=u.href:i.value=s;return}catch{i.issues.push({code:"invalid_format",format:"url",input:i.value,inst:t,continue:!r.abort})}}}),$h=$("$ZodEmoji",(t,r)=>{r.pattern??(r.pattern=nh()),Me.init(t,r)}),Dh=$("$ZodNanoID",(t,r)=>{r.pattern??(r.pattern=J3),Me.init(t,r)}),Mh=$("$ZodCUID",(t,r)=>{r.pattern??(r.pattern=W3),Me.init(t,r)}),Lh=$("$ZodCUID2",(t,r)=>{r.pattern??(r.pattern=G3),Me.init(t,r)}),qh=$("$ZodULID",(t,r)=>{r.pattern??(r.pattern=H3),Me.init(t,r)}),Fh=$("$ZodXID",(t,r)=>{r.pattern??(r.pattern=X3),Me.init(t,r)}),Uh=$("$ZodKSUID",(t,r)=>{r.pattern??(r.pattern=K3),Me.init(t,r)}),Zh=$("$ZodISODateTime",(t,r)=>{r.pattern??(r.pattern=ph(r)),Me.init(t,r)}),Vh=$("$ZodISODate",(t,r)=>{r.pattern??(r.pattern=ch),Me.init(t,r)}),Wh=$("$ZodISOTime",(t,r)=>{r.pattern??(r.pattern=dh(r)),Me.init(t,r)}),Gh=$("$ZodISODuration",(t,r)=>{r.pattern??(r.pattern=Q3),Me.init(t,r)}),Hh=$("$ZodIPv4",(t,r)=>{r.pattern??(r.pattern=oh),Me.init(t,r),t._zod.bag.format="ipv4"}),Xh=$("$ZodIPv6",(t,r)=>{r.pattern??(r.pattern=rh),Me.init(t,r),t._zod.bag.format="ipv6",t._zod.check=i=>{try{new URL(`http://[${i.value}]`)}catch{i.issues.push({code:"invalid_format",format:"ipv6",input:i.value,inst:t,continue:!r.abort})}}}),Kh=$("$ZodCIDRv4",(t,r)=>{r.pattern??(r.pattern=ih),Me.init(t,r)}),Jh=$("$ZodCIDRv6",(t,r)=>{r.pattern??(r.pattern=ah),Me.init(t,r),t._zod.check=i=>{const s=i.value.split("/");try{if(s.length!==2)throw new Error;const[u,f]=s;if(!f)throw new Error;const p=Number(f);if(`${p}`!==f)throw new Error;if(p<0||p>128)throw new Error;new URL(`http://[${u}]`)}catch{i.issues.push({code:"invalid_format",format:"cidrv6",input:i.value,inst:t,continue:!r.abort})}}});function p7(t){if(t==="")return!0;if(/\s/.test(t)||t.length%4!==0)return!1;try{return atob(t),!0}catch{return!1}}const Qh=$("$ZodBase64",(t,r)=>{r.pattern??(r.pattern=sh),Me.init(t,r),t._zod.bag.contentEncoding="base64",t._zod.check=i=>{p7(i.value)||i.issues.push({code:"invalid_format",format:"base64",input:i.value,inst:t,continue:!r.abort})}});function Yh(t){if(!i7.test(t))return!1;const r=t.replace(/[-_]/g,s=>s==="-"?"+":"/"),i=r.padEnd(Math.ceil(r.length/4)*4,"=");return p7(i)}const ey=$("$ZodBase64URL",(t,r)=>{r.pattern??(r.pattern=i7),Me.init(t,r),t._zod.bag.contentEncoding="base64url",t._zod.check=i=>{Yh(i.value)||i.issues.push({code:"invalid_format",format:"base64url",input:i.value,inst:t,continue:!r.abort})}}),ty=$("$ZodE164",(t,r)=>{r.pattern??(r.pattern=uh),Me.init(t,r)});function ny(t,r=null){try{const i=t.split(".");if(i.length!==3)return!1;const[s]=i;if(!s)return!1;const u=JSON.parse(atob(s));return!("typ"in u&&u?.typ!=="JWT"||!u.alg||r&&(!("alg"in u)||u.alg!==r))}catch{return!1}}const oy=$("$ZodJWT",(t,r)=>{Me.init(t,r),t._zod.check=i=>{ny(i.value,r.alg)||i.issues.push({code:"invalid_format",format:"jwt",input:i.value,inst:t,continue:!r.abort})}}),f7=$("$ZodNumber",(t,r)=>{De.init(t,r),t._zod.pattern=t._zod.bag.pattern??l7,t._zod.parse=(i,s)=>{if(r.coerce)try{i.value=Number(i.value)}catch{}const u=i.value;if(typeof u=="number"&&!Number.isNaN(u)&&Number.isFinite(u))return i;const f=typeof u=="number"?Number.isNaN(u)?"NaN":Number.isFinite(u)?void 0:"Infinity":void 0;return i.issues.push({expected:"number",code:"invalid_type",input:u,inst:t,...f?{received:f}:{}}),i}}),ry=$("$ZodNumberFormat",(t,r)=>{xh.init(t,r),f7.init(t,r)}),iy=$("$ZodBoolean",(t,r)=>{De.init(t,r),t._zod.pattern=gh,t._zod.parse=(i,s)=>{if(r.coerce)try{i.value=!!i.value}catch{}const u=i.value;return typeof u=="boolean"||i.issues.push({expected:"boolean",code:"invalid_type",input:u,inst:t}),i}}),ay=$("$ZodBigInt",(t,r)=>{De.init(t,r),t._zod.pattern=mh,t._zod.parse=(i,s)=>{if(r.coerce)try{i.value=BigInt(i.value)}catch{}return typeof i.value=="bigint"||i.issues.push({expected:"bigint",code:"invalid_type",input:i.value,inst:t}),i}}),sy=$("$ZodUnknown",(t,r)=>{De.init(t,r),t._zod.parse=i=>i}),ly=$("$ZodNever",(t,r)=>{De.init(t,r),t._zod.parse=(i,s)=>(i.issues.push({expected:"never",code:"invalid_type",input:i.value,inst:t}),i)});function em(t,r,i){t.issues.length&&r.issues.push(...Qo(i,t.issues)),r.value[i]=t.value}const uy=$("$ZodArray",(t,r)=>{De.init(t,r),t._zod.parse=(i,s)=>{const u=i.value;if(!Array.isArray(u))return i.issues.push({expected:"array",code:"invalid_type",input:u,inst:t}),i;i.value=Array(u.length);const f=[];for(let p=0;pem(I,i,p))):em(x,i,p)}return f.length?Promise.all(f).then(()=>i):i}});function Aa(t,r,i,s,u,f){const p=i in s;if(t.issues.length){if(u&&f&&!p)return;r.issues.push(...Qo(i,t.issues))}if(!p&&!u){t.issues.length||r.issues.push({code:"invalid_type",expected:"nonoptional",input:void 0,path:[i]});return}t.value===void 0?p&&(r.value[i]=void 0):r.value[i]=t.value}function m7(t){const r=Object.keys(t.shape);for(const s of r)if(!t.shape?.[s]?._zod?.traits?.has("$ZodType"))throw new Error(`Invalid element at key "${s}": expected a Zod schema`);const i=S3(t.shape);return{...t,keys:r,keySet:new Set(r),numKeys:r.length,optionalKeys:new Set(i)}}function v7(t,r,i,s,u,f){const p=[],v=u.keySet,x=u.catchall._zod,I=x.def.type,w=x.optin==="optional",b=x.optout==="optional";for(const C in r){if(C==="__proto__"||v.has(C))continue;if(I==="never"){p.push(C);continue}const O=x.run({value:r[C],issues:[]},s);O instanceof Promise?t.push(O.then(L=>Aa(L,i,C,r,w,b))):Aa(O,i,C,r,w,b)}return p.length&&i.issues.push({code:"unrecognized_keys",keys:p,input:r,inst:f}),t.length?Promise.all(t).then(()=>i):i}const cy=$("$ZodObject",(t,r)=>{if(De.init(t,r),!Object.getOwnPropertyDescriptor(r,"shape")?.get){const v=r.shape;Object.defineProperty(r,"shape",{get:()=>{const x={...v};return Object.defineProperty(r,"shape",{value:x}),x}})}const s=Ua(()=>m7(r));ze(t._zod,"propValues",()=>{const v=r.shape,x={};for(const I in v){const w=v[I]._zod;if(w.values){x[I]??(x[I]=new Set);for(const b of w.values)x[I].add(b)}}return x});const u=ai,f=r.catchall;let p;t._zod.parse=(v,x)=>{p??(p=s.value);const I=v.value;if(!u(I))return v.issues.push({expected:"object",code:"invalid_type",input:I,inst:t}),v;v.value={};const w=[],b=p.shape;for(const C of p.keys){const O=b[C],L=O._zod.optin==="optional",W=O._zod.optout==="optional",D=O._zod.run({value:I[C],issues:[]},x);D instanceof Promise?w.push(D.then(G=>Aa(G,v,C,I,L,W))):Aa(D,v,C,I,L,W)}return f?v7(w,I,v,x,s.value,t):w.length?Promise.all(w).then(()=>v):v}}),dy=$("$ZodObjectJIT",(t,r)=>{cy.init(t,r);const i=t._zod.parse,s=Ua(()=>m7(r)),u=C=>{const O=new Rh(["shape","payload","ctx"]),L=s.value,W=J=>{const H=Qf(J);return`shape[${H}]._zod.run({ value: input[${H}], issues: [] }, ctx)`};O.write("const input = payload.value;");const D=Object.create(null);let G=0;for(const J of L.keys)D[J]=`key_${G++}`;O.write("const newResult = {};");for(const J of L.keys){const H=D[J],te=Qf(J),ue=C[J],ve=ue?._zod?.optin==="optional",pe=ue?._zod?.optout==="optional";O.write(`const ${H} = ${W(J)};`),ve&&pe?O.write(` if (${H}.issues.length) { if (${te} in input) { payload.issues = payload.issues.concat(${H}.issues.map(iss => ({ @@ -70,5 +70,5 @@ Error generating stack: `+m.message+` `)}O.write("payload.value = newResult;"),O.write("return payload;");const ee=O.compile();return(J,H)=>ee(C,J,H)};let f;const p=ai,v=!Su.jitless,I=v&&E3.value,w=r.catchall;let b;t._zod.parse=(C,O)=>{b??(b=s.value);const L=C.value;return p(L)?v&&I&&O?.async===!1&&O.jitless!==!0?(f||(f=u(r.shape)),C=f(C,O),w?v7([],L,C,O,b,t):C):i(C,O):(C.issues.push({expected:"object",code:"invalid_type",input:L,inst:t}),C)}});function tm(t,r,i,s){for(const f of t)if(f.issues.length===0)return r.value=f.value,r;const u=t.filter(f=>!Jo(f));return u.length===1?(r.value=u[0].value,u[0]):(r.issues.push({code:"invalid_union",input:r.value,inst:i,errors:t.map(f=>f.issues.map(p=>kn(p,s,bn())))}),r)}const g7=$("$ZodUnion",(t,r)=>{De.init(t,r),ze(t._zod,"optin",()=>r.options.some(s=>s._zod.optin==="optional")?"optional":void 0),ze(t._zod,"optout",()=>r.options.some(s=>s._zod.optout==="optional")?"optional":void 0),ze(t._zod,"values",()=>{if(r.options.every(s=>s._zod.values))return new Set(r.options.flatMap(s=>Array.from(s._zod.values)))}),ze(t._zod,"pattern",()=>{if(r.options.every(s=>s._zod.pattern)){const s=r.options.map(u=>u._zod.pattern);return new RegExp(`^(${s.map(u=>ku(u.source)).join("|")})$`)}});const i=r.options.length===1?r.options[0]._zod.run:null;t._zod.parse=(s,u)=>{if(i)return i(s,u);let f=!1;const p=[];for(const v of r.options){const x=v._zod.run({value:s.value,issues:[]},u);if(x instanceof Promise)p.push(x),f=!0;else{if(x.issues.length===0)return x;p.push(x)}}return f?Promise.all(p).then(v=>tm(v,s,t,u)):tm(p,s,t,u)}}),py=$("$ZodDiscriminatedUnion",(t,r)=>{r.inclusive=!1,g7.init(t,r);const i=t._zod.parse;ze(t._zod,"propValues",()=>{const u={};for(const f of r.options){const p=f._zod.propValues;if(!p||Object.keys(p).length===0)throw new Error(`Invalid discriminated union option at index "${r.options.indexOf(f)}"`);for(const[v,x]of Object.entries(p)){u[v]||(u[v]=new Set);for(const I of x)u[v].add(I)}}return u});const s=Ua(()=>{const u=r.options,f=new Map;for(const p of u){const v=p._zod.propValues?.[r.discriminator];if(!v||v.size===0)throw new Error(`Invalid discriminated union option at index "${r.options.indexOf(p)}"`);for(const x of v){if(f.has(x))throw new Error(`Duplicate discriminator value "${String(x)}"`);f.set(x,p)}}return f});t._zod.parse=(u,f)=>{const p=u.value;if(!ai(p))return u.issues.push({code:"invalid_type",expected:"object",input:p,inst:t}),u;const v=s.value.get(p?.[r.discriminator]);return v?v._zod.run(u,f):r.unionFallback||f.direction==="backward"?i(u,f):(u.issues.push({code:"invalid_union",errors:[],note:"No matching discriminator",discriminator:r.discriminator,options:Array.from(s.value.keys()),input:p,path:[r.discriminator],inst:t}),u)}}),fy=$("$ZodIntersection",(t,r)=>{De.init(t,r),t._zod.parse=(i,s)=>{const u=i.value,f=r.left._zod.run({value:u,issues:[]},s),p=r.right._zod.run({value:u,issues:[]},s);return f instanceof Promise||p instanceof Promise?Promise.all([f,p]).then(([x,I])=>nm(i,x,I)):nm(i,f,p)}});function lu(t,r){if(t===r)return{valid:!0,data:t};if(t instanceof Date&&r instanceof Date&&+t==+r)return{valid:!0,data:t};if(ir(t)&&ir(r)){const i=Object.keys(r),s=Object.keys(t).filter(f=>i.indexOf(f)!==-1),u={...t,...r};for(const f of s){const p=lu(t[f],r[f]);if(!p.valid)return{valid:!1,mergeErrorPath:[f,...p.mergeErrorPath]};u[f]=p.data}return{valid:!0,data:u}}if(Array.isArray(t)&&Array.isArray(r)){if(t.length!==r.length)return{valid:!1,mergeErrorPath:[]};const i=[];for(let s=0;sv.l&&v.r).map(([v])=>v);if(f.length&&u&&t.issues.push({...u,keys:f}),Jo(t))return t;const p=lu(r.value,i.value);if(!p.valid)throw new Error(`Unmergable intersection. Error path: ${JSON.stringify(p.mergeErrorPath)}`);return t.value=p.data,t}const my=$("$ZodRecord",(t,r)=>{De.init(t,r),t._zod.parse=(i,s)=>{const u=i.value;if(!ir(u))return i.issues.push({expected:"record",code:"invalid_type",input:u,inst:t}),i;const f=[],p=r.keyType._zod.values;if(p){i.value={};const v=new Set;for(const I of p)if(typeof I=="string"||typeof I=="number"||typeof I=="symbol"){v.add(typeof I=="number"?I.toString():I);const w=r.keyType._zod.run({value:I,issues:[]},s);if(w instanceof Promise)throw new Error("Async schemas not supported in object keys currently");if(w.issues.length){i.issues.push({code:"invalid_key",origin:"record",issues:w.issues.map(O=>kn(O,s,bn())),input:I,path:[I],inst:t});continue}const b=w.value,C=r.valueType._zod.run({value:u[I],issues:[]},s);C instanceof Promise?f.push(C.then(O=>{O.issues.length&&i.issues.push(...Qo(I,O.issues)),i.value[b]=O.value})):(C.issues.length&&i.issues.push(...Qo(I,C.issues)),i.value[b]=C.value)}let x;for(const I in u)v.has(I)||(x=x??[],x.push(I));x&&x.length>0&&i.issues.push({code:"unrecognized_keys",input:u,inst:t,keys:x})}else{i.value={};for(const v of Reflect.ownKeys(u)){if(v==="__proto__"||!Object.prototype.propertyIsEnumerable.call(u,v))continue;let x=r.keyType._zod.run({value:v,issues:[]},s);if(x instanceof Promise)throw new Error("Async schemas not supported in object keys currently");if(typeof v=="string"&&l7.test(v)&&x.issues.length){const b=r.keyType._zod.run({value:Number(v),issues:[]},s);if(b instanceof Promise)throw new Error("Async schemas not supported in object keys currently");b.issues.length===0&&(x=b)}if(x.issues.length){r.mode==="loose"?i.value[v]=u[v]:i.issues.push({code:"invalid_key",origin:"record",issues:x.issues.map(b=>kn(b,s,bn())),input:v,path:[v],inst:t});continue}const w=r.valueType._zod.run({value:u[v],issues:[]},s);w instanceof Promise?f.push(w.then(b=>{b.issues.length&&i.issues.push(...Qo(v,b.issues)),i.value[x.value]=b.value})):(w.issues.length&&i.issues.push(...Qo(v,w.issues)),i.value[x.value]=w.value)}}return f.length?Promise.all(f).then(()=>i):i}}),vy=$("$ZodEnum",(t,r)=>{De.init(t,r);const i=Ym(r.entries),s=new Set(i);t._zod.values=s,t._zod.pattern=new RegExp(`^(${i.filter(u=>w3.has(typeof u)).map(u=>typeof u=="string"?ar(u):u.toString()).join("|")})$`),t._zod.parse=(u,f)=>{const p=u.value;return s.has(p)||u.issues.push({code:"invalid_value",values:i,input:p,inst:t}),u}}),gy=$("$ZodLiteral",(t,r)=>{if(De.init(t,r),r.values.length===0)throw new Error("Cannot create literal schema with no valid values");const i=new Set(r.values);t._zod.values=i,t._zod.pattern=new RegExp(`^(${r.values.map(s=>typeof s=="string"?ar(s):s?ar(s.toString()):String(s)).join("|")})$`),t._zod.parse=(s,u)=>{const f=s.value;return i.has(f)||s.issues.push({code:"invalid_value",values:r.values,input:f,inst:t}),s}}),hy=$("$ZodTransform",(t,r)=>{De.init(t,r),t._zod.optin="optional",t._zod.parse=(i,s)=>{if(s.direction==="backward")throw new Qm(t.constructor.name);const u=r.transform(i.value,i);if(s.async)return(u instanceof Promise?u:Promise.resolve(u)).then(p=>(i.value=p,i.fallback=!0,i));if(u instanceof Promise)throw new er;return i.value=u,i.fallback=!0,i}});function om(t,r){return r===void 0&&(t.issues.length||t.fallback)?{issues:[],value:void 0}:t}const h7=$("$ZodOptional",(t,r)=>{De.init(t,r),t._zod.optin="optional",t._zod.optout="optional",ze(t._zod,"values",()=>r.innerType._zod.values?new Set([...r.innerType._zod.values,void 0]):void 0),ze(t._zod,"pattern",()=>{const i=r.innerType._zod.pattern;return i?new RegExp(`^(${ku(i.source)})?$`):void 0}),t._zod.parse=(i,s)=>{if(r.innerType._zod.optin==="optional"){const u=i.value,f=r.innerType._zod.run(i,s);return f instanceof Promise?f.then(p=>om(p,u)):om(f,u)}return i.value===void 0?i:r.innerType._zod.run(i,s)}}),yy=$("$ZodExactOptional",(t,r)=>{h7.init(t,r),ze(t._zod,"values",()=>r.innerType._zod.values),ze(t._zod,"pattern",()=>r.innerType._zod.pattern),t._zod.parse=(i,s)=>r.innerType._zod.run(i,s)}),_y=$("$ZodNullable",(t,r)=>{De.init(t,r),ze(t._zod,"optin",()=>r.innerType._zod.optin),ze(t._zod,"optout",()=>r.innerType._zod.optout),ze(t._zod,"pattern",()=>{const i=r.innerType._zod.pattern;return i?new RegExp(`^(${ku(i.source)}|null)$`):void 0}),ze(t._zod,"values",()=>r.innerType._zod.values?new Set([...r.innerType._zod.values,null]):void 0),t._zod.parse=(i,s)=>i.value===null?i:r.innerType._zod.run(i,s)}),xy=$("$ZodDefault",(t,r)=>{De.init(t,r),t._zod.optin="optional",ze(t._zod,"values",()=>r.innerType._zod.values),t._zod.parse=(i,s)=>{if(s.direction==="backward")return r.innerType._zod.run(i,s);if(i.value===void 0)return i.value=r.defaultValue,i;const u=r.innerType._zod.run(i,s);return u instanceof Promise?u.then(f=>rm(f,r)):rm(u,r)}});function rm(t,r){return t.value===void 0&&(t.value=r.defaultValue),t}const Iy=$("$ZodPrefault",(t,r)=>{De.init(t,r),t._zod.optin="optional",ze(t._zod,"values",()=>r.innerType._zod.values),t._zod.parse=(i,s)=>(s.direction==="backward"||i.value===void 0&&(i.value=r.defaultValue),r.innerType._zod.run(i,s))}),Ey=$("$ZodNonOptional",(t,r)=>{De.init(t,r),ze(t._zod,"values",()=>{const i=r.innerType._zod.values;return i?new Set([...i].filter(s=>s!==void 0)):void 0}),t._zod.parse=(i,s)=>{const u=r.innerType._zod.run(i,s);return u instanceof Promise?u.then(f=>im(f,t)):im(u,t)}});function im(t,r){return!t.issues.length&&t.value===void 0&&t.issues.push({code:"invalid_type",expected:"nonoptional",input:t.value,inst:r}),t}const wy=$("$ZodCatch",(t,r)=>{De.init(t,r),t._zod.optin="optional",ze(t._zod,"optout",()=>r.innerType._zod.optout),ze(t._zod,"values",()=>r.innerType._zod.values),t._zod.parse=(i,s)=>{if(s.direction==="backward")return r.innerType._zod.run(i,s);const u=r.innerType._zod.run(i,s);return u instanceof Promise?u.then(f=>(i.value=f.value,f.issues.length&&(i.value=r.catchValue({...i,error:{issues:f.issues.map(p=>kn(p,s,bn()))},input:i.value}),i.issues=[],i.fallback=!0),i)):(i.value=u.value,u.issues.length&&(i.value=r.catchValue({...i,error:{issues:u.issues.map(f=>kn(f,s,bn()))},input:i.value}),i.issues=[],i.fallback=!0),i)}}),Sy=$("$ZodPipe",(t,r)=>{De.init(t,r),ze(t._zod,"values",()=>r.in._zod.values),ze(t._zod,"optin",()=>r.in._zod.optin),ze(t._zod,"optout",()=>r.out._zod.optout),ze(t._zod,"propValues",()=>r.in._zod.propValues),t._zod.parse=(i,s)=>{if(s.direction==="backward"){const f=r.out._zod.run(i,s);return f instanceof Promise?f.then(p=>Ba(p,r.in,s)):Ba(f,r.in,s)}const u=r.in._zod.run(i,s);return u instanceof Promise?u.then(f=>Ba(f,r.out,s)):Ba(u,r.out,s)}});function Ba(t,r,i){return t.issues.length?(t.aborted=!0,t):r._zod.run({value:t.value,issues:t.issues,fallback:t.fallback},i)}const by=$("$ZodReadonly",(t,r)=>{De.init(t,r),ze(t._zod,"propValues",()=>r.innerType._zod.propValues),ze(t._zod,"values",()=>r.innerType._zod.values),ze(t._zod,"optin",()=>r.innerType?._zod?.optin),ze(t._zod,"optout",()=>r.innerType?._zod?.optout),t._zod.parse=(i,s)=>{if(s.direction==="backward")return r.innerType._zod.run(i,s);const u=r.innerType._zod.run(i,s);return u instanceof Promise?u.then(am):am(u)}});function am(t){return t.value=Object.freeze(t.value),t}const ky=$("$ZodCustom",(t,r)=>{Bt.init(t,r),De.init(t,r),t._zod.parse=(i,s)=>i,t._zod.check=i=>{const s=i.value,u=r.fn(s);if(u instanceof Promise)return u.then(f=>sm(f,i,s,t));sm(u,i,s,t)}});function sm(t,r,i,s){if(!t){const u={code:"custom",input:i,inst:s,path:[...s._zod.def.path??[]],continue:!s._zod.def.abort};s._zod.def.params&&(u.params=s._zod.def.params),r.issues.push(si(u))}}var lm;class By{constructor(){this._map=new WeakMap,this._idmap=new Map}add(r,...i){const s=i[0];return this._map.set(r,s),s&&typeof s=="object"&&"id"in s&&this._idmap.set(s.id,r),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(r){const i=this._map.get(r);return i&&typeof i=="object"&&"id"in i&&this._idmap.delete(i.id),this._map.delete(r),this}get(r){const i=r._zod.parent;if(i){const s={...this.get(i)??{}};delete s.id;const u={...s,...this._map.get(r)};return Object.keys(u).length?u:void 0}return this._map.get(r)}has(r){return this._map.has(r)}}function zy(){return new By}(lm=globalThis).__zod_globalRegistry??(lm.__zod_globalRegistry=zy());const ti=globalThis.__zod_globalRegistry;function Ty(t,r){return new t({type:"string",...ie(r)})}function Cy(t,r){return new t({type:"string",format:"email",check:"string_format",abort:!1,...ie(r)})}function um(t,r){return new t({type:"string",format:"guid",check:"string_format",abort:!1,...ie(r)})}function Ry(t,r){return new t({type:"string",format:"uuid",check:"string_format",abort:!1,...ie(r)})}function Ny(t,r){return new t({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v4",...ie(r)})}function Py(t,r){return new t({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v6",...ie(r)})}function jy(t,r){return new t({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v7",...ie(r)})}function y7(t,r){return new t({type:"string",format:"url",check:"string_format",abort:!1,...ie(r)})}function Ay(t,r){return new t({type:"string",format:"emoji",check:"string_format",abort:!1,...ie(r)})}function Oy(t,r){return new t({type:"string",format:"nanoid",check:"string_format",abort:!1,...ie(r)})}function $y(t,r){return new t({type:"string",format:"cuid",check:"string_format",abort:!1,...ie(r)})}function Dy(t,r){return new t({type:"string",format:"cuid2",check:"string_format",abort:!1,...ie(r)})}function My(t,r){return new t({type:"string",format:"ulid",check:"string_format",abort:!1,...ie(r)})}function Ly(t,r){return new t({type:"string",format:"xid",check:"string_format",abort:!1,...ie(r)})}function qy(t,r){return new t({type:"string",format:"ksuid",check:"string_format",abort:!1,...ie(r)})}function Fy(t,r){return new t({type:"string",format:"ipv4",check:"string_format",abort:!1,...ie(r)})}function Uy(t,r){return new t({type:"string",format:"ipv6",check:"string_format",abort:!1,...ie(r)})}function Zy(t,r){return new t({type:"string",format:"cidrv4",check:"string_format",abort:!1,...ie(r)})}function Vy(t,r){return new t({type:"string",format:"cidrv6",check:"string_format",abort:!1,...ie(r)})}function Wy(t,r){return new t({type:"string",format:"base64",check:"string_format",abort:!1,...ie(r)})}function Gy(t,r){return new t({type:"string",format:"base64url",check:"string_format",abort:!1,...ie(r)})}function Hy(t,r){return new t({type:"string",format:"e164",check:"string_format",abort:!1,...ie(r)})}function Xy(t,r){return new t({type:"string",format:"jwt",check:"string_format",abort:!1,...ie(r)})}function Ky(t,r){return new t({type:"string",format:"datetime",check:"string_format",offset:!1,local:!1,precision:null,...ie(r)})}function Jy(t,r){return new t({type:"string",format:"date",check:"string_format",...ie(r)})}function Qy(t,r){return new t({type:"string",format:"time",check:"string_format",precision:null,...ie(r)})}function Yy(t,r){return new t({type:"string",format:"duration",check:"string_format",...ie(r)})}function e_(t,r){return new t({type:"number",checks:[],...ie(r)})}function t_(t,r){return new t({type:"number",check:"number_format",abort:!1,format:"safeint",...ie(r)})}function n_(t,r){return new t({type:"boolean",...ie(r)})}function o_(t,r){return new t({type:"bigint",coerce:!0,...ie(r)})}function r_(t){return new t({type:"unknown"})}function i_(t,r){return new t({type:"never",...ie(r)})}function Oa(t,r){return new c7({check:"less_than",...ie(r),value:t,inclusive:!1})}function tr(t,r){return new c7({check:"less_than",...ie(r),value:t,inclusive:!0})}function $a(t,r){return new d7({check:"greater_than",...ie(r),value:t,inclusive:!1})}function Jn(t,r){return new d7({check:"greater_than",...ie(r),value:t,inclusive:!0})}function uu(t,r){return new _h({check:"multiple_of",...ie(r),value:t})}function _7(t,r){return new Ih({check:"max_length",...ie(r),maximum:t})}function Da(t,r){return new Eh({check:"min_length",...ie(r),minimum:t})}function x7(t,r){return new wh({check:"length_equals",...ie(r),length:t})}function a_(t,r){return new Sh({check:"string_format",format:"regex",...ie(r),pattern:t})}function s_(t){return new bh({check:"string_format",format:"lowercase",...ie(t)})}function l_(t){return new kh({check:"string_format",format:"uppercase",...ie(t)})}function u_(t,r){return new Bh({check:"string_format",format:"includes",...ie(r),includes:t})}function c_(t,r){return new zh({check:"string_format",format:"starts_with",...ie(r),prefix:t})}function d_(t,r){return new Th({check:"string_format",format:"ends_with",...ie(r),suffix:t})}function dr(t){return new Ch({check:"overwrite",tx:t})}function p_(t){return dr(r=>r.normalize(t))}function f_(){return dr(t=>t.trim())}function m_(){return dr(t=>t.toLowerCase())}function v_(){return dr(t=>t.toUpperCase())}function g_(){return dr(t=>I3(t))}function h_(t,r,i){return new t({type:"array",element:r,...ie(i)})}function y_(t,r,i){return new t({type:"custom",check:"custom",fn:r,...ie(i)})}function __(t,r){const i=x_(s=>(s.addIssue=u=>{if(typeof u=="string")s.issues.push(si(u,s.value,i._zod.def));else{const f=u;f.fatal&&(f.continue=!1),f.code??(f.code="custom"),f.input??(f.input=s.value),f.inst??(f.inst=i),f.continue??(f.continue=!i._zod.def.abort),s.issues.push(si(f))}},t(s.value,s)),r);return i}function x_(t,r){const i=new Bt({check:"custom",...ie(r)});return i._zod.check=t,i}function I7(t){let r=t?.target??"draft-2020-12";return r==="draft-4"&&(r="draft-04"),r==="draft-7"&&(r="draft-07"),{processors:t.processors??{},metadataRegistry:t?.metadata??ti,target:r,unrepresentable:t?.unrepresentable??"throw",override:t?.override??(()=>{}),io:t?.io??"output",counter:0,seen:new Map,cycles:t?.cycles??"ref",reused:t?.reused??"inline",external:t?.external??void 0}}function Je(t,r,i={path:[],schemaPath:[]}){var s;const u=t._zod.def,f=r.seen.get(t);if(f)return f.count++,i.schemaPath.includes(t)&&(f.cycle=i.path),f.schema;const p={schema:{},count:1,cycle:void 0,path:i.path};r.seen.set(t,p);const v=t._zod.toJSONSchema?.();if(v)p.schema=v;else{const w={...i,schemaPath:[...i.schemaPath,t],path:i.path};if(t._zod.processJSONSchema)t._zod.processJSONSchema(r,p.schema,w);else{const C=p.schema,O=r.processors[u.type];if(!O)throw new Error(`[toJSONSchema]: Non-representable type encountered: ${u.type}`);O(t,r,C,w)}const b=t._zod.parent;b&&(p.ref||(p.ref=b),Je(b,r,w),r.seen.get(b).isParent=!0)}const x=r.metadataRegistry.get(t);return x&&Object.assign(p.schema,x),r.io==="input"&>(t)&&(delete p.schema.examples,delete p.schema.default),r.io==="input"&&"_prefault"in p.schema&&((s=p.schema).default??(s.default=p.schema._prefault)),delete p.schema._prefault,r.seen.get(t).schema}function E7(t,r){const i=t.seen.get(r);if(!i)throw new Error("Unprocessed schema. This is a bug in Zod.");const s=new Map;for(const p of t.seen.entries()){const v=t.metadataRegistry.get(p[0])?.id;if(v){const x=s.get(v);if(x&&x!==p[0])throw new Error(`Duplicate schema id "${v}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);s.set(v,p[0])}}const u=p=>{const v=t.target==="draft-2020-12"?"$defs":"definitions";if(t.external){const b=t.external.registry.get(p[0])?.id,C=t.external.uri??(L=>L);if(b)return{ref:C(b)};const O=p[1].defId??p[1].schema.id??`schema${t.counter++}`;return p[1].defId=O,{defId:O,ref:`${C("__shared")}#/${v}/${O}`}}if(p[1]===i)return{ref:"#"};const I=`#/${v}/`,w=p[1].schema.id??`__schema${t.counter++}`;return{defId:w,ref:I+w}},f=p=>{if(p[1].schema.$ref)return;const v=p[1],{ref:x,defId:I}=u(p);v.def={...v.schema},I&&(v.defId=I);const w=v.schema;for(const b in w)delete w[b];w.$ref=x};if(t.cycles==="throw")for(const p of t.seen.entries()){const v=p[1];if(v.cycle)throw new Error(`Cycle detected: #/${v.cycle?.join("/")}/ -Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const p of t.seen.entries()){const v=p[1];if(r===p[0]){f(p);continue}if(t.external){const I=t.external.registry.get(p[0])?.id;if(r!==p[0]&&I){f(p);continue}}if(t.metadataRegistry.get(p[0])?.id){f(p);continue}if(v.cycle){f(p);continue}if(v.count>1&&t.reused==="ref"){f(p);continue}}}function w7(t,r){const i=t.seen.get(r);if(!i)throw new Error("Unprocessed schema. This is a bug in Zod.");const s=v=>{const x=t.seen.get(v);if(x.ref===null)return;const I=x.def??x.schema,w={...I},b=x.ref;if(x.ref=null,b){s(b);const O=t.seen.get(b),L=O.schema;if(L.$ref&&(t.target==="draft-07"||t.target==="draft-04"||t.target==="openapi-3.0")?(I.allOf=I.allOf??[],I.allOf.push(L)):Object.assign(I,L),Object.assign(I,w),v._zod.parent===b)for(const D in I)D==="$ref"||D==="allOf"||D in w||delete I[D];if(L.$ref&&O.def)for(const D in I)D==="$ref"||D==="allOf"||D in O.def&&JSON.stringify(I[D])===JSON.stringify(O.def[D])&&delete I[D]}const C=v._zod.parent;if(C&&C!==b){s(C);const O=t.seen.get(C);if(O?.schema.$ref&&(I.$ref=O.schema.$ref,O.def))for(const L in I)L==="$ref"||L==="allOf"||L in O.def&&JSON.stringify(I[L])===JSON.stringify(O.def[L])&&delete I[L]}t.override({zodSchema:v,jsonSchema:I,path:x.path??[]})};for(const v of[...t.seen.entries()].reverse())s(v[0]);const u={};if(t.target==="draft-2020-12"?u.$schema="https://json-schema.org/draft/2020-12/schema":t.target==="draft-07"?u.$schema="http://json-schema.org/draft-07/schema#":t.target==="draft-04"?u.$schema="http://json-schema.org/draft-04/schema#":t.target,t.external?.uri){const v=t.external.registry.get(r)?.id;if(!v)throw new Error("Schema is missing an `id` property");u.$id=t.external.uri(v)}Object.assign(u,i.def??i.schema);const f=t.metadataRegistry.get(r)?.id;f!==void 0&&u.id===f&&delete u.id;const p=t.external?.defs??{};for(const v of t.seen.entries()){const x=v[1];x.def&&x.defId&&(x.def.id===x.defId&&delete x.def.id,p[x.defId]=x.def)}t.external||Object.keys(p).length>0&&(t.target==="draft-2020-12"?u.$defs=p:u.definitions=p);try{const v=JSON.parse(JSON.stringify(u));return Object.defineProperty(v,"~standard",{value:{...r["~standard"],jsonSchema:{input:Ma(r,"input",t.processors),output:Ma(r,"output",t.processors)}},enumerable:!1,writable:!1}),v}catch{throw new Error("Error converting schema to JSON.")}}function gt(t,r){const i=r??{seen:new Set};if(i.seen.has(t))return!1;i.seen.add(t);const s=t._zod.def;if(s.type==="transform")return!0;if(s.type==="array")return gt(s.element,i);if(s.type==="set")return gt(s.valueType,i);if(s.type==="lazy")return gt(s.getter(),i);if(s.type==="promise"||s.type==="optional"||s.type==="nonoptional"||s.type==="nullable"||s.type==="readonly"||s.type==="default"||s.type==="prefault")return gt(s.innerType,i);if(s.type==="intersection")return gt(s.left,i)||gt(s.right,i);if(s.type==="record"||s.type==="map")return gt(s.keyType,i)||gt(s.valueType,i);if(s.type==="pipe")return t._zod.traits.has("$ZodCodec")?!0:gt(s.in,i)||gt(s.out,i);if(s.type==="object"){for(const u in s.shape)if(gt(s.shape[u],i))return!0;return!1}if(s.type==="union"){for(const u of s.options)if(gt(u,i))return!0;return!1}if(s.type==="tuple"){for(const u of s.items)if(gt(u,i))return!0;return!!(s.rest&>(s.rest,i))}return!1}const I_=(t,r={})=>i=>{const s=I7({...i,processors:r});return Je(t,s),E7(s,t),w7(s,t)},Ma=(t,r,i={})=>s=>{const{libraryOptions:u,target:f}=s??{},p=I7({...u??{},target:f,io:r,processors:i});return Je(t,p),E7(p,t),w7(p,t)},E_={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},w_=(t,r,i,s)=>{const u=i;u.type="string";const{minimum:f,maximum:p,format:v,patterns:x,contentEncoding:I}=t._zod.bag;if(typeof f=="number"&&(u.minLength=f),typeof p=="number"&&(u.maxLength=p),v&&(u.format=E_[v]??v,u.format===""&&delete u.format,v==="time"&&delete u.format),I&&(u.contentEncoding=I),x&&x.size>0){const w=[...x];w.length===1?u.pattern=w[0].source:w.length>1&&(u.allOf=[...w.map(b=>({...r.target==="draft-07"||r.target==="draft-04"||r.target==="openapi-3.0"?{type:"string"}:{},pattern:b.source}))])}},S_=(t,r,i,s)=>{const u=i,{minimum:f,maximum:p,format:v,multipleOf:x,exclusiveMaximum:I,exclusiveMinimum:w}=t._zod.bag;typeof v=="string"&&v.includes("int")?u.type="integer":u.type="number";const b=typeof w=="number"&&w>=(f??Number.NEGATIVE_INFINITY),C=typeof I=="number"&&I<=(p??Number.POSITIVE_INFINITY),O=r.target==="draft-04"||r.target==="openapi-3.0";b?O?(u.minimum=w,u.exclusiveMinimum=!0):u.exclusiveMinimum=w:typeof f=="number"&&(u.minimum=f),C?O?(u.maximum=I,u.exclusiveMaximum=!0):u.exclusiveMaximum=I:typeof p=="number"&&(u.maximum=p),typeof x=="number"&&(u.multipleOf=x)},b_=(t,r,i,s)=>{i.type="boolean"},k_=(t,r,i,s)=>{if(r.unrepresentable==="throw")throw new Error("BigInt cannot be represented in JSON Schema")},B_=(t,r,i,s)=>{i.not={}},z_=(t,r,i,s)=>{},T_=(t,r,i,s)=>{const u=t._zod.def,f=Ym(u.entries);f.every(p=>typeof p=="number")&&(i.type="number"),f.every(p=>typeof p=="string")&&(i.type="string"),i.enum=f},C_=(t,r,i,s)=>{const u=t._zod.def,f=[];for(const p of u.values)if(p===void 0){if(r.unrepresentable==="throw")throw new Error("Literal `undefined` cannot be represented in JSON Schema")}else if(typeof p=="bigint"){if(r.unrepresentable==="throw")throw new Error("BigInt literals cannot be represented in JSON Schema");f.push(Number(p))}else f.push(p);if(f.length!==0)if(f.length===1){const p=f[0];i.type=p===null?"null":typeof p,r.target==="draft-04"||r.target==="openapi-3.0"?i.enum=[p]:i.const=p}else f.every(p=>typeof p=="number")&&(i.type="number"),f.every(p=>typeof p=="string")&&(i.type="string"),f.every(p=>typeof p=="boolean")&&(i.type="boolean"),f.every(p=>p===null)&&(i.type="null"),i.enum=f},R_=(t,r,i,s)=>{if(r.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},N_=(t,r,i,s)=>{if(r.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},P_=(t,r,i,s)=>{const u=i,f=t._zod.def,{minimum:p,maximum:v}=t._zod.bag;typeof p=="number"&&(u.minItems=p),typeof v=="number"&&(u.maxItems=v),u.type="array",u.items=Je(f.element,r,{...s,path:[...s.path,"items"]})},j_=(t,r,i,s)=>{const u=i,f=t._zod.def;u.type="object",u.properties={};const p=f.shape;for(const I in p)u.properties[I]=Je(p[I],r,{...s,path:[...s.path,"properties",I]});const v=new Set(Object.keys(p)),x=new Set([...v].filter(I=>{const w=f.shape[I]._zod;return r.io==="input"?w.optin===void 0:w.optout===void 0}));x.size>0&&(u.required=Array.from(x)),f.catchall?._zod.def.type==="never"?u.additionalProperties=!1:f.catchall?f.catchall&&(u.additionalProperties=Je(f.catchall,r,{...s,path:[...s.path,"additionalProperties"]})):r.io==="output"&&(u.additionalProperties=!1)},A_=(t,r,i,s)=>{const u=t._zod.def,f=u.inclusive===!1,p=u.options.map((v,x)=>Je(v,r,{...s,path:[...s.path,f?"oneOf":"anyOf",x]}));f?i.oneOf=p:i.anyOf=p},O_=(t,r,i,s)=>{const u=t._zod.def,f=Je(u.left,r,{...s,path:[...s.path,"allOf",0]}),p=Je(u.right,r,{...s,path:[...s.path,"allOf",1]}),v=I=>"allOf"in I&&Object.keys(I).length===1,x=[...v(f)?f.allOf:[f],...v(p)?p.allOf:[p]];i.allOf=x},$_=(t,r,i,s)=>{const u=i,f=t._zod.def;u.type="object";const p=f.keyType,x=p._zod.bag?.patterns;if(f.mode==="loose"&&x&&x.size>0){const w=Je(f.valueType,r,{...s,path:[...s.path,"patternProperties","*"]});u.patternProperties={};for(const b of x)u.patternProperties[b.source]=w}else(r.target==="draft-07"||r.target==="draft-2020-12")&&(u.propertyNames=Je(f.keyType,r,{...s,path:[...s.path,"propertyNames"]})),u.additionalProperties=Je(f.valueType,r,{...s,path:[...s.path,"additionalProperties"]});const I=p._zod.values;if(I){const w=[...I].filter(b=>typeof b=="string"||typeof b=="number");w.length>0&&(u.required=w)}},D_=(t,r,i,s)=>{const u=t._zod.def,f=Je(u.innerType,r,s),p=r.seen.get(t);r.target==="openapi-3.0"?(p.ref=u.innerType,i.nullable=!0):i.anyOf=[f,{type:"null"}]},M_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType},L_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType,i.default=JSON.parse(JSON.stringify(u.defaultValue))},q_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType,r.io==="input"&&(i._prefault=JSON.parse(JSON.stringify(u.defaultValue)))},F_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType;let p;try{p=u.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}i.default=p},U_=(t,r,i,s)=>{const u=t._zod.def,f=u.in._zod.traits.has("$ZodTransform"),p=r.io==="input"?f?u.out:u.in:u.out;Je(p,r,s);const v=r.seen.get(t);v.ref=p},Z_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType,i.readOnly=!0},S7=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType},V_=$("ZodISODateTime",(t,r)=>{Zh.init(t,r),Ve.init(t,r)});function k(t){return Ky(V_,t)}const W_=$("ZodISODate",(t,r)=>{Vh.init(t,r),Ve.init(t,r)});function G_(t){return Jy(W_,t)}const H_=$("ZodISOTime",(t,r)=>{Wh.init(t,r),Ve.init(t,r)});function X_(t){return Qy(H_,t)}const K_=$("ZodISODuration",(t,r)=>{Gh.init(t,r),Ve.init(t,r)});function J_(t){return Yy(K_,t)}const Q_=(t,r)=>{o7.init(t,r),t.name="ZodError",Object.defineProperties(t,{format:{value:i=>A3(t,i)},flatten:{value:i=>j3(t,i)},addIssue:{value:i=>{t.issues.push(i),t.message=JSON.stringify(t.issues,su,2)}},addIssues:{value:i=>{t.issues.push(...i),t.message=JSON.stringify(t.issues,su,2)}},isEmpty:{get(){return t.issues.length===0}}})},qt=$("ZodError",Q_,{Parent:Error}),Y_=zu(qt),e8=Tu(qt),t8=Za(qt),n8=Va(qt),o8=D3(qt),r8=M3(qt),i8=L3(qt),a8=q3(qt),s8=F3(qt),l8=U3(qt),u8=Z3(qt),c8=V3(qt),cm=new WeakMap;function ui(t,r,i){const s=Object.getPrototypeOf(t);let u=cm.get(s);if(u||(u=new Set,cm.set(s,u)),!u.has(r)){u.add(r);for(const f in i){const p=i[f];Object.defineProperty(s,f,{configurable:!0,enumerable:!1,get(){const v=p.bind(this);return Object.defineProperty(this,f,{configurable:!0,writable:!0,enumerable:!0,value:v}),v},set(v){Object.defineProperty(this,f,{configurable:!0,writable:!0,enumerable:!0,value:v})}})}}}const Le=$("ZodType",(t,r)=>(De.init(t,r),Object.assign(t["~standard"],{jsonSchema:{input:Ma(t,"input"),output:Ma(t,"output")}}),t.toJSONSchema=I_(t,{}),t.def=r,t.type=r.type,Object.defineProperty(t,"_def",{value:r}),t.parse=(i,s)=>Y_(t,i,s,{callee:t.parse}),t.safeParse=(i,s)=>t8(t,i,s),t.parseAsync=async(i,s)=>e8(t,i,s,{callee:t.parseAsync}),t.safeParseAsync=async(i,s)=>n8(t,i,s),t.spa=t.safeParseAsync,t.encode=(i,s)=>o8(t,i,s),t.decode=(i,s)=>r8(t,i,s),t.encodeAsync=async(i,s)=>i8(t,i,s),t.decodeAsync=async(i,s)=>a8(t,i,s),t.safeEncode=(i,s)=>s8(t,i,s),t.safeDecode=(i,s)=>l8(t,i,s),t.safeEncodeAsync=async(i,s)=>u8(t,i,s),t.safeDecodeAsync=async(i,s)=>c8(t,i,s),ui(t,"ZodType",{check(...i){const s=this.def;return this.clone(oo(s,{checks:[...s.checks??[],...i.map(u=>typeof u=="function"?{_zod:{check:u,def:{check:"custom"},onattach:[]}}:u)]}),{parent:!0})},with(...i){return this.check(...i)},clone(i,s){return ro(this,i,s)},brand(){return this},register(i,s){return i.add(this,s),this},refine(i,s){return this.check(t5(i,s))},superRefine(i,s){return this.check(n5(i,s))},overwrite(i){return this.check(dr(i))},optional(){return mm(this)},exactOptional(){return F8(this)},nullable(){return vm(this)},nullish(){return mm(vm(this))},nonoptional(i){return H8(this,i)},array(){return y(this)},or(i){return un([this,i])},and(i){return $8(this,i)},transform(i){return gm(this,L8(i))},default(i){return V8(this,i)},prefault(i){return G8(this,i)},catch(i){return K8(this,i)},pipe(i){return gm(this,i)},readonly(){return Y8(this)},describe(i){const s=this.clone();return ti.add(s,{description:i}),s},meta(...i){if(i.length===0)return ti.get(this);const s=this.clone();return ti.add(s,i[0]),s},isOptional(){return this.safeParse(void 0).success},isNullable(){return this.safeParse(null).success},apply(i){return i(this)}}),Object.defineProperty(t,"description",{get(){return ti.get(t)?.description},configurable:!0}),t)),b7=$("_ZodString",(t,r)=>{Cu.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(s,u,f)=>w_(t,s,u);const i=t._zod.bag;t.format=i.format??null,t.minLength=i.minimum??null,t.maxLength=i.maximum??null,ui(t,"_ZodString",{regex(...s){return this.check(a_(...s))},includes(...s){return this.check(u_(...s))},startsWith(...s){return this.check(c_(...s))},endsWith(...s){return this.check(d_(...s))},min(...s){return this.check(Da(...s))},max(...s){return this.check(_7(...s))},length(...s){return this.check(x7(...s))},nonempty(...s){return this.check(Da(1,...s))},lowercase(s){return this.check(s_(s))},uppercase(s){return this.check(l_(s))},trim(){return this.check(f_())},normalize(...s){return this.check(p_(...s))},toLowerCase(){return this.check(m_())},toUpperCase(){return this.check(v_())},slugify(){return this.check(g_())}})}),d8=$("ZodString",(t,r)=>{Cu.init(t,r),b7.init(t,r),t.email=i=>t.check(Cy(p8,i)),t.url=i=>t.check(y7(k7,i)),t.jwt=i=>t.check(Xy(B8,i)),t.emoji=i=>t.check(Ay(f8,i)),t.guid=i=>t.check(um(dm,i)),t.uuid=i=>t.check(Ry(za,i)),t.uuidv4=i=>t.check(Ny(za,i)),t.uuidv6=i=>t.check(Py(za,i)),t.uuidv7=i=>t.check(jy(za,i)),t.nanoid=i=>t.check(Oy(m8,i)),t.guid=i=>t.check(um(dm,i)),t.cuid=i=>t.check($y(v8,i)),t.cuid2=i=>t.check(Dy(g8,i)),t.ulid=i=>t.check(My(h8,i)),t.base64=i=>t.check(Wy(S8,i)),t.base64url=i=>t.check(Gy(b8,i)),t.xid=i=>t.check(Ly(y8,i)),t.ksuid=i=>t.check(qy(_8,i)),t.ipv4=i=>t.check(Fy(x8,i)),t.ipv6=i=>t.check(Uy(I8,i)),t.cidrv4=i=>t.check(Zy(E8,i)),t.cidrv6=i=>t.check(Vy(w8,i)),t.e164=i=>t.check(Hy(k8,i)),t.datetime=i=>t.check(k(i)),t.date=i=>t.check(G_(i)),t.time=i=>t.check(X_(i)),t.duration=i=>t.check(J_(i))});function e(t){return Ty(d8,t)}const Ve=$("ZodStringFormat",(t,r)=>{Me.init(t,r),b7.init(t,r)}),p8=$("ZodEmail",(t,r)=>{Ah.init(t,r),Ve.init(t,r)}),dm=$("ZodGUID",(t,r)=>{Ph.init(t,r),Ve.init(t,r)}),za=$("ZodUUID",(t,r)=>{jh.init(t,r),Ve.init(t,r)}),k7=$("ZodURL",(t,r)=>{Oh.init(t,r),Ve.init(t,r)});function pm(t){return y7(k7,t)}const f8=$("ZodEmoji",(t,r)=>{$h.init(t,r),Ve.init(t,r)}),m8=$("ZodNanoID",(t,r)=>{Dh.init(t,r),Ve.init(t,r)}),v8=$("ZodCUID",(t,r)=>{Mh.init(t,r),Ve.init(t,r)}),g8=$("ZodCUID2",(t,r)=>{Lh.init(t,r),Ve.init(t,r)}),h8=$("ZodULID",(t,r)=>{qh.init(t,r),Ve.init(t,r)}),y8=$("ZodXID",(t,r)=>{Fh.init(t,r),Ve.init(t,r)}),_8=$("ZodKSUID",(t,r)=>{Uh.init(t,r),Ve.init(t,r)}),x8=$("ZodIPv4",(t,r)=>{Hh.init(t,r),Ve.init(t,r)}),I8=$("ZodIPv6",(t,r)=>{Xh.init(t,r),Ve.init(t,r)}),E8=$("ZodCIDRv4",(t,r)=>{Kh.init(t,r),Ve.init(t,r)}),w8=$("ZodCIDRv6",(t,r)=>{Jh.init(t,r),Ve.init(t,r)}),S8=$("ZodBase64",(t,r)=>{Qh.init(t,r),Ve.init(t,r)}),b8=$("ZodBase64URL",(t,r)=>{ey.init(t,r),Ve.init(t,r)}),k8=$("ZodE164",(t,r)=>{ty.init(t,r),Ve.init(t,r)}),B8=$("ZodJWT",(t,r)=>{oy.init(t,r),Ve.init(t,r)}),B7=$("ZodNumber",(t,r)=>{f7.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(s,u,f)=>S_(t,s,u),ui(t,"ZodNumber",{gt(s,u){return this.check($a(s,u))},gte(s,u){return this.check(Jn(s,u))},min(s,u){return this.check(Jn(s,u))},lt(s,u){return this.check(Oa(s,u))},lte(s,u){return this.check(tr(s,u))},max(s,u){return this.check(tr(s,u))},int(s){return this.check(Ue(s))},safe(s){return this.check(Ue(s))},positive(s){return this.check($a(0,s))},nonnegative(s){return this.check(Jn(0,s))},negative(s){return this.check(Oa(0,s))},nonpositive(s){return this.check(tr(0,s))},multipleOf(s,u){return this.check(uu(s,u))},step(s,u){return this.check(uu(s,u))},finite(){return this}});const i=t._zod.bag;t.minValue=Math.max(i.minimum??Number.NEGATIVE_INFINITY,i.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,t.maxValue=Math.min(i.maximum??Number.POSITIVE_INFINITY,i.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,t.isInt=(i.format??"").includes("int")||Number.isSafeInteger(i.multipleOf??.5),t.isFinite=!0,t.format=i.format??null});function pt(t){return e_(B7,t)}const z8=$("ZodNumberFormat",(t,r)=>{ry.init(t,r),B7.init(t,r)});function Ue(t){return t_(z8,t)}const T8=$("ZodBoolean",(t,r)=>{iy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>b_(t,i,s)});function R(t){return n_(T8,t)}const C8=$("ZodBigInt",(t,r)=>{ay.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(s,u,f)=>k_(t,s),t.gte=(s,u)=>t.check(Jn(s,u)),t.min=(s,u)=>t.check(Jn(s,u)),t.gt=(s,u)=>t.check($a(s,u)),t.gte=(s,u)=>t.check(Jn(s,u)),t.min=(s,u)=>t.check(Jn(s,u)),t.lt=(s,u)=>t.check(Oa(s,u)),t.lte=(s,u)=>t.check(tr(s,u)),t.max=(s,u)=>t.check(tr(s,u)),t.positive=s=>t.check($a(BigInt(0),s)),t.negative=s=>t.check(Oa(BigInt(0),s)),t.nonpositive=s=>t.check(tr(BigInt(0),s)),t.nonnegative=s=>t.check(Jn(BigInt(0),s)),t.multipleOf=(s,u)=>t.check(uu(s,u));const i=t._zod.bag;t.minValue=i.minimum??null,t.maxValue=i.maximum??null,t.format=i.format??null}),R8=$("ZodUnknown",(t,r)=>{sy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>z_()});function no(){return r_(R8)}const N8=$("ZodNever",(t,r)=>{ly.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>B_(t,i,s)});function Ga(t){return i_(N8,t)}const P8=$("ZodArray",(t,r)=>{uy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>P_(t,i,s,u),t.element=r.element,ui(t,"ZodArray",{min(i,s){return this.check(Da(i,s))},nonempty(i){return this.check(Da(1,i))},max(i,s){return this.check(_7(i,s))},length(i,s){return this.check(x7(i,s))},unwrap(){return this.element}})});function y(t,r){return h_(P8,t,r)}const j8=$("ZodObject",(t,r)=>{dy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>j_(t,i,s,u),ze(t,"shape",()=>r.shape),ui(t,"ZodObject",{keyof(){return me(Object.keys(this._zod.def.shape))},catchall(i){return this.clone({...this._zod.def,catchall:i})},passthrough(){return this.clone({...this._zod.def,catchall:no()})},loose(){return this.clone({...this._zod.def,catchall:no()})},strict(){return this.clone({...this._zod.def,catchall:Ga()})},strip(){return this.clone({...this._zod.def,catchall:void 0})},extend(i){return z3(this,i)},safeExtend(i){return T3(this,i)},merge(i){return C3(this,i)},pick(i){return k3(this,i)},omit(i){return B3(this,i)},partial(...i){return R3(T7,this,i[0])},required(...i){return N3(C7,this,i[0])}})});function c(t,r){const i={type:"object",shape:t??{},...ie(r)};return new j8(i)}const z7=$("ZodUnion",(t,r)=>{g7.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>A_(t,i,s,u),t.options=r.options});function un(t,r){return new z7({type:"union",options:t,...ie(r)})}const A8=$("ZodDiscriminatedUnion",(t,r)=>{z7.init(t,r),py.init(t,r)});function pr(t,r,i){return new A8({type:"union",options:r,discriminator:t,...ie(i)})}const O8=$("ZodIntersection",(t,r)=>{fy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>O_(t,i,s,u)});function $8(t,r){return new O8({type:"intersection",left:t,right:r})}const fm=$("ZodRecord",(t,r)=>{my.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>$_(t,i,s,u),t.keyType=r.keyType,t.valueType=r.valueType});function pe(t,r,i){return!r||!r._zod?new fm({type:"record",keyType:e(),valueType:t,...ie(r)}):new fm({type:"record",keyType:t,valueType:r,...ie(i)})}const cu=$("ZodEnum",(t,r)=>{vy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(s,u,f)=>T_(t,s,u),t.enum=r.entries,t.options=Object.values(r.entries);const i=new Set(Object.keys(r.entries));t.extract=(s,u)=>{const f={};for(const p of s)if(i.has(p))f[p]=r.entries[p];else throw new Error(`Key ${p} not found in enum`);return new cu({...r,checks:[],...ie(u),entries:f})},t.exclude=(s,u)=>{const f={...r.entries};for(const p of s)if(i.has(p))delete f[p];else throw new Error(`Key ${p} not found in enum`);return new cu({...r,checks:[],...ie(u),entries:f})}});function me(t,r){const i=Array.isArray(t)?Object.fromEntries(t.map(s=>[s,s])):t;return new cu({type:"enum",entries:i,...ie(r)})}const D8=$("ZodLiteral",(t,r)=>{gy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>C_(t,i,s),t.values=new Set(r.values),Object.defineProperty(t,"value",{get(){if(r.values.length>1)throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");return r.values[0]}})});function g(t,r){return new D8({type:"literal",values:Array.isArray(t)?t:[t],...ie(r)})}const M8=$("ZodTransform",(t,r)=>{hy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>N_(t,i),t._zod.parse=(i,s)=>{if(s.direction==="backward")throw new Qm(t.constructor.name);i.addIssue=f=>{if(typeof f=="string")i.issues.push(si(f,i.value,r));else{const p=f;p.fatal&&(p.continue=!1),p.code??(p.code="custom"),p.input??(p.input=i.value),p.inst??(p.inst=t),i.issues.push(si(p))}};const u=r.transform(i.value,i);return u instanceof Promise?u.then(f=>(i.value=f,i.fallback=!0,i)):(i.value=u,i.fallback=!0,i)}});function L8(t){return new M8({type:"transform",transform:t})}const T7=$("ZodOptional",(t,r)=>{h7.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>S7(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function mm(t){return new T7({type:"optional",innerType:t})}const q8=$("ZodExactOptional",(t,r)=>{yy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>S7(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function F8(t){return new q8({type:"optional",innerType:t})}const U8=$("ZodNullable",(t,r)=>{_y.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>D_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function vm(t){return new U8({type:"nullable",innerType:t})}const Z8=$("ZodDefault",(t,r)=>{xy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>L_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType,t.removeDefault=t.unwrap});function V8(t,r){return new Z8({type:"default",innerType:t,get defaultValue(){return typeof r=="function"?r():t7(r)}})}const W8=$("ZodPrefault",(t,r)=>{Iy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>q_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function G8(t,r){return new W8({type:"prefault",innerType:t,get defaultValue(){return typeof r=="function"?r():t7(r)}})}const C7=$("ZodNonOptional",(t,r)=>{Ey.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>M_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function H8(t,r){return new C7({type:"nonoptional",innerType:t,...ie(r)})}const X8=$("ZodCatch",(t,r)=>{wy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>F_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType,t.removeCatch=t.unwrap});function K8(t,r){return new X8({type:"catch",innerType:t,catchValue:typeof r=="function"?r:()=>r})}const J8=$("ZodPipe",(t,r)=>{Sy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>U_(t,i,s,u),t.in=r.in,t.out=r.out});function gm(t,r){return new J8({type:"pipe",in:t,out:r})}const Q8=$("ZodReadonly",(t,r)=>{by.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>Z_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function Y8(t){return new Q8({type:"readonly",innerType:t})}const e5=$("ZodCustom",(t,r)=>{ky.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>R_(t,i)});function t5(t,r={}){return y_(e5,t,r)}function n5(t,r){return __(t,r)}function h(t){return o_(C8,t)}const o5=c({MaxMessageLength:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),SupportsAttachments:R(),SupportsChildConversations:R()}),ci=c({account_id:e(),provider:e()});c({dir:e().optional(),name:e().min(1),provider:e().min(1),scope:e().optional()});c({agent:e(),status:e()});const r5=c({agent_id:e(),parent_tool_use_id:e()});c({dir:e().optional(),env:pe(e(),e()).optional(),name:e().optional(),provider:e().optional(),scope:e().optional(),suspended:R().optional(),tmux_alias:e().optional(),work_dir:e().optional()});c({provider:e().optional(),scope:e().optional(),suspended:R().optional()});c({provider:e().optional(),scope:e().optional(),suspended:R().optional()});const i5=c({dir:e().optional(),is_pool:R().optional(),name:e(),origin:e(),provider:e().optional(),scope:e().optional(),suspended:R()}),a5=c({acp_args:y(e()).optional(),acp_command:e().optional(),args:y(e()).nullish(),command:e().optional(),display_name:e().optional(),env:pe(e(),e()).optional(),origin:e(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({event_cursor:e(),request_id:e(),status:e()});c({event_cursor:e(),request_id:e()});c({assignee:e().optional()});const Ru=c({attempted_claimant:e(),bead_id:e(),existing_claimant:e()});c({assignee:e().optional(),defer_until:k().optional(),description:e().optional(),labels:y(e()).nullish(),metadata:pe(e(),e()).optional(),parent:e().optional(),priority:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),rig:e().optional(),title:e().min(1),type:e().optional()});const Nu=c({bead_id:e(),dead_assignee:e().optional(),routed_to:e().optional()});c({assignee:e().optional(),description:e().optional(),labels:y(e()).nullish(),metadata:pe(e(),e()).optional(),parent:e().nullish(),priority:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),remove_labels:y(e()).nullish(),status:e().optional(),title:e().optional(),type:e().optional()});const Pu=c({bead_id:e(),path:e(),reason:e(),rig:e()}),ju=c({bead_id:e(),branch:e(),path:e(),rig:e()}),s5=c({beads_store:e(),degraded:R().optional(),gc_bd_inflight:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),native_store_eligible:R(),preflight_gate:e().optional(),preflight_reason:e().optional()}),l5=me(["active","ended"]),Au=c({agent_name:e().optional(),conversation_id:e(),provider:e(),session_id:e()}),Ou=c({backoff_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),failures:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),from:e(),op_class:e(),scope:e(),to:e()});c({bootstrap_profile:me(["k8s-cell","kubernetes","kubernetes-cell","single-host-compat"]).optional(),dir:e().min(1),provider:e().min(1).optional(),start_command:e().optional()});const $u=c({name:e(),path:e(),request_id:e()});c({agent_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),name:e(),path:e(),provider:e().optional(),rig_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_template:e().optional(),suspended:R(),uptime_sec:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),version:e().optional()});const u5=c({error:e().optional(),name:e(),path:e(),phases_completed:y(e()).nullish(),running:R(),status:e().optional()}),di=c({name:e(),path:e()});c({suspended:R().optional()});const c5=c({kind:e(),request_id:e(),session_id:e()}),Du=c({name:e(),path:e(),request_id:e()}),Mu=c({bd_version:e().optional(),mode:e(),origin:e(),reason:e(),store_id:e(),store_kind:e()}),d5=c({dir:e().optional(),is_pool:R().optional(),name:e(),provider:e().optional(),scope:e().optional(),suspended:R()}),p5=c({agents:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),providers:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),rigs:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({agents:y(i5).nullable(),patches:p5,providers:pe(e(),a5)});const f5=c({agent_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),provider_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),rig_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),m5=c({name:e(),path:e(),prefix:e().optional(),suspended:R()});c({errors:y(e()).nullable(),valid:R(),warnings:y(e()).nullable()});const Lu=c({duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),phase:e(),threshold_breach:R().optional()});c({GroupID:e(),Handle:e(),ID:e(),Metadata:pe(e(),e()),Public:R(),SessionID:e(),SessionName:e()});const v5=me(["dm","room","thread"]),Yt=c({account_id:e(),conversation_id:e(),kind:v5,parent_conversation_id:e().optional(),provider:e(),scope_id:e()});c({items:y(e()).nullish()});c({closed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),complete:R(),convoy_id:e(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({items:y(e()).nullish(),rig:e().optional(),title:e().min(1)});const g5=c({closed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({items:y(e()).nullish()});const h5=c({BindingGeneration:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),Conversation:Yt,ID:e(),LastMessageID:e(),LastPublishedAt:k(),Metadata:pe(e(),e()),SchemaVersion:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),SessionID:e(),SourceSessionID:e()}),y5=c({depends_on_id:e(),issue_id:e(),type:e()}),xo=c({assignee:e().optional(),created_at:k(),defer_until:k().optional(),dependencies:y(y5).nullish(),description:e().optional(),ephemeral:R().optional(),from:e().optional(),id:e(),is_blocked:R().optional(),issue_type:e(),labels:y(e()).nullish(),metadata:pe(e(),e()).optional(),needs:y(e()).nullish(),no_history:R().optional(),parent:e().optional(),priority:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),ref:e().optional(),status:e(),title:e(),updated_at:k().optional()});c({children:y(xo).nullable()});const Cn=c({bead:xo});c({children:y(xo).nullish(),convoy:xo.optional(),progress:g5.optional()});const qu=c({check:e(),city:e().optional(),detail:e(),subject:e().optional()}),_5=c({location:e().optional(),message:e().optional(),value:no().optional()});c({code:e().optional(),detail:e().optional(),errors:y(_5).nullish(),instance:pm().optional(),status:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),title:e().optional(),type:pm().optional().default("about:blank")});c({status:e()});c({actor:e().min(1),message:e().optional(),subject:e().optional(),type:e().min(1)});const x5=c({seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),ts:k(),type:e()}),I5=c({compression_status:me(["pending","complete"]),first_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),last_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),path:e()});c({anchor_event:x5.optional(),archive:I5.optional(),reason:e().optional(),rotated:R()});c({account_id:e().min(1),callback_url:e().optional(),capabilities:o5.optional(),name:e().optional(),provider:e().min(1)});c({account_id:e(),name:e(),provider:e(),status:e()});c({account_id:e().min(1),provider:e().min(1)});c({agent_name:e().optional(),conversation:Yt.optional(),metadata:pe(e(),e()).optional(),replace:R().optional(),session_id:e().optional()});c({default_handle:e().optional(),metadata:pe(e(),e()).optional(),mode:e().optional(),root_conversation:Yt.optional()});c({conversation:Yt.optional(),idempotency_key:e().optional(),reply_to_message_id:e().optional(),session_id:e().min(1),text:e().optional()});c({group_id:e().min(1),handle:e().min(1)});c({group_id:e().min(1),handle:e().min(1),metadata:pe(e(),e()).optional(),public:R().optional(),session_id:e().min(1)});c({conversation:Yt.optional(),sequence:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),session_id:e().min(1)});c({agent_name:e().optional(),conversation:Yt.optional(),session_id:e().optional()});const R7=c({display_name:e(),id:e(),is_bot:R()}),N7=c({mime_type:e(),provider_id:e(),url:e()}),P7=c({actor:R7,attachments:y(N7).nullish(),conversation:Yt,dedup_key:e().optional(),explicit_target:e().optional(),provider_message_id:e(),received_at:k(),reply_to_message_id:e().optional(),text:e()});c({account_id:e().optional(),message:P7.optional(),payload:e().optional(),provider:e().optional()});const E5=c({account_id:e(),name:e(),provider:e()}),w5=c({AllowUntargetedPublication:R(),Enabled:R(),MaxPeerTriggeredPublishes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),MaxTotalPeerDeliveries:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({DefaultHandle:e(),FanoutPolicy:w5,ID:e(),LastAddressedHandle:e(),Metadata:pe(e(),e()),Mode:e(),RootConversation:Yt,SchemaVersion:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({scope_kind:e().optional(),scope_ref:e().optional(),target:e().min(1),vars:pe(e(),e()).optional()});const j7=c({from:e(),kind:e().optional(),to:e()}),S5=c({id:e(),kind:e(),scope_ref:e().optional(),title:e()}),b5=c({edges:y(j7).nullable(),nodes:y(S5).nullable()}),A7=c({started_at:e(),status:e(),target:e(),updated_at:e(),workflow_id:e()});c({formula:e(),partial:R(),partial_errors:y(e()).nullish(),recent_runs:y(A7).nullable(),run_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({name:e(),source:e()});const k5=c({assignee:e().optional(),id:e(),kind:e(),labels:y(e()).nullish(),metadata:pe(e(),e()).optional(),title:e(),type:e().optional()});c({errors:y(e()).nullish(),valid:R()});const O7=c({default:no().optional(),description:e().optional(),enum:y(e()).nullish(),name:e(),pattern:e().optional(),required:R().optional(),type:e()});c({deps:y(j7).nullable(),description:e(),name:e(),preview:b5,steps:y(k5).nullable(),var_defs:y(O7).nullable()});const B5=c({description:e(),name:e(),recent_runs:y(A7).nullable(),run_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),var_defs:y(O7).nullable()});c({items:y(B5).nullable(),partial:R(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const z5=c({ahead:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),behind:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),branch:e(),changed_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),clean:R()}),Fu=c({conversation_id:e(),mode:e(),provider:e()}),T5=c({Match:e(),TargetSessionID:e(),UpdateCursor:R()});c({city:e().optional(),status:e(),uptime_sec:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),version:e().optional()});const fr=c({timestamp:e()}),Uu=c({actor:e(),conversation_id:e(),provider:e(),target_agent:e().optional(),target_session:e()});c({items:y(xo).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({items:y(c5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({items:y(E5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const C5=pe(e(),Ga());c({partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),unread:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({body:e().optional(),from:e().optional(),subject:e().optional()});c({body:e().optional(),from:e().optional(),rig:e().optional(),subject:e().min(1),to:e().min(1)});const du=c({after_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),before_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),duration_s:pt(),err:e().optional(),finished_at:e(),snapshot_path:e().optional(),stage:e(),started_at:e()});c({enabled:R(),history:y(du).nullable(),in_flight:R(),in_flight_start:e().optional(),interval_seconds:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),last_run:du.optional(),next_scheduled:e().optional()});c({accepted:R(),run:du.optional(),started_at:e().optional()});const $7=c({body:e(),cc:y(e()).nullish(),created_at:k(),from:e(),id:e(),priority:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),read:R(),reply_to:e().optional(),rig:e().optional(),subject:e(),thread_id:e().optional(),to:e()}),ht=c({message:$7.optional(),rig:e()});c({items:y($7).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const Zu=c({actor:e(),close_reason:e().optional(),from_status:e(),issue_id:e(),session_id:e().optional(),session_name:e().optional(),to_status:e(),ts:k(),work_dir:e().optional()}),D7=c({attached_bead_id:e().optional(),bead_id:e().optional(),detail_available:R().optional(),id:e(),logical_bead_id:e().optional(),root_bead_id:e().optional(),root_store_ref:e().optional(),run_detail_available:R().optional(),scope_kind:e(),scope_ref:e(),started_at:e(),status:e(),store_ref:e().optional(),target:e(),title:e(),type:e(),updated_at:e(),workflow_id:e().optional()});c({items:y(D7).nullable(),partial:R(),partial_errors:y(e()).nullish()});const fe=pe(e(),Ga());c({status:e()});c({id:e().optional(),status:e()});const R5=c({label:e(),value:e()}),N5=c({due:R(),last_run:e().optional(),last_run_outcome:e().optional(),name:e(),reason:e(),rig:e().optional(),scoped_name:e()});c({checks:y(N5).nullable()});const Vu=c({elapsed_s:pt(),order:e(),scope:e().optional()});c({bead_id:e(),created_at:e(),labels:y(e()).nullable(),output:e(),store_ref:e()});const P5=c({bead_id:e(),capture_output:R(),created_at:e(),duration_ms:e().optional(),error:e().optional(),exit_code:e().optional(),has_output:R(),labels:y(e()).nullable(),name:e(),rig:e().optional(),scoped_name:e(),signal:e().optional(),store_ref:e(),wisp_root_id:e().optional()});c({entries:y(P5).nullable()});const j5=c({capture_output:R(),check:e().optional(),check_timeout:e().optional(),check_timeout_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),description:e().optional(),enabled:R(),env:pe(e(),e()).optional(),exec:e().optional(),formula:e().optional(),gate:e().optional(),interval:e().optional(),name:e(),on:e().optional(),pool:e().optional(),rig:e().optional(),schedule:e().optional(),scoped_name:e(),timeout:e().optional(),timeout_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),trigger:e().optional(),type:e()});c({orders:y(j5).nullable()});c({vars:pe(e(),e()).optional()});c({scoped_name:e().optional(),status:e(),tracking_id:e().optional()});c({items:y(D7).nullable(),partial:R(),partial_errors:y(e()).nullish()});const Wu=c({conversation_id:e(),owner_session:e(),posting_session:e(),provider:e()}),Gu=c({conversation_id:e(),message_id:e(),provider:e(),session:e()}),Hu=c({role:e(),text:e(),timestamp:e().optional()});c({name:e().optional(),source:e().min(1),version:e().optional()});c({git_backed:R(),name:e(),source:e(),version:e().optional()});c({name:e()});const A5=c({name:e(),source:e().optional(),version:e().optional()});c({packs:y(A5).nullable()});const So=c({has_newer_messages:R().optional(),has_older_messages:R(),returned_message_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total_compactions:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total_message_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),truncated_before_message:e().optional()}),M7=c({agent:e(),format:e(),pagination:So.optional(),turns:y(Hu).nullable()});c({agent_patch:e().optional(),provider_patch:e().optional(),rig_patch:e().optional(),status:e()});c({agent_patch:e().optional(),provider_patch:e().optional(),rig_patch:e().optional(),status:e()});const Xu=c({kind:e(),metadata:pe(e(),e()).optional(),options:y(e()).nullish(),prompt:e().optional(),request_id:e()}),O5=c({Check:e().nullable(),DrainTimeout:e().nullable(),Max:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),Min:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),OnBoot:e().nullable(),OnDeath:e().nullable()}),$5=c({AppendFragments:y(e()).nullable(),Args:y(e()).nullable(),AssignedWorkDeferLimit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),Attach:R().nullable(),DefaultSlingFormula:e().nullable(),DependsOn:y(e()).nullable(),Dir:e(),Env:pe(e(),e()),EnvRemove:y(e()).nullable(),HooksInstalled:R().nullable(),IdleTimeout:e().nullable(),InjectAssignedSkills:R().nullable(),InjectFragments:y(e()).nullable(),InjectFragmentsAppend:y(e()).nullable(),InstallAgentHooks:y(e()).nullable(),InstallAgentHooksAppend:y(e()).nullable(),Lifecycle:e().nullable(),MCP:y(e()).nullable(),MCPAppend:y(e()).nullable(),MaxActiveSessions:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),MaxSessionAge:e().nullable(),MaxSessionAgeJitter:e().nullable(),MinActiveSessions:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),MouseMode:e().nullable(),Name:e(),Nudge:e().nullable(),OptionDefaults:pe(e(),e()),OverlayDir:e().nullable(),Pool:O5,PreStart:y(e()).nullable(),PreStartAppend:y(e()).nullable(),PromptTemplate:e().nullable(),Provider:e().nullable(),ResumeCommand:e().nullable(),ScaleCheck:e().nullable(),Scope:e().nullable(),Session:e().nullable(),SessionLive:y(e()).nullable(),SessionLiveAppend:y(e()).nullable(),SessionSetup:y(e()).nullable(),SessionSetupAppend:y(e()).nullable(),SessionSetupScript:e().nullable(),Skills:y(e()).nullable(),SkillsAppend:y(e()).nullable(),SleepAfterIdle:e().nullable(),StartCommand:e().nullable(),Suspended:R().nullable(),Tier:e().nullable(),TmuxAlias:e().nullable(),Upstream:e().nullable(),WakeMode:e().nullable(),WorkDir:e().nullable()});c({items:y($5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const Ku=c({host:e(),port:e(),scope_kind:e(),scope_name:e(),source:e(),user:e()}),Ju=c({layer:e(),new_id:e(),old_id:e().optional(),scope_root:e(),source:e()});c({acp_args:y(e()).nullish(),acp_command:e().optional(),args:y(e()).nullish(),args_append:y(e()).nullish(),base:e().optional(),command:e().optional(),display_name:e().optional(),env:pe(e(),e()).optional(),name:e().min(1),option_defaults:pe(e(),e()).optional(),options_schema_merge:e().optional(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({provider:e(),status:e()});const D5=c({choices:y(R5).nullable(),default:e(),key:e(),label:e(),type:e()}),M5=c({ACPArgs:y(e()).nullable(),ACPCommand:e().nullable(),AcceptStartupDialogs:R().nullable(),Args:y(e()).nullable(),ArgsAppend:y(e()).nullable(),Base:e().nullable(),Command:e().nullable(),Env:pe(e(),e()),EnvRemove:y(e()).nullable(),Name:e(),OptionsSchemaMerge:e().nullable(),PromptFlag:e().nullable(),PromptMode:e().nullable(),ReadyDelayMs:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),Replace:R()});c({items:y(M5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({accept_startup_dialogs:R().optional(),acp_args:y(e()).nullish(),acp_command:e().optional(),args:y(e()).nullish(),command:e().optional(),env:pe(e(),e()).optional(),name:e().optional(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});const L5=c({builtin:R(),city_level:R(),display_name:e().optional(),effective_defaults:pe(e(),e()).optional(),name:e(),options_schema:y(D5).nullish()});c({items:y(L5).nullable(),next_cursor:e().optional(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const q5=c({detail:e().optional(),display_name:e(),status:e()});c({providers:pe(e(),q5)});const F5=c({acp_args:y(e()).optional(),acp_command:e().optional(),args:y(e()).nullish(),builtin:R(),city_level:R(),command:e().optional(),display_name:e().optional(),env:pe(e(),e()).optional(),name:e(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({items:y(F5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const U5=c({acp_args:y(e()).optional(),acp_command:e().optional(),args:y(e()).nullish(),command:e().optional(),display_name:e().optional(),env:pe(e(),e()).optional(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({acp_args:y(e()).nullish(),acp_command:e().optional(),args:y(e()).nullish(),args_append:y(e()).nullish(),base:e().optional(),command:e().optional(),display_name:e().optional(),env:pe(e(),e()).optional(),option_defaults:pe(e(),e()).optional(),options_schema_merge:e().optional(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});const Qu=c({pids_signaled:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),quarantine_dir:e(),rate_limited:R().optional(),scope:e()}),Z5=c({Conversation:Yt,Delivered:R(),FailureKind:e(),MessageID:e(),Metadata:pe(e(),e()),RetryAfter:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),Yu=c({five_hour_resets_at:e().optional(),five_hour_util:pt(),opus_util:pt().optional(),provider:e(),seven_day_resets_at:e().optional(),seven_day_util:pt(),sonnet_util:pt().optional()}),ec=c({provider:e(),reason_class:e()}),V5=c({detail:e().optional(),display_name:e(),kind:e(),name:e(),status:e()});c({items:pe(e(),V5)});const pi=c({actor:e(),created_at:k(),hostname:e().optional(),id:e(),message:e(),metadata:pe(e(),e()).optional(),ref_bead:e().optional(),severity:e(),source_path:e().optional(),source_pid:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),tc=c({error_code:e(),error_message:e(),operation:me(["city.create","city.unregister","session.create","session.message","session.submit","rig.create"]),request_id:e()});c({action:e(),failed:y(e()).nullish(),killed:y(e()).nullish(),rig:e(),status:e()});c({default_branch:e().optional(),git_url:e().optional(),name:e().min(1),path:e().optional(),prefix:e().optional(),request_id:e().optional()});c({default_branch:e().optional(),event_cursor:e().optional(),prefix:e().optional(),request_id:e().optional(),rig:e().optional(),status:me(["created","accepted","exists"])});const nc=c({default_branch:e(),prefix:e(),request_id:e(),rig:e()}),W5=c({DefaultBranch:e().nullable(),FormulaVars:pe(e(),e()),Name:e(),Path:e().nullable(),Prefix:e().nullable(),Suspended:R().nullable(),SuspendedOnStart:R().nullable()});c({items:y(W5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({default_branch:e().optional(),name:e().optional(),path:e().optional(),prefix:e().optional(),suspended:R().optional()});const oc=c({detail:e().optional(),request_id:e().optional(),rig:e(),step:e(),warn:R().optional()}),G5=c({agent_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),default_branch:e().optional(),git:z5.optional(),last_activity:k().optional(),name:e(),path:e(),prefix:e().optional(),running_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),suspended:R()});c({items:y(G5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({default_branch:e().optional(),path:e().optional(),prefix:e().optional(),suspended:R().optional()});const rc=c({prior_archive:e(),prior_first_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),prior_last_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),H5=c({code:e(),message:e().optional()}),X5=c({kind:e().optional(),ref:e().optional()}),ic=me(["pending","active","waiting","canceling","completed","failed","canceled","skipped"]),K5=c({formula:e().optional(),last_error:H5.optional(),run_id:e(),scope:X5,started_at:e().optional(),status:ic,target:e().optional(),title:e(),updated_at:e().optional()});c({closed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),run_id:e(),status:ic});const J5=c({kind:me(["sling","order"]),run_id:e(),status:ic}),L7=c({active:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),canceled:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),canceling:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),completed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),failed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),pending:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),skipped:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),waiting:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),Q5=me(["pending","active","blocked","completed","failed","skipped","canceled"]),Y5=c({assignee:e().optional(),id:e(),kind:e().optional(),status:Q5,title:e()});c({run_id:e(),steps:y(Y5).nullable()});c({partial:R().optional(),partial_errors:y(e()).nullish(),status_counts:L7});c({partial:R().optional(),partial_errors:y(e()).nullish(),runs:y(K5).nullable(),status_counts:L7});const ex=pe(e(),Ga());c({action:e(),service:e(),status:e()});const q7=c({activity:e()});c({messages:y(no()).nullable(),status:e().optional()});c({agents:y(r5).nullable()});const ac=c({AgentName:e(),BindingGeneration:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),BoundAt:k(),Conversation:Yt,ExpiresAt:k().nullable(),ID:e(),Metadata:pe(e(),e()),SchemaVersion:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),SessionID:e(),SessionName:e(),Status:l5});c({unbound:y(ac).nullable()});c({items:y(ac).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({alias:e().optional(),async:R().optional(),kind:e().optional(),message:e().optional(),name:e().optional(),options:pe(e(),e()).optional(),project_id:e().optional(),session_name:e().optional(),title:e().optional()});const sc=c({bead_id:e(),bead_status:e().optional(),reason:e().optional(),session_id:e(),template:e().optional()}),tx=c({attached:R(),last_activity:k().optional(),name:e()}),nx=c({active_bead:e().optional(),activity:e().optional(),available:R(),context_pct:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_window:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),description:e().optional(),display_name:e().optional(),last_output:e().optional(),model:e().optional(),name:e(),pack:e().optional(),pack_derived:R(),pool:e().optional(),provider:e().optional(),rig:e().optional(),running:R(),session:tx.optional(),state:e(),suspended:R(),unavailable_reason:e().optional()});c({items:y(nx).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const bo=c({reason:e().optional(),session_id:e(),template:e().optional()});c({message:e().min(1).regex(/\S/)});const lc=c({request_id:e(),session_id:e()});c({alias:e().optional(),title:e().min(1).optional()});const F7=c({request_id:e()});c({pending:Xu.optional(),supported:R()});c({permission_mode:e().min(1).regex(/\S/)});const U7=no();c({title:e().min(1)});const uc=c({elapsed_s:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),reset_committed_at:e(),session_name:e(),template:e()});c({action:e().min(1),metadata:pe(e(),e()).optional(),request_id:e().optional(),text:e().optional()});c({id:e(),status:e()});const cc=c({session_id:e(),session_name:e().optional(),template:e().optional(),work_bead_ids:y(e()).nullish()});un([q7,Xu,F7,fr]);const ox=c({format:e(),id:e(),pagination:So.optional(),provider:e(),template:e(),turns:y(Hu).nullable()}),rx=c({format:e(),id:e(),messages:y(U7).nullable(),pagination:So.optional(),provider:e(),template:e()}),cn=c({name:e(),value:e()}),ix=c({file_path:e().optional(),image_url:e().optional(),mime_type:e().optional(),text:e().optional(),type:g("image")}),ax=c({text:e().optional(),type:g("text")}),sx=c({signature:e().optional(),thinking:e().optional(),type:g("thinking")}),lx=c({compaction_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),has_branches:R().optional(),note:e().optional(),status:e()}),ux=c({after_entry_id:e().optional(),resume_token:e()}),cx=c({code:e(),count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),message:e().optional()}),dx=c({id:e(),observed_at:e().optional()}),px=c({text:e().optional()}),Z7=c({action:e().optional(),kind:e().optional(),options:y(e()).nullish(),prompt:e().optional(),request_id:e().optional(),state:e()}),fx=c({interaction:Z7.optional(),type:g("interaction")}),dc=c({file_path:e().optional(),lines:y(e()).nullish(),new_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),new_start:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),old_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),old_start:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),Ha=c({status:e().optional(),step:e().optional()}),mx=c({description:e().optional(),label:e().optional()}),V7=c({header:e().optional(),multi_select:R().optional(),options:y(mx).nullish(),question:e().optional()}),pc=c({snippet:e().optional(),title:e().optional(),url:e().optional()}),W7=c({category:e().optional(),code:e().optional(),kind:e().optional(),message:e().optional()}),vx=c({activity:e(),degraded:R().optional(),degraded_reason:e().optional(),last_entry_id:e().optional(),open_tool_call_ids:y(e()).nullish(),pending_interaction_ids:y(e()).nullish()}),G7=c({continuity:lx,cursor:ux,diagnostics:y(cx).nullish(),gc_session_id:e().optional(),generation:dx,logical_conversation_id:e().optional(),provider_session_id:e().optional(),tail_state:vx,transcript_stream_id:e()}),sr=c({active_form:e().optional(),content:e().optional(),id:e().optional(),priority:e().optional(),status:e().optional()}),ft=c({category:me(["user_rejection","user_rejection_with_reason","command_failure","file_error","validation_error","timeout","network_error","unknown"]),message:e().optional(),user_reason:e().optional()}),gx=c({arguments:y(cn),kind:g("arguments")}),hx=c({code:e(),kind:g("code"),language:e().optional()}),yx=c({arguments:y(cn).nullish(),command:e(),kind:g("command")}),_x=c({kind:g("fetch"),prompt:e().optional(),url:e().optional()}),xx=c({command:e().optional(),file_path:e(),kind:g("file"),language:e().optional()}),Ix=c({arguments:y(cn).nullish(),file_path:e().optional(),kind:g("glob"),pattern:e().optional(),query:e().optional()}),Ex=c({file_path:e().optional(),kind:g("patch"),language:e().optional(),patch:e()}),wx=c({explanation:e().optional(),kind:g("plan"),plan:e().optional(),steps:y(Ha).nullish()}),Sx=c({kind:g("question"),options:y(e()).nullish(),question:e().optional()}),bx=c({arguments:y(cn).nullish(),command:e().optional(),file_path:e().optional(),kind:g("search"),pattern:e().optional(),query:e().optional()}),kx=c({kind:g("stdin"),linked_command:e().optional(),task_id:e().optional(),text:e().optional()}),Bx=c({description:e().optional(),kind:g("task"),prompt:e().optional(),task_id:e().optional(),task_status:e().optional(),task_type:e().optional()}),zx=c({kind:g("text"),text:e()}),Tx=c({kind:g("todo"),todos:y(sr).nullish()}),Cx=c({arguments:y(cn).nullish(),code:e().optional(),command:e().optional(),description:e().optional(),explanation:e().optional(),file_path:e().optional(),kind:g("unknown"),language:e().optional(),linked_command:e().optional(),options:y(e()).nullish(),patch:e().optional(),pattern:e().optional(),plan:e().optional(),prompt:e().optional(),query:e().optional(),question:e().optional(),steps:y(Ha).nullish(),task_id:e().optional(),task_status:e().optional(),task_type:e().optional(),text:e().optional(),todos:y(sr).nullish(),url:e().optional()}),Rx=c({file_path:e().optional(),kind:g("write"),language:e().optional(),text:e().optional()}),H7=pr("kind",[Cx.extend({kind:g("unknown")}),yx.extend({kind:g("command")}),kx.extend({kind:g("stdin")}),hx.extend({kind:g("code")}),Ex.extend({kind:g("patch")}),Rx.extend({kind:g("write")}),Ix.extend({kind:g("glob")}),_x.extend({kind:g("fetch")}),bx.extend({kind:g("search")}),xx.extend({kind:g("file")}),Tx.extend({kind:g("todo")}),wx.extend({kind:g("plan")}),Sx.extend({kind:g("question")}),Bx.extend({kind:g("task")}),zx.extend({kind:g("text")}),gx.extend({kind:g("arguments")})]),Nx=c({file_path:e().optional(),id:e().optional(),input:H7.optional(),name:e().optional(),type:g("tool_use")}),Px=c({command:e().optional(),content:e().optional(),error:ft.optional(),exit_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),interrupted:R().optional(),is_image:R().optional(),kind:g("bash"),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),stderr:e().optional(),stderr_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),stdout:e().optional(),stdout_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),task_id:e().optional(),task_status:e().optional(),text:e().optional(),timestamp:e().optional(),truncated:R().optional()}),jx=c({content:e().optional(),error:ft.optional(),file_path:e().optional(),file_paths:y(e()).nullish(),kind:g("edit"),new_string:e().optional(),old_string:e().optional(),original_file:e().optional(),patch:e().optional(),patch_hunks:y(dc).nullish(),replace_all:R().optional(),user_modified:R().optional()}),Ax=c({bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),content:e().optional(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),kind:g("fetch"),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),status_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),status_text:e().optional(),text:e().optional(),url:e().optional()}),Ox=c({content:e().optional(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),filenames:y(e()).nullish(),kind:g("glob"),num_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),truncated:R().optional()}),$x=c({applied_limit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),content:e().optional(),counts:y(cn).nullish(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),filenames:y(e()).nullish(),kind:g("grep"),mode:e().optional(),num_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_results:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),query:e().optional(),result_items:y(pc).nullish()}),Dx=c({content:e().optional(),error:ft.optional(),explanation:e().optional(),kind:g("plan"),plan:e().optional(),steps:y(Ha).nullish(),text:e().optional()}),Mx=c({code:e().optional(),error:ft.optional(),exit_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),interrupted:R().optional(),is_image:R().optional(),kind:g("python"),stderr:e().optional(),stdout:e().optional(),text:e().optional(),truncated:R().optional()}),Lx=c({answer:e().optional(),answers:y(cn).nullish(),content:e().optional(),error:ft.optional(),kind:g("question"),options:y(e()).nullish(),question:e().optional(),questions:y(V7).nullish(),text:e().optional()}),qx=c({content:e().optional(),error:ft.optional(),file_path:e().optional(),kind:g("read"),language:e().optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),start_line:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),Fx=c({applied_limit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),content:e().optional(),counts:y(cn).nullish(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),filenames:y(e()).nullish(),kind:g("search"),mode:e().optional(),num_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_results:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),query:e().optional(),result_items:y(pc).nullish()}),Ux=c({content:e().optional(),error:ft.optional(),kind:g("stdin"),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),task_id:e().optional(),text:e().optional()}),Zx=c({content:e().optional(),description:e().optional(),error:ft.optional(),exit_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),kind:g("task"),output:e().optional(),stderr:e().optional(),stdout:e().optional(),task_id:e().optional(),task_status:e().optional(),task_type:e().optional(),text:e().optional(),total_duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_tool_use_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),Vx=c({content:e().optional(),error:ft.optional(),kind:g("text"),text:e().optional()}),Wx=c({content:e().optional(),error:ft.optional(),kind:g("todo"),new_todos:y(sr).nullish(),old_todos:y(sr).nullish(),text:e().optional()}),Gx=c({answer:e().optional(),answers:y(cn).nullish(),applied_limit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),code:e().optional(),command:e().optional(),content:e().optional(),counts:y(cn).nullish(),description:e().optional(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),exit_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),explanation:e().optional(),file_path:e().optional(),file_paths:y(e()).nullish(),filenames:y(e()).nullish(),interrupted:R().optional(),is_image:R().optional(),kind:g("unknown"),language:e().optional(),mode:e().optional(),new_string:e().optional(),new_todos:y(sr).nullish(),num_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_results:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),old_string:e().optional(),old_todos:y(sr).nullish(),options:y(e()).nullish(),original_file:e().optional(),output:e().optional(),patch:e().optional(),patch_hunks:y(dc).nullish(),plan:e().optional(),query:e().optional(),question:e().optional(),questions:y(V7).nullish(),replace_all:R().optional(),result_items:y(pc).nullish(),start_line:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),status_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),status_text:e().optional(),stderr:e().optional(),stderr_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),stdout:e().optional(),stdout_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),steps:y(Ha).nullish(),task_id:e().optional(),task_status:e().optional(),task_type:e().optional(),text:e().optional(),timestamp:e().optional(),total_duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_tool_use_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),truncated:R().optional(),url:e().optional(),user_modified:R().optional()}),Hx=c({content:e().optional(),error:ft.optional(),file_path:e().optional(),file_paths:y(e()).nullish(),kind:g("write"),language:e().optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),patch:e().optional(),patch_hunks:y(dc).nullish(),start_line:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),text:e().optional(),total_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),X7=pr("kind",[Gx.extend({kind:g("unknown")}),Px.extend({kind:g("bash")}),Mx.extend({kind:g("python")}),qx.extend({kind:g("read")}),Ox.extend({kind:g("glob")}),$x.extend({kind:g("grep")}),Fx.extend({kind:g("search")}),Ax.extend({kind:g("fetch")}),Wx.extend({kind:g("todo")}),Dx.extend({kind:g("plan")}),Lx.extend({kind:g("question")}),Ux.extend({kind:g("stdin")}),Zx.extend({kind:g("task")}),Hx.extend({kind:g("write")}),jx.extend({kind:g("edit")}),Vx.extend({kind:g("text")})]),Xx=c({content:e().optional(),file_path:e().optional(),is_error:R().optional(),name:e().optional(),structured:X7.optional(),tool_call_id:e().optional(),type:g("tool_result")}),Kx=c({content:e().optional(),file_path:e().optional(),id:e().optional(),image_url:e().optional(),input:H7.optional(),interaction:Z7.optional(),is_error:R().optional(),mime_type:e().optional(),name:e().optional(),signature:e().optional(),structured:X7.optional(),text:e().optional(),thinking:e().optional(),tool_call_id:e().optional(),type:g("unknown")}),fi=pr("type",[ax.extend({type:g("text")}),sx.extend({type:g("thinking")}),Nx.extend({type:g("tool_use")}),Xx.extend({type:g("tool_result")}),fx.extend({type:g("interaction")}),ix.extend({type:g("image")}),Kx.extend({type:g("unknown")})]),Jx=c({blocks:y(fi),id:e(),provider:e().optional(),role:g("system"),status:me(["unknown","final","partial","superseded"]),system_event:W7.optional(),timestamp:e().optional()}),Qx=c({blocks:y(fi),id:e(),provider:e().optional(),role:g("tool"),status:me(["unknown","final","partial","superseded"]),timestamp:e().optional()}),Yx=c({file_path:e().optional(),mime_type:e().optional(),original_name:e().optional(),preview_url:e().optional(),size:e().optional()}),K7=c({cache_creation_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),cache_read_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_percent:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_used_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_window_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),input_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),output_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),reasoning_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),e4=c({blocks:y(fi),id:e(),model:e().optional(),provider:e().optional(),role:g("assistant"),status:me(["unknown","final","partial","superseded"]),stop_reason:e().optional(),timestamp:e().optional(),usage:K7.optional()}),J7=c({opened_files:y(e()).nullish(),selections:y(px).nullish(),text:e().optional(),uploaded_files:y(Yx).nullish()}),t4=c({blocks:y(fi),id:e(),model:e().optional(),provider:e().optional(),role:g("unknown"),status:me(["unknown","final","partial","superseded"]),stop_reason:e().optional(),system_event:W7.optional(),timestamp:e().optional(),usage:K7.optional(),user_prompt:J7.optional()}),n4=c({blocks:y(fi),id:e(),provider:e().optional(),role:g("user"),status:me(["unknown","final","partial","superseded"]),timestamp:e().optional(),user_prompt:J7.optional()}),Q7=pr("role",[t4.extend({role:g("unknown")}),n4.extend({role:g("user")}),e4.extend({role:g("assistant")}),Jx.extend({role:g("system")}),Qx.extend({role:g("tool")})]),Y7=c({format:g("structured"),history:G7,id:e(),operation:me(["snapshot","upsert","reset"]),pagination:So.optional(),provider:e(),reset_reason:me(["resume_invalid","stream_changed","cursor_invalidated","history_rewritten"]).optional(),schema_version:g("session.structured.v1"),structured_messages:y(Q7),template:e()}),fc=c({intent:e(),queued:R(),request_id:e(),session_id:e()}),o4=c({format:me(["conversation","text"]),id:e(),pagination:So.optional(),provider:e(),template:e(),turns:y(Hu).nullish()}),r4=c({format:me(["raw"]),id:e(),messages:y(U7).nullable(),pagination:So.optional(),provider:e(),template:e()}),i4=c({format:g("structured"),history:G7,id:e(),operation:g("snapshot"),pagination:So.optional(),provider:e(),schema_version:g("session.structured.v1"),structured_messages:y(Q7),template:e()});un([c({format:un([g("conversation"),g("text")])}).and(o4),c({format:g("raw")}).and(r4),c({format:g("structured")}).and(i4)]);const mc=c({escalated:R(),first_seen:e().optional(),session_id:e(),session_name:e().optional(),state:e()});c({attached_bead_id:e().optional(),bead:e().optional(),force:R().optional(),formula:e().optional(),merge:e().optional(),no_convoy:R().optional(),no_formula:R().optional(),owned:R().optional(),reassign:R().optional(),rig:e().optional(),scope_kind:e().optional(),scope_ref:e().optional(),target:e().min(1),title:e().optional(),vars:pe(e(),e()).optional()});c({attached_bead_id:e().optional(),bead:e().optional(),dashboard_url:e().optional(),formula:e().optional(),mode:e().optional(),root_bead_id:e().optional(),run:J5.optional(),status:e(),target:e(),warnings:y(e()).nullish(),workflow_id:e().optional()});const a4=c({allow_websockets:R().optional(),hostname:e().optional(),kind:e().optional(),local_state:e(),mount_path:e(),publication_state:e(),publish_mode:e(),reason:e().optional(),service_name:e(),state:e().optional(),state_root:e(),updated_at:k(),url:e().optional(),visibility:e().optional(),workflow_contract:e().optional()});c({items:y(a4).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const s4=c({quarantined:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),running:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),suspended:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),l4=c({draining:R().optional(),expanded:R().optional(),group_name:e().optional(),name:e(),qualified_name:e(),running:R(),scale_label:e().optional(),scope:e(),session_name:e().optional(),suspended:R()}),u4=c({capable:R(),kind:e(),latch:me(["incapable","unlatched"]),probe:me(["capable","incapable","unprobed"]),reason:e().optional(),store_id:e()}),c4=c({total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),unread:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),d4=c({identity:e(),mode:e(),status:e()}),p4=c({suspended:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),f4=c({name:e(),path:e(),suspended:R()}),m4=c({config_value:e().optional(),env_value:e().optional(),env_var:e().optional(),flag_key:e(),kind:e(),message:e()}),v4=c({effective:me(["off","active","degraded","fail_closed","pending_restart"]),mode:me(["off","auto","require"]),notices:y(m4).nullish(),origin:me(["builtin","config","env"]),stores:y(u4).nullish()}),g4=c({active:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),suspended:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),h4=c({last_gc_at:e().optional(),last_gc_status:e().optional(),live_rows:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),path:e(),ratio_mb_per_row:pt(),size_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),threshold_mb_per_row:pt(),warning:R()}),y4=c({in_progress:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),open:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),ready:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({agent_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),agent_details:y(l4).nullish(),agents:s4,beads:s5.optional(),beads_version:e().optional(),conditional_writes:v4.optional(),dolt_version:e().optional(),mail:c4,name:e(),named_session_details:y(d4).nullish(),partial:R().optional(),partial_errors:y(e()).nullish(),path:e(),rig_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),rig_details:y(f4).nullish(),rigs:p4,running:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_counts_detail:g4.optional(),store_health:h4.optional(),suspended:R(),uptime_sec:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),version:e().optional(),work:y4});const vc=c({class:e(),consecutive_fails:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),reason:e().optional(),scope:e()}),gc=c({data_dir:e(),floor_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),free_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),hc=c({data_dir:e(),floor_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),free_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),warn_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),yc=c({after_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),before_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),duration_s:pt(),snapshot_path:e()}),_c=c({duration_s:pt(),error_msg:e(),snapshot_path:e().optional(),stage:e()}),xc=c({probe:e(),reason:e().optional(),scope:e()}),Ic=c({class:e().optional(),scope:e()}),_4=c({supports_follow_up:R(),supports_interrupt_now:R()}),ev=c({active_bead:e().optional(),activity:e().optional(),agent_kind:e().optional(),alias:e().optional(),attached:R(),configured_named_session:R().optional(),context_pct:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_window:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),created_at:e(),display_name:e().optional(),id:e(),kind:e().optional(),last_active:e().optional(),last_nudge_delivered_at:e().optional(),last_output:e().optional(),metadata:pe(e(),e()).optional(),model:e().optional(),options:pe(e(),e()).optional(),pool:e().optional(),provider:e(),reason:e().optional(),rig:e().optional(),running:R(),session_name:e(),state:e(),submission_capabilities:_4.optional(),template:e(),title:e(),work_dir:e().optional()});c({items:y(ev).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const Ec=c({request_id:e(),session:ev}),x4=me(["default","follow_up","interrupt_now"]);c({intent:x4.optional(),message:e().min(1).regex(/\S/)});c({items:y(u5).nullable(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const wc=c({avg60:pt(),consecutive_skips:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),max_consecutive_skips:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),outcome:e(),threshold:pt(),trigger:e().optional()}),Sc=c({duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),host:e().optional(),method:e(),origin_allowed:R(),path:e(),phase:me(["start","complete"]),remote_addr_class:me(["loopback","private","public","unknown"]),request_id:e().optional(),status:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),bc=c({client_addr:e().optional(),mode:me(["destructive","preserve_sessions","unknown"]),signal:e().optional(),source:me(["signal","socket_stop"])}),kc=c({previous_exit:me(["clean","crash","unknown"])}),I4=c({phase:e().optional(),phases_completed:y(e()).nullish(),ready:R()});c({build_id:e().optional(),cities_running:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cities_total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),packs_lock_sha256:e().optional(),startup:I4.optional(),status:e(),uptime_sec:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),version:e()});const E4=me(["inbound","outbound"]),w4=me(["live","hydrated"]),Bc=c({Actor:R7,Attachments:y(N7).nullable(),Conversation:Yt,CreatedAt:k(),ExplicitTarget:e(),ID:e(),Kind:E4,Metadata:pe(e(),e()),Provenance:w4,ProviderMessageID:e(),ReplyToMessageID:e(),SchemaVersion:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),Sequence:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),SourceSessionID:e(),Text:e()});c({Binding:ac,GroupRoute:T5,Message:P7,TargetAgentName:e(),TargetSessionID:e(),TranscriptEntry:Bc});c({items:y(Bc).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({DeliveryContext:h5,Receipt:Z5,TranscriptEntry:Bc});const zc=c({count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e()}),S4=c({cache_creation_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cache_read_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cost_usd_estimate:pt(),input_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),output_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session:e(),session_id:e().optional(),unpriced:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),Jl=c({cache_creation_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cache_read_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),compute_facts:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cost_usd_estimate:pt(),input_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),invocations:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),output_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),unpriced:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),wall_seconds:pt()});c({available:R(),last_24h:Jl.optional(),observed_from:e().optional(),partial:R().optional(),partial_reasons:y(e()).nullish(),recent:Jl,recent_by_session:y(S4).nullish(),recent_window_secs:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),recording:R(),source:me(["local_estimate","unavailable"]),today:Jl,updated_at:e()});const b4=c({created_at:e().optional(),delivery_attempt:e().optional(),dep_ids:y(e()).nullish(),dep_mode:e().optional(),expires_at:e().optional(),id:e(),kind:e(),labels:y(e()).nullish(),note:e().optional(),nudge_id:e().optional(),registered_epoch:e().optional(),session_id:e(),session_name:e().optional(),state:e(),status:e()});c({capped:R(),partial:R().optional(),partial_errors:y(e()).nullish(),waits:y(b4).nullable()});const Tc=c({body_size:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),dedup_id:e().optional(),deduped:R(),dispatched:R(),event_type:e().optional(),matched:R(),order:e().optional(),rig:e().optional(),rule_index:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),scheme:e().optional(),scoped_name:e().optional(),tracking_id:e().optional(),webhook:e()}),Cc=c({body_size:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),dedup_id:e().optional(),event_type:e().optional(),reason:e(),scheme:e().optional(),status:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),webhook:e()}),Rc=c({agent_name:e().optional(),bead_id:e().optional(),cache_creation_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),cache_read_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),completion_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),cost_usd_estimate:pt().optional(),delivered:R().optional(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),error:e().optional(),finished_at:k(),latency_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),model:e().optional(),op_id:e(),operation:e(),prompt_sha:e().optional(),prompt_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),prompt_version:e().optional(),provider:e().optional(),queued:R().optional(),result:e(),run_id:e().optional(),session_id:e().optional(),session_name:e().optional(),started_at:k(),template:e().optional(),transport:e().optional(),unpriced:R().optional()}),tv=un([ci,Ru,Nu,Cn,Pu,ju,Au,Ou,$u,di,Du,Mu,Lu,qu,Fu,Uu,ht,Zu,fe,Vu,Wu,Gu,Ku,Ju,Qu,Yu,ec,pi,tc,nc,oc,rc,Ec,sc,bo,lc,uc,cc,fc,mc,vc,gc,hc,yc,_c,xc,Ic,wc,Sc,bc,kc,zc,Tc,Cc,Rc]),k4=c({active_attempt:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),attempt_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),max_attempts:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),nv=c({assignee:e().optional(),attempt:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),id:e(),kind:e(),logical_bead_id:e().optional(),metadata:pe(e(),e()),scope_ref:e().optional(),status:e(),step_ref:e().optional(),title:e()});c({closed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),deleted:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),partial:R().optional(),partial_errors:y(e()).nullish(),workflow_id:e()});const pu=c({from:e(),kind:e().optional(),to:e()});c({beads:y(xo).nullable(),deps:y(pu).nullable(),root:xo});const z=c({attempt_summary:k4.optional(),bead:nv,changed_fields:y(e()).nullable(),event_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),event_ts:e(),event_type:e(),logical_node_id:e(),requires_resync:R().optional(),root_bead_id:e(),root_store_ref:e(),scope_kind:e(),scope_ref:e(),type:e(),watch_generation:e(),workflow_id:e(),workflow_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:tv.optional(),run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:e(),workflow:z.optional()});c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:tv.optional(),run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:e(),workflow:z.optional()});const B4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ru,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.claim_rejected"),workflow:z.optional()}),z4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.closed"),workflow:z.optional()}),T4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.created"),workflow:z.optional()}),C4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Nu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.dead_assignee_reopened"),workflow:z.optional()}),R4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.deleted"),workflow:z.optional()}),N4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.updated"),workflow:z.optional()}),P4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Pu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.worktree.reap_skipped"),workflow:z.optional()}),j4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ju,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.worktree.reaped"),workflow:z.optional()}),A4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Mu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("beads.conditional_writes.degraded"),workflow:z.optional()}),O4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ou,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("breaker.state_changed"),workflow:z.optional()}),$4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:di,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.created"),workflow:z.optional()}),D4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.resumed"),workflow:z.optional()}),M4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.suspended"),workflow:z.optional()}),L4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:di,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.unregister_requested"),workflow:z.optional()}),q4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.started"),workflow:z.optional()}),F4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.stopped"),workflow:z.optional()}),U4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Lu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.tick_completed"),workflow:z.optional()}),Z4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("convoy.closed"),workflow:z.optional()}),V4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("convoy.created"),workflow:z.optional()}),W4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:no(),run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:e(),workflow:z.optional()}),G4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:qu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("doctor.alert"),workflow:z.optional()}),H4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:pi,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("emergency.acked"),workflow:z.optional()}),X4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:pi,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("emergency.signaled"),workflow:z.optional()}),K4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:rc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("events.rotated"),workflow:z.optional()}),J4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.step_defined"),workflow:z.optional()}),Q4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.work_associated"),workflow:z.optional()}),Y4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ci,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.adapter_added"),workflow:z.optional()}),e6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ci,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.adapter_removed"),workflow:z.optional()}),t6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Au,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.bound"),workflow:z.optional()}),n6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Fu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.group_created"),workflow:z.optional()}),o6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Uu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.inbound"),workflow:z.optional()}),r6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Gu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.outbound"),workflow:z.optional()}),i6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Wu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.outbound_channel_mismatch"),workflow:z.optional()}),a6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:zc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.unbound"),workflow:z.optional()}),s6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:gc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.disk_critical"),workflow:z.optional()}),l6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:hc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.disk_warn"),workflow:z.optional()}),u6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:yc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.maintenance.done"),workflow:z.optional()}),c6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:_c,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.maintenance.failed"),workflow:z.optional()}),d6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.archived"),workflow:z.optional()}),p6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.deleted"),workflow:z.optional()}),f6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.marked_read"),workflow:z.optional()}),m6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.marked_unread"),workflow:z.optional()}),v6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.read"),workflow:z.optional()}),g6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.replied"),workflow:z.optional()}),h6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.sent"),workflow:z.optional()}),y6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Zu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("molecule.resolved"),workflow:z.optional()}),_6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.completed"),workflow:z.optional()}),x6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.failed"),workflow:z.optional()}),I6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.fired"),workflow:z.optional()}),E6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Vu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.gate_timeout_fail_open"),workflow:z.optional()}),w6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ku,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("pg.credential_resolved"),workflow:z.optional()}),S6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ju,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("project.identity.stamped"),workflow:z.optional()}),b6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Yu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.quota_observed"),workflow:z.optional()}),k6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ec,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.quota_poll_failed"),workflow:z.optional()}),B6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.swapped"),workflow:z.optional()}),z6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Qu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("proxy.reaped"),workflow:z.optional()}),T6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:tc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.failed"),workflow:z.optional()}),C6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:$u,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.city.create"),workflow:z.optional()}),R6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Du,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.city.unregister"),workflow:z.optional()}),N6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:nc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.rig.create"),workflow:z.optional()}),P6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ec,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.create"),workflow:z.optional()}),j6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:lc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.message"),workflow:z.optional()}),A6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.submit"),workflow:z.optional()}),O6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:oc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("rig.provision.progress"),workflow:z.optional()}),$6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.cold_start_timeout"),workflow:z.optional()}),D6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.crashed"),workflow:z.optional()}),M6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:sc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.drain_acked_with_assigned_work"),workflow:z.optional()}),L6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.draining"),workflow:z.optional()}),q6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.idle_killed"),workflow:z.optional()}),F6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.max_age_killed"),workflow:z.optional()}),U6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.quarantined"),workflow:z.optional()}),Z6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:uc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.reset_stalled"),workflow:z.optional()}),V6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.stopped"),workflow:z.optional()}),W6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:cc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.stranded"),workflow:z.optional()}),G6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.suspended"),workflow:z.optional()}),H6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.undrained"),workflow:z.optional()}),X6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:mc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.unknown_state"),workflow:z.optional()}),K6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.updated"),workflow:z.optional()}),J6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.woke"),workflow:z.optional()}),Q6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.work_query_failed"),workflow:z.optional()}),Y6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:vc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.degraded"),workflow:z.optional()}),eI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:xc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.probe_failed"),workflow:z.optional()}),tI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ic,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.recovered"),workflow:z.optional()}),nI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:wc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.fs_pressure.skipped_tick"),workflow:z.optional()}),oI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Sc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.request"),workflow:z.optional()}),rI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.shutdown_requested"),workflow:z.optional()}),iI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:kc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.started"),workflow:z.optional()}),aI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Tc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("webhook.received"),workflow:z.optional()}),sI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("webhook.rejected"),workflow:z.optional()}),lI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Rc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("worker.operation"),workflow:z.optional()}),ov=pr("type",[B4.extend({type:g("bead.claim_rejected")}),z4.extend({type:g("bead.closed")}),T4.extend({type:g("bead.created")}),C4.extend({type:g("bead.dead_assignee_reopened")}),R4.extend({type:g("bead.deleted")}),N4.extend({type:g("bead.updated")}),P4.extend({type:g("bead.worktree.reap_skipped")}),j4.extend({type:g("bead.worktree.reaped")}),A4.extend({type:g("beads.conditional_writes.degraded")}),O4.extend({type:g("breaker.state_changed")}),$4.extend({type:g("city.created")}),D4.extend({type:g("city.resumed")}),M4.extend({type:g("city.suspended")}),L4.extend({type:g("city.unregister_requested")}),q4.extend({type:g("controller.started")}),F4.extend({type:g("controller.stopped")}),U4.extend({type:g("controller.tick_completed")}),Z4.extend({type:g("convoy.closed")}),V4.extend({type:g("convoy.created")}),G4.extend({type:g("doctor.alert")}),H4.extend({type:g("emergency.acked")}),X4.extend({type:g("emergency.signaled")}),K4.extend({type:g("events.rotated")}),J4.extend({type:g("execution.step_defined")}),Q4.extend({type:g("execution.work_associated")}),Y4.extend({type:g("extmsg.adapter_added")}),e6.extend({type:g("extmsg.adapter_removed")}),t6.extend({type:g("extmsg.bound")}),n6.extend({type:g("extmsg.group_created")}),o6.extend({type:g("extmsg.inbound")}),r6.extend({type:g("extmsg.outbound")}),i6.extend({type:g("extmsg.outbound_channel_mismatch")}),a6.extend({type:g("extmsg.unbound")}),s6.extend({type:g("gc.store.disk_critical")}),l6.extend({type:g("gc.store.disk_warn")}),u6.extend({type:g("gc.store.maintenance.done")}),c6.extend({type:g("gc.store.maintenance.failed")}),d6.extend({type:g("mail.archived")}),p6.extend({type:g("mail.deleted")}),f6.extend({type:g("mail.marked_read")}),m6.extend({type:g("mail.marked_unread")}),v6.extend({type:g("mail.read")}),g6.extend({type:g("mail.replied")}),h6.extend({type:g("mail.sent")}),y6.extend({type:g("molecule.resolved")}),_6.extend({type:g("order.completed")}),x6.extend({type:g("order.failed")}),I6.extend({type:g("order.fired")}),E6.extend({type:g("order.gate_timeout_fail_open")}),w6.extend({type:g("pg.credential_resolved")}),S6.extend({type:g("project.identity.stamped")}),b6.extend({type:g("provider.quota_observed")}),k6.extend({type:g("provider.quota_poll_failed")}),B6.extend({type:g("provider.swapped")}),z6.extend({type:g("proxy.reaped")}),T6.extend({type:g("request.failed")}),C6.extend({type:g("request.result.city.create")}),R6.extend({type:g("request.result.city.unregister")}),N6.extend({type:g("request.result.rig.create")}),P6.extend({type:g("request.result.session.create")}),j6.extend({type:g("request.result.session.message")}),A6.extend({type:g("request.result.session.submit")}),O6.extend({type:g("rig.provision.progress")}),$6.extend({type:g("session.cold_start_timeout")}),D6.extend({type:g("session.crashed")}),M6.extend({type:g("session.drain_acked_with_assigned_work")}),L6.extend({type:g("session.draining")}),q6.extend({type:g("session.idle_killed")}),F6.extend({type:g("session.max_age_killed")}),U6.extend({type:g("session.quarantined")}),Z6.extend({type:g("session.reset_stalled")}),V6.extend({type:g("session.stopped")}),W6.extend({type:g("session.stranded")}),G6.extend({type:g("session.suspended")}),H6.extend({type:g("session.undrained")}),X6.extend({type:g("session.unknown_state")}),K6.extend({type:g("session.updated")}),J6.extend({type:g("session.woke")}),Q6.extend({type:g("session.work_query_failed")}),Y6.extend({type:g("store.degraded")}),eI.extend({type:g("store.probe_failed")}),tI.extend({type:g("store.recovered")}),nI.extend({type:g("supervisor.fs_pressure.skipped_tick")}),oI.extend({type:g("supervisor.request")}),rI.extend({type:g("supervisor.shutdown_requested")}),iI.extend({type:g("supervisor.started")}),aI.extend({type:g("webhook.received")}),sI.extend({type:g("webhook.rejected")}),lI.extend({type:g("worker.operation")}),W4.extend({type:g("TypedEventStreamEnvelopeCustom")})]);c({items:y(ov).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const uI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ru,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.claim_rejected"),workflow:z.optional()}),cI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.closed"),workflow:z.optional()}),dI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.created"),workflow:z.optional()}),pI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Nu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.dead_assignee_reopened"),workflow:z.optional()}),fI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.deleted"),workflow:z.optional()}),mI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.updated"),workflow:z.optional()}),vI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Pu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.worktree.reap_skipped"),workflow:z.optional()}),gI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ju,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.worktree.reaped"),workflow:z.optional()}),hI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Mu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("beads.conditional_writes.degraded"),workflow:z.optional()}),yI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ou,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("breaker.state_changed"),workflow:z.optional()}),_I=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:di,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.created"),workflow:z.optional()}),xI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.resumed"),workflow:z.optional()}),II=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.suspended"),workflow:z.optional()}),EI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:di,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.unregister_requested"),workflow:z.optional()}),wI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.started"),workflow:z.optional()}),SI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.stopped"),workflow:z.optional()}),bI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Lu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.tick_completed"),workflow:z.optional()}),kI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("convoy.closed"),workflow:z.optional()}),BI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("convoy.created"),workflow:z.optional()}),zI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:no(),run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:e(),workflow:z.optional()}),TI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:qu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("doctor.alert"),workflow:z.optional()}),CI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:pi,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("emergency.acked"),workflow:z.optional()}),RI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:pi,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("emergency.signaled"),workflow:z.optional()}),NI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:rc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("events.rotated"),workflow:z.optional()}),PI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.step_defined"),workflow:z.optional()}),jI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.work_associated"),workflow:z.optional()}),AI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ci,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.adapter_added"),workflow:z.optional()}),OI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ci,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.adapter_removed"),workflow:z.optional()}),$I=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Au,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.bound"),workflow:z.optional()}),DI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Fu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.group_created"),workflow:z.optional()}),MI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Uu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.inbound"),workflow:z.optional()}),LI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Gu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.outbound"),workflow:z.optional()}),qI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Wu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.outbound_channel_mismatch"),workflow:z.optional()}),FI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:zc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.unbound"),workflow:z.optional()}),UI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:gc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.disk_critical"),workflow:z.optional()}),ZI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:hc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.disk_warn"),workflow:z.optional()}),VI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:yc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.maintenance.done"),workflow:z.optional()}),WI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:_c,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.maintenance.failed"),workflow:z.optional()}),GI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.archived"),workflow:z.optional()}),HI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.deleted"),workflow:z.optional()}),XI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.marked_read"),workflow:z.optional()}),KI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.marked_unread"),workflow:z.optional()}),JI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.read"),workflow:z.optional()}),QI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.replied"),workflow:z.optional()}),YI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.sent"),workflow:z.optional()}),eE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Zu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("molecule.resolved"),workflow:z.optional()}),tE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.completed"),workflow:z.optional()}),nE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.failed"),workflow:z.optional()}),oE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.fired"),workflow:z.optional()}),rE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Vu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.gate_timeout_fail_open"),workflow:z.optional()}),iE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ku,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("pg.credential_resolved"),workflow:z.optional()}),aE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ju,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("project.identity.stamped"),workflow:z.optional()}),sE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Yu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.quota_observed"),workflow:z.optional()}),lE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ec,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.quota_poll_failed"),workflow:z.optional()}),uE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.swapped"),workflow:z.optional()}),cE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Qu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("proxy.reaped"),workflow:z.optional()}),dE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:tc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.failed"),workflow:z.optional()}),pE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:$u,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.city.create"),workflow:z.optional()}),fE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Du,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.city.unregister"),workflow:z.optional()}),mE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:nc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.rig.create"),workflow:z.optional()}),vE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ec,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.create"),workflow:z.optional()}),gE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:lc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.message"),workflow:z.optional()}),hE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.submit"),workflow:z.optional()}),yE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:oc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("rig.provision.progress"),workflow:z.optional()}),_E=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.cold_start_timeout"),workflow:z.optional()}),xE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.crashed"),workflow:z.optional()}),IE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:sc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.drain_acked_with_assigned_work"),workflow:z.optional()}),EE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.draining"),workflow:z.optional()}),wE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.idle_killed"),workflow:z.optional()}),SE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.max_age_killed"),workflow:z.optional()}),bE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.quarantined"),workflow:z.optional()}),kE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:uc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.reset_stalled"),workflow:z.optional()}),BE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.stopped"),workflow:z.optional()}),zE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:cc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.stranded"),workflow:z.optional()}),TE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.suspended"),workflow:z.optional()}),CE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.undrained"),workflow:z.optional()}),RE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:mc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.unknown_state"),workflow:z.optional()}),NE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.updated"),workflow:z.optional()}),PE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fe,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.woke"),workflow:z.optional()}),jE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.work_query_failed"),workflow:z.optional()}),AE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:vc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.degraded"),workflow:z.optional()}),OE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:xc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.probe_failed"),workflow:z.optional()}),$E=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ic,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.recovered"),workflow:z.optional()}),DE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:wc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.fs_pressure.skipped_tick"),workflow:z.optional()}),ME=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Sc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.request"),workflow:z.optional()}),LE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.shutdown_requested"),workflow:z.optional()}),qE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:kc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.started"),workflow:z.optional()}),FE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Tc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("webhook.received"),workflow:z.optional()}),UE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("webhook.rejected"),workflow:z.optional()}),ZE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Rc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("worker.operation"),workflow:z.optional()}),rv=pr("type",[uI.extend({type:g("bead.claim_rejected")}),cI.extend({type:g("bead.closed")}),dI.extend({type:g("bead.created")}),pI.extend({type:g("bead.dead_assignee_reopened")}),fI.extend({type:g("bead.deleted")}),mI.extend({type:g("bead.updated")}),vI.extend({type:g("bead.worktree.reap_skipped")}),gI.extend({type:g("bead.worktree.reaped")}),hI.extend({type:g("beads.conditional_writes.degraded")}),yI.extend({type:g("breaker.state_changed")}),_I.extend({type:g("city.created")}),xI.extend({type:g("city.resumed")}),II.extend({type:g("city.suspended")}),EI.extend({type:g("city.unregister_requested")}),wI.extend({type:g("controller.started")}),SI.extend({type:g("controller.stopped")}),bI.extend({type:g("controller.tick_completed")}),kI.extend({type:g("convoy.closed")}),BI.extend({type:g("convoy.created")}),TI.extend({type:g("doctor.alert")}),CI.extend({type:g("emergency.acked")}),RI.extend({type:g("emergency.signaled")}),NI.extend({type:g("events.rotated")}),PI.extend({type:g("execution.step_defined")}),jI.extend({type:g("execution.work_associated")}),AI.extend({type:g("extmsg.adapter_added")}),OI.extend({type:g("extmsg.adapter_removed")}),$I.extend({type:g("extmsg.bound")}),DI.extend({type:g("extmsg.group_created")}),MI.extend({type:g("extmsg.inbound")}),LI.extend({type:g("extmsg.outbound")}),qI.extend({type:g("extmsg.outbound_channel_mismatch")}),FI.extend({type:g("extmsg.unbound")}),UI.extend({type:g("gc.store.disk_critical")}),ZI.extend({type:g("gc.store.disk_warn")}),VI.extend({type:g("gc.store.maintenance.done")}),WI.extend({type:g("gc.store.maintenance.failed")}),GI.extend({type:g("mail.archived")}),HI.extend({type:g("mail.deleted")}),XI.extend({type:g("mail.marked_read")}),KI.extend({type:g("mail.marked_unread")}),JI.extend({type:g("mail.read")}),QI.extend({type:g("mail.replied")}),YI.extend({type:g("mail.sent")}),eE.extend({type:g("molecule.resolved")}),tE.extend({type:g("order.completed")}),nE.extend({type:g("order.failed")}),oE.extend({type:g("order.fired")}),rE.extend({type:g("order.gate_timeout_fail_open")}),iE.extend({type:g("pg.credential_resolved")}),aE.extend({type:g("project.identity.stamped")}),sE.extend({type:g("provider.quota_observed")}),lE.extend({type:g("provider.quota_poll_failed")}),uE.extend({type:g("provider.swapped")}),cE.extend({type:g("proxy.reaped")}),dE.extend({type:g("request.failed")}),pE.extend({type:g("request.result.city.create")}),fE.extend({type:g("request.result.city.unregister")}),mE.extend({type:g("request.result.rig.create")}),vE.extend({type:g("request.result.session.create")}),gE.extend({type:g("request.result.session.message")}),hE.extend({type:g("request.result.session.submit")}),yE.extend({type:g("rig.provision.progress")}),_E.extend({type:g("session.cold_start_timeout")}),xE.extend({type:g("session.crashed")}),IE.extend({type:g("session.drain_acked_with_assigned_work")}),EE.extend({type:g("session.draining")}),wE.extend({type:g("session.idle_killed")}),SE.extend({type:g("session.max_age_killed")}),bE.extend({type:g("session.quarantined")}),kE.extend({type:g("session.reset_stalled")}),BE.extend({type:g("session.stopped")}),zE.extend({type:g("session.stranded")}),TE.extend({type:g("session.suspended")}),CE.extend({type:g("session.undrained")}),RE.extend({type:g("session.unknown_state")}),NE.extend({type:g("session.updated")}),PE.extend({type:g("session.woke")}),jE.extend({type:g("session.work_query_failed")}),AE.extend({type:g("store.degraded")}),OE.extend({type:g("store.probe_failed")}),$E.extend({type:g("store.recovered")}),DE.extend({type:g("supervisor.fs_pressure.skipped_tick")}),ME.extend({type:g("supervisor.request")}),LE.extend({type:g("supervisor.shutdown_requested")}),qE.extend({type:g("supervisor.started")}),FE.extend({type:g("webhook.received")}),UE.extend({type:g("webhook.rejected")}),ZE.extend({type:g("worker.operation")}),zI.extend({type:g("TypedTaggedEventStreamEnvelopeCustom")})]);c({event_cursor:e(),items:y(rv).nullable(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({beads:y(nv).nullable(),deps:y(pu).nullable(),logical_edges:y(pu).nullable(),logical_nodes:y(C5).nullable(),partial:R(),resolved_root_store:e(),root_bead_id:e(),root_store_ref:e(),scope_groups:y(ex).nullable(),scope_kind:e(),scope_ref:e(),snapshot_event_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),snapshot_version:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),stores_scanned:y(e()).nullable(),workflow_id:e()});const VE=c({declared_name:e().optional(),declared_prefix:e().optional(),max_active_sessions:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),name:e(),prefix:e().optional(),provider:e().optional(),session_template:e().optional(),suspended:R()});c({agents:y(d5).nullable(),effective_api_url:e().optional(),patches:f5.optional(),providers:pe(e(),U5).optional(),rigs:y(m5).nullable(),workspace:VE});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),base:e()});c({cityName:e().min(1).regex(/\S/),base:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),base:e()});c({cityName:e().min(1).regex(/\S/),base:e()});c({tail:e().optional(),before:e().optional()});c({cityName:e().min(1).regex(/\S/),base:e()});y(un([c({data:fr,event:g("heartbeat"),id:Ue().optional(),retry:Ue().optional()}),c({data:M7,event:g("turn"),id:Ue().optional(),retry:Ue().optional()})]));c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),base:e(),action:me(["suspend","resume"])});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({tail:e().optional(),before:e().optional()});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});y(un([c({data:fr,event:g("heartbeat"),id:Ue().optional(),retry:Ue().optional()}),c({data:M7,event:g("turn"),id:Ue().optional(),retry:Ue().optional()})]));c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e(),action:me(["suspend","resume"])});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),pool:e().optional(),rig:e().optional(),running:me(["true","false"]).optional(),peek:R().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});pe(e(),e());c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100)),status:e().optional(),type:e().optional(),label:e().optional(),assignee:e().optional(),rig:e().optional(),all:R().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),rootID:e()});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100))});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100)),type:e().optional(),actor:e().optional(),since:e().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({wait:R().optional()});c({"Last-Event-ID":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({after_seq:e().optional()});y(un([c({data:ov,event:g("event"),id:Ue().optional(),retry:Ue().optional()}),c({data:fr,event:g("heartbeat"),id:Ue().optional(),retry:Ue().optional()})]));c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({session_id:e().optional()});c({cityName:e().min(1).regex(/\S/)});c({scope_id:e().optional(),provider:e().optional(),account_id:e().optional(),conversation_id:e().optional(),kind:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({scope_id:e().optional(),provider:e().optional(),account_id:e().optional(),conversation_id:e().optional(),parent_conversation_id:e().optional(),kind:e().optional(),after_sequence:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),limit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),order:me(["asc","desc"]).optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),name:e()});c({scope_kind:e().optional(),scope_ref:e().optional(),target:e()});c({cityName:e().min(1).regex(/\S/)});c({scope_kind:e().optional(),scope_ref:e().optional()});c({cityName:e().min(1).regex(/\S/)});c({scope_kind:e().optional(),scope_ref:e().optional(),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),name:e()});c({scope_kind:e().optional(),scope_ref:e().optional(),target:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({scope_kind:e().optional(),scope_ref:e().optional(),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100)),agent:e().optional(),status:e().optional(),rig:e().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({agent:e().optional(),rig:e().optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({wait:R().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),bead_id:e()});c({store_ref:e().optional()});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({fresh:R().optional()});c({cityName:e().min(1).regex(/\S/)});c({scope_kind:e().optional(),scope_ref:e().optional(),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({cityName:e().min(1).regex(/\S/)});c({scoped_name:e().min(1),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),before:e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),base:e()});c({cityName:e().min(1).regex(/\S/),base:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({providers:e().optional(),fresh:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({items:e().optional(),fresh:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e()});c({git:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e(),action:me(["suspend","resume","restart"])});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),git:R().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),run_id:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),run_id:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),run_id:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),id:e()});c({peek:R().optional(),peek_lines:h().gte(BigInt(0)).lte(BigInt(1e4)).optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e(),agentId:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({delete:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"Last-Event-ID":e().max(2048).optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({format:me(["conversation","raw","structured"]).optional(),include_thinking:R().optional(),after_cursor:e().max(2048).optional()});y(un([c({data:q7,event:g("activity"),id:e().optional(),retry:Ue().optional()}),c({data:fr,event:g("heartbeat"),id:e().optional(),retry:Ue().optional()}),c({data:rx,event:g("message").optional(),id:e().optional(),retry:Ue().optional()}),c({data:Xu,event:g("pending"),id:e().optional(),retry:Ue().optional()}),c({data:F7,event:g("pending_cleared"),id:e().optional(),retry:Ue().optional()}),c({data:Y7,event:g("structured"),id:e().optional(),retry:Ue().optional()}),c({data:ox,event:g("turn"),id:e().optional(),retry:Ue().optional()})]));c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({tail:e().optional(),format:me(["conversation","raw","structured"]).optional(),include_thinking:R().optional(),before:e().optional(),after:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/)});c({cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100)),state:e().optional(),template:e().optional(),peek:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),lite:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e()});c({cityName:e().min(1).regex(/\S/)});c({aggregate_only:R().optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/)});c({state:e().optional(),session:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),workflow_id:e()});c({scope_kind:e().optional(),scope_ref:e().optional(),delete:R().optional()});c({cityName:e().min(1).regex(/\S/),workflow_id:e()});c({scope_kind:e().optional(),scope_ref:e().optional()});c({type:e().optional(),actor:e().optional(),since:e().optional(),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({"Last-Event-ID":e().optional()});c({after_cursor:e().optional()});y(un([c({data:fr,event:g("heartbeat"),id:e().optional(),retry:Ue().optional()}),c({data:rv,event:g("tagged_event"),id:e().optional(),retry:Ue().optional()})]));c({providers:e().optional(),fresh:R().optional()});c({items:e().optional(),fresh:R().optional()});const WE="session.structured.v1";function ln(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function GE(t){if(!ln(t)||t.format!=="structured"||t.schema_version!==WE||typeof t.id!="string"||typeof t.template!="string"||typeof t.provider!="string"||!Array.isArray(t.structured_messages)||!t.structured_messages.every(iv)||!Y7.safeParse(t).success||!XE(t.history))return!1;switch(t.operation){case"snapshot":case"upsert":return t.reset_reason===void 0;case"reset":return HE(t.reset_reason);default:return!1}}function HE(t){return t==="resume_invalid"||t==="stream_changed"||t==="cursor_invalidated"||t==="history_rewritten"}function w9(t){return ln(t)&&typeof t.activity=="string"}function S9(t){return ln(t)&&typeof t.timestamp=="string"}function XE(t){if(!ln(t)||typeof t.transcript_stream_id!="string")return!1;const r=t.generation;if(!ln(r)||typeof r.id!="string")return!1;const i=t.cursor;if(!ln(i)||typeof i.resume_token!="string"||i.resume_token==="")return!1;const s=t.continuity;if(!ln(s)||typeof s.status!="string")return!1;const u=t.tail_state;return!(!ln(u)||typeof u.activity!="string")}function iv(t){return ln(t)&&typeof t.id=="string"&&KE(t.role)&&typeof t.status=="string"&&Array.isArray(t.blocks)&&t.blocks.every(JE)}function KE(t){return t==="unknown"||t==="user"||t==="assistant"||t==="system"||t==="tool"}function JE(t){return ln(t)?t.type==="text"||t.type==="thinking"||t.type==="tool_use"||t.type==="tool_result"||t.type==="interaction"||t.type==="image"||t.type==="unknown":!1}function b9(t){return Array.isArray(t.structured_messages)?t.structured_messages.filter(iv):[]}function hm(t,r){const i=t??1;return r===void 0||r===1?String(i):`${i},${r}`}function QE(t){const r=t.old_start,i=t.new_start;return r===void 0&&i===void 0?"@@":`@@ -${hm(r,t.old_lines)} +${hm(i,t.new_lines)} @@`}function k9(t){if(t==null||t.length===0)return"";const r=[];let i="";for(const s of t){const u=s.file_path??"";if(u!==""&&u!==i&&(r.push(`*** Update File: ${u}`),i=u),r.push(QE(s)),s.lines!==void 0&&s.lines!==null)for(const f of s.lines)r.push(f)}return r.join(` -`)}function ei(t,r,i){i!==void 0&&i!==0&&t.push(`${r} ${i}`)}function B9(t){if(t===void 0)return"";const r=[];ei(r,"in",t.input_tokens),ei(r,"out",t.output_tokens),ei(r,"reason",t.reasoning_tokens),ei(r,"cache",t.cache_read_tokens),ei(r,"write",t.cache_creation_tokens);const i=t.context_used_tokens,s=t.context_window_tokens;i!==void 0&&s!==void 0&&r.push(`${i}/${s}`);const u=t.context_percent;return u!==void 0&&r.push(`${u}%`),r.length>0?`tokens ${r.join(" ")}`:""}const YE="modulepreload",ew=function(t){return"/"+t},ym={},Rn=function(r,i,s){let u=Promise.resolve();if(i&&i.length>0){let x=function(I){return Promise.all(I.map(w=>Promise.resolve(w).then(b=>({status:"fulfilled",value:b}),b=>({status:"rejected",reason:b}))))};document.getElementsByTagName("link");const p=document.querySelector("meta[property=csp-nonce]"),v=p?.nonce||p?.getAttribute("nonce");u=x(i.map(I=>{if(I=ew(I),I in ym)return;ym[I]=!0;const w=I.endsWith(".css"),b=w?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${I}"]${b}`))return;const C=document.createElement("link");if(C.rel=w?"stylesheet":YE,w||(C.as="script"),C.crossOrigin="",C.href=I,v&&C.setAttribute("nonce",v),document.head.appendChild(C),w)return new Promise((O,L)=>{C.addEventListener("load",O),C.addEventListener("error",()=>L(new Error(`Unable to preload CSS for ${I}`)))})}))}function f(p){const v=new Event("vite:preloadError",{cancelable:!0});if(v.payload=p,window.dispatchEvent(v),!v.defaultPrevented)throw p}return u.then(p=>{for(const v of p||[])v.status==="rejected"&&f(v.reason);return r().catch(f)})};let li=null;function tw(t){if(!Jm.test(t))throw new Error(`invalid city name: ${t}`);li=t}function Xa(){return li}function pn(t){const r=li;if(r===null)throw new Error(`${t} called before an active city was resolved`);return r}function _o(t){if(li===null)throw new Error(`cityPath("${t}") called before an active city was resolved`);return`/api/city/${encodeURIComponent(li)}${t}`}async function nw(t,r,i,s){const p=await fetch(r,{method:t,headers:{Accept:"application/json"},credentials:"same-origin"});if(!p.ok){const x=await p.text(),I=ow(x),w=I?.error??(x.trim()||p.statusText||`HTTP ${p.status}`);throw new av(p.status,w,I?.kind,I?.reason)}let v;try{v=await p.json()}catch(x){throw new sv(r,`body must be valid JSON: ${iw(x)}`)}return i(v,r)}function ow(t){if(t.trim().length!==0)try{const r=JSON.parse(t);return rw(r)?r:void 0}catch{return}}function rw(t){if(typeof t!="object"||t===null)return!1;const r=t;return typeof r.error!="string"||r.kind!==void 0&&typeof r.kind!="string"?!1:r.reason===void 0||typeof r.reason=="string"}async function Xt(t,r,i,s){return nw(t,r,i)}class av extends Error{constructor(r,i,s,u){super(i),this.status=r,this.kind=s,this.reason=u,this.name="ApiClientError"}status;kind;reason}class sv extends Error{constructor(r,i){super(`Invalid API response for ${r}: ${i}`),this.url=r,this.detail=i,this.name="ApiResponseDecodeError"}url;detail}function iw(t){return t instanceof Error?t.message:typeof t=="string"?t:"unknown error"}function dn(t,r){throw new sv(t,r)}function aw(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function wn(t,r,i){return aw(t)||dn(r,`${i} must be an object`),t}function bt(t,r,i,s){typeof t[s]!="string"&&dn(r,`${i}.${s} must be a string`)}function lv(t,r,i,s){const u=t[s];u!==null&&typeof u!="string"&&dn(r,`${i}.${s} must be a string or null`)}function Io(t,r,i,s){typeof t[s]!="boolean"&&dn(r,`${i}.${s} must be a boolean`)}function Jt(t,r,i,s){typeof t[s]!="number"&&dn(r,`${i}.${s} must be a number`)}function Qt(t,r,i,s){Array.isArray(t[s])||dn(r,`${i}.${s} must be an array`)}function sn(t,r,i,s){wn(t[s],r,`${i}.${s}`)}function sw(t,r,i,s){const u=t[s];u!==null&&(!Array.isArray(u)||u.some(f=>typeof f!="string"))&&dn(r,`${i}.${s} must be an array of strings or null`)}function fn(t,r){return(i,s)=>{const u=wn(i,s,t);return r?.(u,s),u}}function uv(t,r){return fn(t,(i,s)=>{Qt(i,s,t,"items"),r?.(i,s)})}const lw=fn("health",(t,r)=>{Io(t,r,"health","ok"),bt(t,r,"health","ts")}),uw=uv("commits",(t,r)=>{bt(t,r,"commits","view")}),cw=uv("builds",(t,r)=>{lv(t,r,"builds","source"),Io(t,r,"builds","failed_marker")}),dw=fn("config",(t,r)=>{bt(t,r,"config","cityName"),bt(t,r,"config","cityRoot"),Io(t,r,"config","useFixtures"),Io(t,r,"config","readOnly"),bt(t,r,"config","operatorAlias"),bt(t,r,"config","operatorWireAlias"),bt(t,r,"config","decisionLabel"),sw(t,r,"config","enabledModules"),lv(t,r,"config","defaultView")}),pw=new Set(["sample_failed","invalid_sample","value_overflow"]);function Ta(t,r,i,s,u){const f=wn(t[s],r,`${i}.${s}`);if(bt(f,r,`${i}.${s}`,"status"),f.status==="available"){u(f.value,r,`${i}.${s}.value`);return}f.status!=="unavailable"&&dn(r,`${i}.${s}.status must be available or unavailable`),bt(f,r,`${i}.${s}`,"reason"),pw.has(f.reason)||dn(r,`${i}.${s}.reason is not recognized`)}function _m(t,r,i){typeof t!="number"&&dn(r,`${i} must be a number`)}const fw=fn("system health",(t,r)=>{const i=wn(t.admin,r,"system health.admin"),s=wn(t.host,r,"system health.host");Jt(i,r,"system health.admin","pid"),Jt(i,r,"system health.admin","uptime_sec"),Jt(i,r,"system health.admin","heap_used_bytes"),bt(i,r,"system health.admin","node_version"),Ta(i,r,"system health.admin","rss",_m),Jt(s,r,"system health.host","cpu_count"),Ta(s,r,"system health.host","uptime",_m),Ta(s,r,"system health.host","load",(u,f,p)=>{const v=wn(u,f,p);Jt(v,f,p,"load_avg_1"),Jt(v,f,p,"load_avg_5"),Jt(v,f,p,"load_avg_15")}),Ta(s,r,"system health.host","memory",(u,f,p)=>{const v=wn(u,f,p);Jt(v,f,p,"total_mem_bytes"),Jt(v,f,p,"free_mem_bytes")})});function Ql(t,r,i,s){sn(t,r,i,s);const u=t[s],f=`${i}.${s}`;bt(u,r,f,"status")}const mw=fn("local tool versions",(t,r)=>{Ql(t,r,"local tool versions","dolt"),Ql(t,r,"local tool versions","beads"),Ql(t,r,"local tool versions","gc")}),vw=fn("dolt trend",(t,r)=>{Io(t,r,"dolt trend","available"),Qt(t,r,"dolt trend","samples")}),gw=fn("rig store health",(t,r)=>{Io(t,r,"rig store health","available"),Qt(t,r,"rig store health","rigs")});function xm(t,r){const i=wn(t,r,"supervisor status.status");sn(i,r,"supervisor status.status","work")}const hw=fn("supervisor status",(t,r)=>{Io(t,r,"supervisor status","available"),t.available===!0?(bt(t,r,"supervisor status","sampledAt"),xm(t.status,r)):(bt(t,r,"supervisor status","reason"),t.status!==null&&xm(t.status,r))}),yw=fn("run summary",(t,r)=>{Jt(t,r,"run summary","totalActive"),Jt(t,r,"run summary","totalHistorical"),Qt(t,r,"run summary","lanes"),Qt(t,r,"run summary","historicalLanes"),Qt(t,r,"run summary","blockedLanes"),Qt(t,r,"run summary","recentChanges"),sn(t,r,"run summary","runCounts"),sn(t,r,"run summary","census")}),_w=fn("formula run detail",(t,r)=>{bt(t,r,"formula run detail","runId"),sn(t,r,"formula run detail","formula"),sn(t,r,"formula run detail","formulaDetail"),sn(t,r,"formula run detail","executionPath"),sn(t,r,"formula run detail","snapshotEventSeq"),sn(t,r,"formula run detail","completeness");const i=wn(t.progress,r,"formula run detail.progress");sn(i,r,"formula run detail.progress","statusCounts"),Qt(t,r,"formula run detail","stages"),Qt(t,r,"formula run detail","nodes"),Qt(t,r,"formula run detail","edges"),Qt(t,r,"formula run detail","lanes")});function xw(t,r="request failed"){if(t instanceof av){const i={message:t.message,status:t.status};return t.kind!==void 0&&(i.kind=t.kind),i}return t instanceof Error?{message:t.message}:{message:r}}function Lt(t,r="request failed"){const i=xw(t,r);return i.status===void 0?i.message:`${i.status} ${i.message}`}const lr={health(){return Xt("GET","/api/health",lw)},listCommits(t){return Xt("GET",`/api/git/commits?view=${encodeURIComponent(t)}`,uw)},listBuilds(){return Xt("GET","/api/builds",cw)},config(){return Xt("GET",_o("/config"),dw)},systemHealth(){return Xt("GET","/api/health/system",fw)},localToolVersions(){return Xt("GET","/api/health/local-tools",mw)},doltTrend(){return Xt("GET",_o("/dolt-noms/trend"),vw)},rigStoreHealth(){return Xt("GET",_o("/rig-store-health"),gw)},supervisorStatus(){return Xt("GET",_o("/supervisor-status"),hw)},runSummary(){return Xt("GET",_o("/runs/summary"),yw)},runDetail(t){return Xt("GET",_o(`/runs/${encodeURIComponent(t)}/detail`),_w)},runDetailStreamUrl(t){return _o(`/runs/${encodeURIComponent(t)}/detail/stream`)}},mi=["agents","beads","runs","mail","activity","health"],Iw=5,Ew=new Map(mi.map((t,r)=>[t,r]));function fu(t,r={}){const i=ww(),s=[];let u=0;for(const I of t)for(const w of I.getItems()){s.push({item:w,index:u});const b=i[w.domain],C=[...b.items,w];i[w.domain]={domain:w.domain,attention:b.attention+(w.severity==="attention"?1:0),watch:b.watch+(w.severity==="watch"?1:0),unavailable:b.unavailable+(w.severity==="unavailable"?1:0),severity:w.severity==="unavailable"?b.severity:Sw(b.severity,w.severity),items:C},u+=1}const f=s.sort((I,w)=>bw(I.item,w.item)||I.index-w.index).map(({item:I})=>I),p=r.topLimit??Iw,v=f.slice(0,p),x=kw(f.slice(p));return{items:f,topItems:v,overflowByDomain:x,byDomain:i}}function ww(){const t={};for(const r of mi)t[r]={domain:r,attention:0,watch:0,unavailable:0,severity:null,items:[]};return t}function Sw(t,r){return t==="attention"||r==="attention"?"attention":"watch"}function bw(t,r){return Im(t.severity)-Im(r.severity)||Ca(r.current??!0)-Ca(t.current??!0)||Ca(r.actionable??!1)-Ca(t.actionable??!1)||Em(r.updatedAt)-Em(t.updatedAt)||wm(t.domain)-wm(r.domain)}function Im(t){switch(t){case"attention":return 0;case"watch":return 1;case"unavailable":return 2}}function Ca(t){return t?1:0}function Em(t){if(t===void 0)return 0;const r=Date.parse(t);return Number.isFinite(r)?r:0}function wm(t){return Ew.get(t)??mi.length}function kw(t){const r=[];for(const i of mi){let s=0,u=0,f=0;for(const v of t)v.domain===i&&(v.severity==="attention"?s+=1:v.severity==="watch"?u+=1:f+=1);const p=s+u+f;p>0&&r.push({domain:i,attention:s,watch:u,unavailable:f,total:p})}return r}const Bw=fu([]),cv=T.createContext(Bw);function zw({contributors:t,topLimit:r,children:i}){const s=T.useMemo(()=>r===void 0?fu(t):fu(t,{topLimit:r}),[t,r]);return M.jsx(cv.Provider,{value:s,children:i})}function Tw(){return T.useContext(cv)}const Nc=new Map;function Yl(t){return Nc.get(t)?.value}function Ra(t){return Nc.get(t)?.fetchedAt}function Cw(t,r){Nc.set(t,{value:r,fetchedAt:new Date().toISOString()})}function En(t,r,i){const s=T.useRef(r);s.current=r;const u=T.useRef(i?.refreshFetcher);u.current=i?.refreshFetcher;const f=T.useRef(i?.sseRefreshFetcher);f.current=i?.sseRefreshFetcher;const p=T.useRef(i?.onError);p.current=i?.onError;const v=T.useRef(t);v.current=t;const x=T.useRef(0),I=T.useRef(null),[w,b]=T.useState(()=>Yl(t)),[C,O]=T.useState(()=>Yl(t)===void 0),[L,W]=T.useState(null),[D,G]=T.useState(()=>Ra(t)),ee=T.useCallback(async te=>{const ue=x.current+1;x.current=ue,I.current?.abort();const ve=new AbortController;I.current=ve;const de=t;O(!0),W(null);try{const we=await te(ve.signal),Se=x.current===ue,Ne=v.current===de;Se&&Ne?(Cw(de,we),b(we),G(Ra(de))):Ne&&(b(Ae=>Ae===void 0?we:Ae),G(Ae=>Ae??Ra(de)??new Date().toISOString()))}catch(we){x.current===ue&&(W(we instanceof Error?we.message:"failed to load"),p.current?.(we))}finally{I.current===ve&&(I.current=null),x.current===ue&&O(!1)}},[t]),J=T.useCallback(()=>ee(u.current??s.current),[ee]),H=T.useCallback(()=>ee(f.current??u.current??s.current),[ee]);return T.useEffect(()=>{const te=Yl(t);return b(te),O(te===void 0),G(Ra(t)),ee(s.current),()=>{x.current+=1,I.current?.abort(),I.current=null}},[t,ee]),{data:w,loading:C,error:L,fetchedAt:D,refresh:J,cheapRefresh:H}}var Rw=async(t,r)=>{let i=typeof r=="function"?await r(t):r;if(i)return t.scheme==="bearer"?`Bearer ${i}`:t.scheme==="basic"?`Basic ${btoa(i)}`:i},Nw={bodySerializer:t=>JSON.stringify(t,(r,i)=>typeof i=="bigint"?i.toString():i)},Pw=t=>{switch(t){case"label":return".";case"matrix":return";";case"simple":return",";default:return"&"}},jw=t=>{switch(t){case"form":return",";case"pipeDelimited":return"|";case"spaceDelimited":return"%20";default:return","}},Aw=t=>{switch(t){case"label":return".";case"matrix":return";";case"simple":return",";default:return"&"}},dv=({allowReserved:t,explode:r,name:i,style:s,value:u})=>{if(!r){let v=(t?u:u.map(x=>encodeURIComponent(x))).join(jw(s));switch(s){case"label":return`.${v}`;case"matrix":return`;${i}=${v}`;case"simple":return v;default:return`${i}=${v}`}}let f=Pw(s),p=u.map(v=>s==="label"||s==="simple"?t?v:encodeURIComponent(v):Ka({allowReserved:t,name:i,value:v})).join(f);return s==="label"||s==="matrix"?f+p:p},Ka=({allowReserved:t,name:r,value:i})=>{if(i==null)return"";if(typeof i=="object")throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");return`${r}=${t?i:encodeURIComponent(i)}`},pv=({allowReserved:t,explode:r,name:i,style:s,value:u,valueOnly:f})=>{if(u instanceof Date)return f?u.toISOString():`${i}=${u.toISOString()}`;if(s!=="deepObject"&&!r){let x=[];Object.entries(u).forEach(([w,b])=>{x=[...x,w,t?b:encodeURIComponent(b)]});let I=x.join(",");switch(s){case"form":return`${i}=${I}`;case"label":return`.${I}`;case"matrix":return`;${i}=${I}`;default:return I}}let p=Aw(s),v=Object.entries(u).map(([x,I])=>Ka({allowReserved:t,name:s==="deepObject"?`${i}[${x}]`:x,value:I})).join(p);return s==="label"||s==="matrix"?p+v:v},Ow=/\{[^{}]+\}/g,$w=({path:t,url:r})=>{let i=r,s=r.match(Ow);if(s)for(let u of s){let f=!1,p=u.substring(1,u.length-1),v="simple";p.endsWith("*")&&(f=!0,p=p.substring(0,p.length-1)),p.startsWith(".")?(p=p.substring(1),v="label"):p.startsWith(";")&&(p=p.substring(1),v="matrix");let x=t[p];if(x==null)continue;if(Array.isArray(x)){i=i.replace(u,dv({explode:f,name:p,style:v,value:x}));continue}if(typeof x=="object"){i=i.replace(u,pv({explode:f,name:p,style:v,value:x,valueOnly:!0}));continue}if(v==="matrix"){i=i.replace(u,`;${Ka({name:p,value:x})}`);continue}let I=encodeURIComponent(v==="label"?`.${x}`:x);i=i.replace(u,I)}return i},fv=({allowReserved:t,array:r,object:i}={})=>s=>{let u=[];if(s&&typeof s=="object")for(let f in s){let p=s[f];if(p!=null)if(Array.isArray(p)){let v=dv({allowReserved:t,explode:!0,name:f,style:"form",value:p,...r});v&&u.push(v)}else if(typeof p=="object"){let v=pv({allowReserved:t,explode:!0,name:f,style:"deepObject",value:p,...i});v&&u.push(v)}else{let v=Ka({allowReserved:t,name:f,value:p});v&&u.push(v)}}return u.join("&")},Dw=t=>{if(!t)return"stream";let r=t.split(";")[0]?.trim();if(r){if(r.startsWith("application/json")||r.endsWith("+json"))return"json";if(r==="multipart/form-data")return"formData";if(["application/","audio/","image/","video/"].some(i=>r.startsWith(i)))return"blob";if(r.startsWith("text/"))return"text"}},Mw=async({security:t,...r})=>{for(let i of t){let s=await Rw(i,r.auth);if(!s)continue;let u=i.name??"Authorization";switch(i.in){case"query":r.query||(r.query={}),r.query[u]=s;break;case"cookie":r.headers.append("Cookie",`${u}=${s}`);break;default:r.headers.set(u,s);break}return}},Sm=t=>Lw({baseUrl:t.baseUrl,path:t.path,query:t.query,querySerializer:typeof t.querySerializer=="function"?t.querySerializer:fv(t.querySerializer),url:t.url}),Lw=({baseUrl:t,path:r,query:i,querySerializer:s,url:u})=>{let f=u.startsWith("/")?u:`/${u}`,p=(t??"")+f;r&&(p=$w({path:r,url:p}));let v=i?s(i):"";return v.startsWith("?")&&(v=v.substring(1)),v&&(p+=`?${v}`),p},bm=(t,r)=>{let i={...t,...r};return i.baseUrl?.endsWith("/")&&(i.baseUrl=i.baseUrl.substring(0,i.baseUrl.length-1)),i.headers=mv(t.headers,r.headers),i},mv=(...t)=>{let r=new Headers;for(let i of t){if(!i||typeof i!="object")continue;let s=i instanceof Headers?i.entries():Object.entries(i);for(let[u,f]of s)if(f===null)r.delete(u);else if(Array.isArray(f))for(let p of f)r.append(u,p);else f!==void 0&&r.set(u,typeof f=="object"?JSON.stringify(f):f)}return r},eu=class{_fns;constructor(){this._fns=[]}clear(){this._fns=[]}getInterceptorIndex(t){return typeof t=="number"?this._fns[t]?t:-1:this._fns.indexOf(t)}exists(t){let r=this.getInterceptorIndex(t);return!!this._fns[r]}eject(t){let r=this.getInterceptorIndex(t);this._fns[r]&&(this._fns[r]=null)}update(t,r){let i=this.getInterceptorIndex(t);return this._fns[i]?(this._fns[i]=r,t):!1}use(t){return this._fns=[...this._fns,t],this._fns.length-1}},qw=()=>({error:new eu,request:new eu,response:new eu}),Fw=fv({allowReserved:!1,array:{explode:!0,style:"form"},object:{explode:!0,style:"deepObject"}}),Uw={"Content-Type":"application/json"},vv=(t={})=>({...Nw,headers:Uw,parseAs:"auto",querySerializer:Fw,...t}),gv=(t={})=>{let r=bm(vv(),t),i=()=>({...r}),s=p=>(r=bm(r,p),i()),u=qw(),f=async p=>{let v={...r,...p,fetch:p.fetch??r.fetch??globalThis.fetch,headers:mv(r.headers,p.headers)};v.security&&await Mw({...v,security:v.security}),v.body&&v.bodySerializer&&(v.body=v.bodySerializer(v.body)),(v.body===void 0||v.body==="")&&v.headers.delete("Content-Type");let x=Sm(v),I={redirect:"follow",...v},w=new Request(x,I);for(let D of u.request._fns)D&&(w=await D(w,v));let b=v.fetch,C=await b(w);for(let D of u.response._fns)D&&(C=await D(C,w,v));let O={request:w,response:C};if(C.ok){if(C.status===204||C.headers.get("Content-Length")==="0")return v.responseStyle==="data"?{}:{data:{},...O};let D=(v.parseAs==="auto"?Dw(C.headers.get("Content-Type")):v.parseAs)??"json";if(D==="stream")return v.responseStyle==="data"?C.body:{data:C.body,...O};let G=await C[D]();return D==="json"&&(v.responseValidator&&await v.responseValidator(G),v.responseTransformer&&(G=await v.responseTransformer(G))),v.responseStyle==="data"?G:{data:G,...O}}let L=await C.text();try{L=JSON.parse(L)}catch{}let W=L;for(let D of u.error._fns)D&&(W=await D(L,C,w,v));if(W=W||{},v.throwOnError)throw W;return v.responseStyle==="data"?void 0:{error:W,...O}};return{buildUrl:Sm,connect:p=>f({...p,method:"CONNECT"}),delete:p=>f({...p,method:"DELETE"}),get:p=>f({...p,method:"GET"}),getConfig:i,head:p=>f({...p,method:"HEAD"}),interceptors:u,options:p=>f({...p,method:"OPTIONS"}),patch:p=>f({...p,method:"PATCH"}),post:p=>f({...p,method:"POST"}),put:p=>f({...p,method:"PUT"}),request:f,setConfig:s,trace:p=>f({...p,method:"TRACE"})}};const Te=gv(vv()),Zw=t=>(t?.client??Te).get({url:"/health",...t}),Vw=t=>(t?.client??Te).get({url:"/v0/cities",...t}),Ww=t=>(t.client??Te).get({url:"/v0/city/{cityName}/agents",...t}),Gw=t=>(t.client??Te).get({url:"/v0/city/{cityName}/bead/{id}",...t}),Hw=t=>(t.client??Te).patch({url:"/v0/city/{cityName}/bead/{id}",...t,headers:{"Content-Type":"application/json",...t.headers}}),Xw=t=>(t.client??Te).post({url:"/v0/city/{cityName}/bead/{id}/close",...t}),Kw=t=>(t.client??Te).get({url:"/v0/city/{cityName}/beads",...t}),Jw=t=>(t.client??Te).post({url:"/v0/city/{cityName}/beads",...t,headers:{"Content-Type":"application/json",...t.headers}}),Qw=t=>(t.client??Te).get({url:"/v0/city/{cityName}/events",...t}),Yw=t=>(t.client??Te).get({url:"/v0/city/{cityName}/formulas/feed",...t}),eS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/formulas/{name}",...t}),tS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/health",...t}),nS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/mail",...t}),oS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail",...t,headers:{"Content-Type":"application/json",...t.headers}}),rS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/mail/thread/{id}",...t}),iS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail/{id}/archive",...t}),aS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail/{id}/mark-unread",...t}),sS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail/{id}/read",...t}),lS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail/{id}/reply",...t,headers:{"Content-Type":"application/json",...t.headers}}),uS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/rigs",...t}),cS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/runs/census",...t}),dS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/session/{id}/pending",...t}),pS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/session/{id}/respond",...t,headers:{"Content-Type":"application/json",...t.headers}}),fS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/session/{id}/transcript",...t}),mS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/sessions",...t}),vS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/sling",...t,headers:{"Content-Type":"application/json",...t.headers}}),gS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/status",...t}),hS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/usage",...t}),yS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/workflow/{workflow_id}",...t});class Sn extends Error{constructor(r,i,s,u){super(i),this.status=r,this.requestId=s,this.code=u}status;requestId;code;name="SupervisorApiError"}async function Be(t,r){let i;try{i=await t}catch(f){throw _S(f)}const{response:s}=i;if(s===void 0)throw new Sn(void 0,vu(i.error),void 0,mu(i.error));if(!s.ok||i.error!==void 0)throw new Sn(s.status,vu(i.error,s.statusText),s.headers.get("x-gc-request-id")??void 0,mu(i.error));const u=i.data;if(u===void 0)throw new Sn(s.status,r,s.headers.get("x-gc-request-id")??void 0);return u}function _S(t){return t instanceof Sn?t:new Sn(void 0,vu(t),void 0,mu(t))}function mu(t){if(!hv(t))return;const r=t.code;return typeof r=="string"&&r.trim().length>0?r.trim():void 0}function vu(t,r="gc supervisor request failed"){if(typeof t=="string"&&t.trim().length>0)return t.trim();if(t instanceof Error&&t.message.trim().length>0)return t.message.trim();if(hv(t))for(const i of["error","message","detail"]){const s=t[i];if(typeof s=="string"&&s.trim().length>0)return s.trim()}return r}function hv(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}const xS="";function IS(){const t=globalThis.location?.origin;return typeof t=="string"&&t.length>0&&t!=="null"?t:xS}function ES(t){if(!t.startsWith("/"))return t;const r=globalThis.location?.origin;return typeof r!="string"||r.length===0||r==="null"?t:new URL(t,r).toString().replace(/\/$/,"")}function km(t,r,i){const s=t.replace(/\/$/,""),u=new URLSearchParams(i).toString(),f=u.length>0?`${r}?${u}`:r;return s===""?f:s.startsWith("/")?`${s}${f}`:new URL(f,`${s}/`).toString()}const wS=6e4,Kt={"X-GC-Request":"dashboard"};let Bm=null;const zm=new Map;function yv(t={}){const r=t.baseUrl??IS(),s={baseUrl:ES(r),headers:{Accept:"application/json"},responseStyle:"fields",throwOnError:!1},u=t.client??gv({...s,fetch:bS(t.fetch??globalThis.fetch,_v(t.timeoutMs))});return{baseUrl:r,health(){return Be(Zw({client:u}),"gc supervisor health response was empty")},cityHealth(f){return Be(tS({client:u,path:{cityName:f}}),"gc supervisor city health response was empty")},cityStatus(f){return Be(gS({client:u,path:{cityName:f}}),"gc supervisor status response was empty")},cityUsage(f){return Be(hS({client:u,path:{cityName:f},query:{aggregate_only:!0}}),"gc supervisor usage response was empty")},runCensus(f){return Be(cS({client:u,path:{cityName:f}}),"gc supervisor run census response was empty")},listCities(){return Be(Vw({client:u}),"gc supervisor cities response was empty")},listAgents(f){return Be(Ww({client:u,path:{cityName:f}}),"gc supervisor agents response was empty")},listRigs(f){return Be(uS({client:u,path:{cityName:f}}),"gc supervisor rigs response was empty")},listBeads(f,p,v){return Be(Kw({client:u,path:{cityName:f},...p===void 0?{}:{query:p},...v===void 0?{}:{signal:v}}),"gc supervisor beads response was empty")},listEvents(f,p){return Be(Qw({client:u,path:{cityName:f},...p===void 0?{}:{query:p}}),"gc supervisor events response was empty")},getBead(f,p){return Be(Gw({client:u,path:{cityName:f,id:p}}),"gc supervisor bead response was empty")},createBead(f,p){return Be(Jw({client:u,path:{cityName:f},headers:Kt,body:p}),"gc supervisor bead create response was empty")},updateBead(f,p,v){return Be(Hw({client:u,path:{cityName:f,id:p},headers:Kt,body:v}),"gc supervisor bead update response was empty")},closeBead(f,p){return Be(Xw({client:u,path:{cityName:f,id:p},headers:Kt}),"gc supervisor bead close response was empty")},sling(f,p){return Be(vS({client:u,path:{cityName:f},headers:Kt,body:p}),"gc supervisor sling response was empty")},listMail(f,p){return Be(nS({client:u,path:{cityName:f},...p===void 0?{}:{query:p}}),"gc supervisor mail response was empty")},formulaFeed(f,p){return Be(Yw({client:u,path:{cityName:f},...p===void 0?{}:{query:p}}),"gc supervisor formula feed response was empty")},sendMail(f,p){return Be(oS({client:u,path:{cityName:f},headers:Kt,body:p}),"gc supervisor mail send response was empty")},mailThread(f,p){return Be(rS({client:u,path:{cityName:f,id:p}}),"gc supervisor mail thread response was empty")},markMailRead(f,p,v){return Be(sS({client:u,path:{cityName:f,id:p},headers:Kt,...v===void 0?{}:{query:v}}),"gc supervisor mail mark-read response was empty")},markMailUnread(f,p,v){return Be(aS({client:u,path:{cityName:f,id:p},headers:Kt,...v===void 0?{}:{query:v}}),"gc supervisor mail mark-unread response was empty")},archiveMail(f,p,v){return Be(iS({client:u,path:{cityName:f,id:p},headers:Kt,...v===void 0?{}:{query:v}}),"gc supervisor mail archive response was empty")},replyMail(f,p,v,x){return Be(lS({client:u,path:{cityName:f,id:p},headers:Kt,body:v,...x===void 0?{}:{query:x}}),"gc supervisor mail reply response was empty")},cityEventStreamUrl(f,p){return km(r,`/v0/city/${encodeURIComponent(f)}/events/stream`,p===void 0?void 0:{after_seq:p})},sessionStreamUrl(f,p,v,x){const I={};return v!==void 0&&(I.after_cursor=v),x!==void 0&&(I.format=x),km(r,`/v0/city/${encodeURIComponent(f)}/session/${encodeURIComponent(p)}/stream`,Object.keys(I).length>0?I:void 0)},async listSessions(f){const p=[],v=[];let x=0,I=!1,w;for(;;){const C=await Be(mS({client:u,path:{cityName:f},query:w===void 0?{limit:1e3}:{limit:1e3,cursor:w}}),"gc supervisor sessions response was empty");C.items&&p.push(...C.items),C.partial&&(I=!0),C.partial_errors&&v.push(...C.partial_errors),x=C.total;const O=C.next_cursor;if(O===void 0||O===""||O===w)break;w=O}const b={items:p,total:x};return I&&(b.partial=!0),v.length>0&&(b.partial_errors=v),b},sessionPending(f,p){return Be(dS({client:u,path:{cityName:f,id:p}}),"gc supervisor session pending response was empty")},respondSession(f,p,v){return Be(pS({client:u,path:{cityName:f,id:p},headers:Kt,body:v}),"gc supervisor session respond response was empty")},sessionTranscript(f,p,v){return Be(fS({client:u,path:{cityName:f,id:p},query:{format:v??"conversation"}}),"gc supervisor transcript response was empty")},workflowRun(f,p,v){return Be(yS({client:u,path:{cityName:f,workflow_id:p},...v===void 0?{}:{query:v}}),"gc supervisor workflow response was empty")},formulaDetail(f,p,v){return Be(eS({client:u,path:{cityName:f,name:p},query:v}),"gc supervisor formula detail response was empty")},mutationHeaders(){return{...Kt}}}}function Qe(){return Bm??=yv(),Bm}function SS(t){const r=_v(t),i=zm.get(r);if(i!==void 0)return i;const s=yv({timeoutMs:r});return zm.set(r,s),s}function _v(t){return typeof t=="number"&&Number.isFinite(t)&&t>0?t:wS}function bS(t,r){return async(i,s)=>{const u=new AbortController,f=new Sn(void 0,`gc supervisor request timed out after ${r}ms`,void 0),p=kS(i,s);p?.aborted&&u.abort(p.reason);const v=()=>u.abort(p?.reason);p?.addEventListener("abort",v,{once:!0});let x;const I=new Promise((C,O)=>{x=setTimeout(()=>{u.abort(f),O(f)},r)}),w=new Request(i,{...s,signal:u.signal}),b=t(w);try{return await Promise.race([b,I])}finally{x!==void 0&&clearTimeout(x),p?.removeEventListener("abort",v)}}}function kS(t,r){return r?.signal!==void 0?r.signal:t instanceof Request?t.signal:null}async function BS(t,r){const i=pn("list agent pending interactions"),s=zS(r),u=t.flatMap(p=>{const v=p.session?.name;if(v===void 0)return[];const x=s.get(v);return x===void 0?[]:[{agentName:p.name,sessionId:x,sessionName:v}]});return(await Promise.all(u.map(async p=>{const v=await Qe().sessionPending(i,p.sessionId);return v.pending===void 0?null:{...p,pending:v.pending}}))).filter(p=>p!==null)}async function z9(t,r){const i=pn("respond to agent pending interaction");return Qe().respondSession(i,t,r)}function T9(t){return`gc agent attach ${TS(t)}`}function zS(t){const r=new Map;for(const i of t)i.session_name!==void 0&&r.set(i.session_name,i.id);return r}function TS(t){return/^[A-Za-z0-9_./:-]+$/.test(t)?t:`'${t.replaceAll("'","'\\''")}'`}const CS=1e3,RS=200,NS=1e3,PS=new Set(["feature","bug","task","epic","chore","decision"]);async function jS(t={}){const r=t.city??pn("list supervisor beads"),i=t.limit??CS,s=t.rigFilter?.trim()??"",u=t.includeClosed??!1,f=t.includeBookkeeping??!1,p={limit:i,...u?{all:!0}:{},...s.length===0?{}:{rig:s}},v=t.signal===void 0?await Qe().listBeads(r,p):await Qe().listBeads(r,p,t.signal),x=Iv(v.items??[]),I=u?x:x.filter(C=>C.status!=="closed"),w=f?I:I.filter(AS),b=xv(v.total);return{items:w,total:w.length,...b===void 0?{}:{upstream_total:b},upstream_fetched:x.length,fetch_limit:i}}async function C9(t,r={}){const i=pn("list supervisor assigned beads"),s=$S(t),u=r.limit??RS,f=r.includeClosed??!1;if(s.length===0)return{items:[],total:0,upstream_fetched:0,fetch_limit:u};const p=await Promise.all(s.map(I=>Qe().listBeads(i,{assignee:I,limit:u,...f?{all:!0}:{}}))),v=Iv(p.flatMap(I=>I.items??[])),x=OS(p);return{items:v,total:v.length,...x===void 0?{}:{upstream_total:x},upstream_fetched:v.length,fetch_limit:u}}async function R9(t){const r=pn("fetch supervisor bead");try{return await Qe().getBead(r,t)}catch(i){if(!(i instanceof Sn)||i.status!==404)throw i;const u=((await Qe().listBeads(r,{limit:NS})).items??[]).find(f=>f.id===t);if(u!==void 0)return u;throw i}}function AS(t){return!(!PS.has(t.issue_type)||Array.isArray(t.labels)&&t.labels.some(r=>r.startsWith("gc:")))}function xv(t){if(typeof t=="number")return t;if(typeof t=="bigint")return Number(t)}function OS(t){let r=0;for(const i of t){const s=xv(i.total);if(s===void 0)return;r+=s}return r}function Iv(t){const r=new Set,i=[];for(const s of t)r.has(s.id)||(r.add(s.id),i.push(s));return i}function $S(t){const r=new Set,i=[];for(const s of t){const u=s.trim();u.length===0||r.has(u)||(r.add(u),i.push(u))}return i}const N9=[100,500,1e3],Pc=100,P9=["24h","7d","all"],DS="all",MS={"24h":1440*60*1e3,"7d":10080*60*1e3};async function jc(t,r,i,s=Pc,u=DS,f=Date.now()){const p=pn("list supervisor mail"),v=await Qe().listMail(p,{limit:s}),x=v.items??[],I=qS(LS(x,t,r,i),u,f);return I.sort(ZS),{...v,items:I,total:I.length,upstream_total:x.length,upstream_fetched:x.length,fetch_limit:s}}async function j9(t,r,i,s=Pc){const u=pn("fetch supervisor mail thread");try{const f=await Qe().mailThread(u,t);return Tm(f)}catch(f){if(!(f instanceof Sn)||f.status!==404)throw f;const p=await jc("all",r,i,s),v=p.items.filter(x=>x.thread_id===t);return Tm({...p,items:v,total:v.length})}}function Tm(t){const r=US(t.items??[]).sort(VS);return{...t,items:r,total:r.length}}function LS(t,r,i,s){const u=FS(i,s);return r==="all"?[...t]:r==="inbox"?t.filter(f=>f.to.toLowerCase()===u):t.filter(f=>f.from.toLowerCase()===u)}function qS(t,r,i){if(r==="all")return[...t];const s=i-MS[r];return t.filter(u=>{const f=Date.parse(u.created_at);return Number.isFinite(f)&&f>=s})}function FS(t,r){const i=t.toLowerCase();return i===r.operatorAlias.toLowerCase()?r.operatorWireAlias:i}function US(t){const r=new Set,i=[];for(const s of t)r.has(s.id)||(r.add(s.id),i.push(s));return i}function ZS(t,r){return r.created_at.localeCompare(t.created_at)}function VS(t,r){return t.created_at.localeCompare(r.created_at)}function Ev(t,r){if(t===void 0||t.length===0)return null;const i=Date.parse(t);if(!Number.isFinite(i))return null;const s=r-i;return s>=0?s:null}function wv(t){const r=Math.max(1,Math.round(t/36e5));return r<48?`${r}h`:`${Math.round(r/24)}d`}const WS=1440*60*1e3,GS=4320*60*1e3;function HS(t,r){const i=[];for(const s of t.escalations){const u=XS(s);u!==null&&i.push(u)}for(const s of t.beads){const u=KS(s,r);u!==null&&i.push(u)}return i}function XS(t){return t.status==="closed"?null:{beadId:t.id,reason:"escalated",severity:"attention",summary:`${t.title} — escalation raised`,updatedAt:t.updated_at??t.created_at}}function KS(t,r){if(t.status!=="open"||JS(t))return null;const i=Ev(t.created_at,r);if(i===null||i=GS;return{beadId:t.id,reason:"ready-unclaimed",severity:s?"attention":"watch",summary:`${t.title} opened ${wv(i)} ago`,updatedAt:t.created_at}}function JS(t){return t.assignee!==void 0&&t.assignee.trim().length>0}function Cm(t,r){const i=`/runs/${encodeURIComponent(t)}`;if(r.status!=="available")return i;const s=new URLSearchParams;return s.set("scope_kind",r.kind),s.set("scope_ref",r.ref),`${i}?${s.toString()}`}const QS={"awaiting-input":"awaiting input",errored:"errored","rate-limited":"rate limited",stalled:"stalled"},YS={respond:"Respond to its prompt.",reset:"Reset the agent.",nudge:"Nudge it to resume."},eb={"awaiting-input":"stuck",errored:"stuck","rate-limited":"warn",stalled:"warn"};function tb(t){return QS[t]}function A9(t){return YS[t]}function O9(t){return eb[t]}const nb=new Set(["gc.store.maintenance.failed","order.failed","request.failed","session.crashed","session.stranded","session.work_query_failed","supervisor.shutdown_requested"]),ob=new Set(["events.rotated","session.quarantined","session.suspended","supervisor.fs_pressure.skipped_tick"]);function rb(t){return nb.has(t.type)?"attention":ob.has(t.type)?"watch":"event"}function ib(t){return t.message??t.subject??t.type}const ab=1440*60*1e3,sb=30,lb=2e9,ub=1e9,cb=1e9,db=512e6,pb="gc:escalation",fb="decision.decide";function mb(t={}){return mi.map(r=>vb(r,t))}function vb(t,r){switch(t){case"activity":return Ib(r.activity);case"agents":return yb(r.agents);case"beads":return _b(r.beads);case"health":return gb(r.health);case"mail":return xb(r.mail);case"runs":return hb(r.runs)}}function gb(t){return{id:"health:derived",domain:"health",getItems:()=>Pb(t)}}function hb(t){return{id:"runs:derived",domain:"runs",getItems:()=>Eb(t)}}function yb(t){return{id:"agents:derived",domain:"agents",getItems:()=>wb(t)}}function _b(t){return{id:"beads:derived",domain:"beads",getItems:()=>Sb(t)}}function xb(t){return{id:"mail:derived",domain:"mail",getItems:()=>zb(t)}}function Ib(t){return{id:"activity:derived",domain:"activity",getItems:()=>Cb(t)}}function Eb(t){const r=[];if(t===void 0)return r;const i={provenance:t.provenance,fetchedAt:t.fetchedAt};if(t.error!==void 0&&t.error.length>0)return r.push(kt("runs",{id:"runs:unavailable",title:"Run data unavailable",summary:t.error,href:"/runs"})),r;const s=t.summary;if(s===void 0)return r;s.lanesPartial===!0&&r.push(oi("runs",{id:"runs:partial",title:"Run list incomplete",href:"/runs"},i));for(const u of[...s.lanes,...s.blockedLanes])u.health.status!=="available"&&r.push(oi("runs",{id:`runs:${u.id}:health-unavailable`,title:`${u.title} health unavailable`,summary:u.health.error,href:Cm(u.id,u.scope)},i));for(const u of d3(s.blockedLanes))r.push(kt("runs",{id:`runs:${u.id}:blocked`,title:`${u.title} blocked`,summary:u.reason,href:Cm(u.id,u.scope)}));return r}function wb(t){const r=[];if(t===void 0)return r;if(t.error!==void 0&&t.error.length>0)return r.push(oi("agents",{id:"agents:unavailable",title:"Agent data unavailable",summary:t.error,href:"/agents"})),r;t.partial===!0&&r.push(oi("agents",{id:"agents:partial",title:"Agent list incomplete",href:"/agents"})),t.pendingError!==void 0&&t.pendingError.length>0&&r.push(oi("agents",{id:"agents:pending-unavailable",title:"Agent pending state unavailable",summary:t.pendingError,href:"/agents"}));const i=(t.pendingInteractions??[]).map(s=>({agentName:s.agentName,...s.pending.prompt===void 0?{}:{prompt:s.pending.prompt}}));for(const s of a3(t.items??[],i))r.push(kt("agents",{id:`agents:${s.name}:needs-you`,title:`${s.name} ${tb(s.reason)}`,summary:s.detail,href:`/agents/${encodeURIComponent(s.name)}`}));return r}function Sb(t){const r=[];if(t===void 0)return r;t.error!==void 0&&t.error.length>0&&r.push(kt("beads",{id:"beads:unavailable",title:"Bead data unavailable",summary:t.error,href:"/beads"})),t.partial===!0&&r.push(Yn("beads",{id:"beads:partial",title:"Bead list incomplete",href:"/beads"})),t.decisionsError!==void 0&&t.decisionsError.length>0&&r.push(kt("beads",{id:"beads:decisions-unavailable",title:"Decision queue unavailable",summary:t.decisionsError,href:"/beads"})),t.escalationsError!==void 0&&t.escalationsError.length>0&&r.push(kt("beads",{id:"beads:escalations-unavailable",title:"Escalation queue unavailable",summary:t.escalationsError,href:"/beads"}));for(const u of t.decisions??[])r.push(Bb(u));const i=t.nowMs??Date.now(),s=(t.items??[]).filter(u=>!kb(u,t.decisionLabel));for(const u of HS({beads:s,escalations:t.escalations??[]},i)){const f=u.severity==="attention"?kt:Yn;r.push(f("beads",{id:`beads:${u.beadId}:${u.reason}`,title:`${u.beadId} ${bb(u.reason)}`,summary:u.summary,href:Sv(u.beadId),updatedAt:u.updatedAt}))}return r}function bb(t){return t==="escalated"?"escalated":"unclaimed"}function Sv(t){const r=new URLSearchParams;return r.set("bead",t),`/beads?${r.toString()}`}function kb(t,r){return(t.labels??[]).includes(r)}function Bb(t){const r=t.metadata?.[fb];return kt("beads",{id:`beads:${t.id}:mayor-decision`,title:t.title,href:Sv(t.id),updatedAt:t.updated_at??t.created_at,...r!==void 0&&r.trim().length>0?{summary:r}:{}})}function zb(t){const r=[];if(t===void 0)return r;t.error!==void 0&&t.error.length>0&&r.push(kt("mail",{id:"mail:unavailable",title:"Mail data unavailable",summary:t.error,href:"/mail"})),t.partial===!0&&r.push(Yn("mail",{id:"mail:partial",title:"Mail list incomplete",href:"/mail"}));const i=t.nowMs??Date.now();for(const s of _3(t.items??[])){const u=Ev(s.created_at,i),f=u!==null&&u>=ab;r.push(kt("mail",{id:`mail:${s.id}:${f?"unread-stale":"unread"}`,title:s.subject,summary:f?`from ${s.from}, unread for ${wv(u)}`:`from ${s.from}`,href:Tb(s.id),updatedAt:s.created_at}))}return r}function Tb(t){const r=new URLSearchParams;return r.set("message",t),`/mail?${r.toString()}`}function Cb(t){const r=[];if(t===void 0)return r;t.deploysError!==void 0&&t.deploysError.length>0&&r.push(kt("activity",{id:"activity:deploys-unavailable",title:"Deploy data unavailable",summary:t.deploysError,href:"/activity"})),t.eventsDegraded!==void 0&&t.eventsDegraded.length>0&&r.push(Yn("activity",{id:"activity:events-degraded",title:"Event stream degraded",summary:t.eventsDegraded,href:"/activity"})),t.eventsError!==void 0&&t.eventsError.length>0&&r.push(Yn("activity",{id:"activity:events-unavailable",title:"Event history unavailable",summary:t.eventsError,href:"/activity"})),t.eventsPartial===!0&&r.push(Yn("activity",{id:"activity:events-partial",title:"Event history incomplete",href:"/activity"})),Rb(r,t.events??[]);const i=t.deploys;if(i===void 0)return r;i.failed_marker&&r.push(kt("activity",{id:"activity:failed-marker",title:"Deploy failed marker present",href:"/activity"}));for(const s of i.items)s.status==="failed"?r.push(kt("activity",{id:`activity:deploy:${s.at}:failed`,title:"Deploy failed",summary:s.detail,href:"/activity",updatedAt:s.at})):s.status==="in-progress"&&r.push(Yn("activity",{id:`activity:deploy:${s.at}:in-progress`,title:"Deploy in progress",summary:s.detail,href:"/activity",updatedAt:s.at}));return r}function Rb(t,r){for(const i of r){const s=rb(i);if(s==="event")continue;const u=s==="attention"?kt:Yn;t.push(u("activity",{id:`activity:event:${String(i.seq)}:${i.type}`,title:i.type,summary:ib(i),href:Nb(i),updatedAt:i.ts}))}}function Nb(t){return`/activity?${new URLSearchParams({mode:"events",type:t.type}).toString()}`}function Pb(t){const r=[];return t===void 0||(t.dashboardError!==void 0&&t.dashboardError.length>0&&r.push(to({id:"health:dashboard-health-unavailable",title:"Dashboard health unavailable",summary:t.dashboardError})),t.supervisor!==void 0&&jb(r,t.supervisor),t.system!==void 0&&(Ab(r,t.system),Ob(r,t.system)),t.trend!==void 0&&!t.trend.available&&r.push(Eo({id:"health:dolt-noms-unavailable",title:"Dolt-noms trend unavailable",summary:t.trend.reason}))),r}function jb(t,r){if(r.status==="unavailable"){t.push(to({id:"health:supervisor-unreachable",title:"Supervisor unreachable",summary:r.error}));return}const i=r.data;i.status!=="ok"&&t.push(to({id:"health:supervisor-not-ok",title:`Supervisor ${i.status}`})),i.city===void 0&&t.push(Eo({id:"health:supervisor-city-missing",title:"Supervisor city missing",summary:"city was absent from generated supervisor health"})),i.version===void 0&&t.push(Eo({id:"health:supervisor-version-missing",title:"Supervisor version missing",summary:"version was absent from generated supervisor health"}))}function Ab(t,r){const i=r.admin;i.uptime_sec=lb?t.push(to({id:"health:dashboard-process-rss-high",title:"Dashboard RSS high",summary:Na(i.rss.value)})):i.rss.status==="available"&&i.rss.value>=ub&&t.push(Eo({id:"health:dashboard-process-rss-elevated",title:"Dashboard RSS elevated",summary:Na(i.rss.value)})),i.heap_used_bytes>=cb?t.push(to({id:"health:dashboard-process-heap-high",title:"Dashboard heap high",summary:Na(i.heap_used_bytes)})):i.heap_used_bytes>=db&&t.push(Eo({id:"health:dashboard-process-heap-elevated",title:"Dashboard heap elevated",summary:Na(i.heap_used_bytes)}))}function Ob(t,r){const i=r.host.memory.status==="available"?Rm(r.host.memory.value.free_mem_bytes,r.host.memory.value.total_mem_bytes):null;i!==null&&i<.05?t.push(to({id:"health:memory-critical",title:"Host memory critical",summary:`${Math.round(i*100)}% free`})):i!==null&&i<.1&&t.push(Eo({id:"health:memory-low",title:"Host memory low",summary:`${Math.round(i*100)}% free`}));const s=r.host.load.status==="available"?r.host.load.value.load_avg_1:null;if(s===null)return;const u=Rm(s,r.host.cpu_count);u!==null&&u>1.5?t.push(to({id:"health:load-high",title:"Host load high",summary:`${s.toFixed(2)} load across ${r.host.cpu_count} CPUs`})):u!==null&&u>1&&t.push(Eo({id:"health:load-elevated",title:"Host load elevated",summary:`${s.toFixed(2)} load across ${r.host.cpu_count} CPUs`}))}function Na(t){return t>=1e9?`${(t/1e9).toFixed(1)} GB`:t>=1e6?`${Math.round(t/1e6)} MB`:t>=1e3?`${Math.round(t/1e3)} KB`:`${t} B`}function Rm(t,r){return r<=0?null:t/r}function to(t){return{domain:"health",severity:"attention",href:"/health",current:!0,actionable:!0,...t}}function kt(t,r){return{domain:t,severity:"attention",current:!0,actionable:!0,...r}}function Yn(t,r){return{domain:t,severity:"watch",current:!0,actionable:!1,...r}}function oi(t,r,i){return{domain:t,severity:"unavailable",current:!0,actionable:!1,...r,...i?.provenance===void 0?{}:{provenance:i.provenance},...i?.fetchedAt===void 0?{}:{fetchedAt:i.fetchedAt}}}function Eo(t){return{domain:"health",severity:"watch",href:"/health",current:!0,actionable:!1,...t}}const $b=1e3,Db=100,Mb="24h",Lb=2500,qb=[250,500,1e3,2e3],Fb=5e3,Ub="city-not-found";function Zb(t,r){const i=Xa(),s=i??"no-city",{decisionLabel:u,operatorWireAlias:f}=t,p=T.useMemo(()=>Vb(r),[r]),v=En(`attention:agents:${s}`,()=>Wb(i)),x=En(`attention:beads:${s}:${u}`,L=>Gb(i,u,L)),I=En(`attention:mail:${s}:${f}`,()=>Jb(i,t)),w=En(`attention:activity:${s}`,()=>Qb(i)),b=En(`attention:health:${s}`,()=>Yb(i)),C=x.data,O=x.refresh;return T.useEffect(()=>{if(C?.cityUnavailable!==!0)return;const L=setTimeout(()=>{O()},Fb);return()=>clearTimeout(L)},[C,O]),T.useMemo(()=>mb(ek({activity:w.data,agents:v.data,beads:C,health:b.data,mail:I.data,runs:p})),[w.data,v.data,C,b.data,I.data,p])}function Vb(t){if(t!==void 0)return t.status==="error"?{error:t.error,provenance:"error"}:{summary:t.data,provenance:t.status,fetchedAt:t.fetchedAt}}async function Wb(t){if(t===null)return{};try{const r=await Qe().listAgents(t),i={items:r.items??[],partial:r.partial===!0};try{const s=await Qe().listSessions(t);i.pendingInteractions=await BS(r.items??[],s.items??[])}catch(s){i.pendingError=Lt(s,"agent pending state unavailable")}return i}catch(r){return{error:Lt(r,"agent list unavailable")}}}async function Gb(t,r,i){if(t===null)return{decisionLabel:r};const s=()=>Promise.allSettled([jS({limit:$b,city:t,...i===void 0?{}:{signal:i}}),Xb(t,r,i),Kb(t,i)]);ni(i);let u=await s();ni(i);for(const w of qb){if(!u.some(Nm))break;await Hb(w,i),ni(i),u=await s(),ni(i)}const[f,p,v]=u,x={nowMs:Date.now(),decisionLabel:r},I=u.find(Nm);if(I!==void 0&&I.status==="rejected"){const w=Lt(I.reason,"city unavailable");return{...x,cityUnavailable:!0,error:w,decisionsError:w,escalationsError:w}}return f.status==="fulfilled"?(x.items=f.value.items,x.partial=f.value.partial===!0):x.error=Lt(f.reason,"bead list unavailable"),p.status==="fulfilled"?x.decisions=p.value.items??[]:x.decisionsError=Lt(p.reason,"decision queue unavailable"),v.status==="fulfilled"?x.escalations=v.value.items??[]:x.escalationsError=Lt(v.reason,"escalation queue unavailable"),x}function Nm(t){return t.status==="rejected"&&t.reason instanceof Sn&&t.reason.status===404&&t.reason.code===Ub}function Hb(t,r){return r===void 0?new Promise(i=>setTimeout(i,t)):(ni(r),new Promise((i,s)=>{const u=setTimeout(()=>{r.removeEventListener("abort",f),i()},t),f=()=>{clearTimeout(u),s(bv(r))};r.addEventListener("abort",f,{once:!0})}))}function ni(t){if(t?.aborted===!0)throw bv(t)}function bv(t){return t.reason??new DOMException("The operation was aborted","AbortError")}async function Xb(t,r,i){return Qe().listBeads(t,{label:r,status:"open"},i)}async function Kb(t,r){return Qe().listBeads(t,{label:pb,status:"open"},r)}async function Jb(t,r){if(t===null)return{};try{const i=await jc("inbox",r.operatorAlias,r,Pc);return{items:i.items??[],nowMs:Date.now(),partial:i.partial===!0}}catch(i){return{error:Lt(i,"mail list unavailable")}}}async function Qb(t){const[r,i]=await Promise.allSettled([lr.listBuilds(),t===null?Promise.resolve(null):Qe().listEvents(t,{limit:Db,since:Mb})]),s={};return r.status==="fulfilled"?s.deploys=r.value:s.deploysError=Lt(r.reason,"deploy activity unavailable"),i.status==="fulfilled"?i.value!==null&&(s.events=i.value.items??[],s.eventsPartial=i.value.partial===!0,i.value.partial_errors!==null&&i.value.partial_errors!==void 0&&(s.eventsDegraded=i.value.partial_errors.join("; "))):s.eventsError=Lt(i.reason,"event history unavailable"),s}async function Yb(t){if(t===null)return{};const[r,i,s]=await Promise.allSettled([lr.systemHealth(),SS(Lb).cityHealth(t),lr.doltTrend()]),u={},f=[];return r.status==="fulfilled"?u.system=r.value:f.push(Lt(r.reason,"dashboard health unavailable")),i.status==="fulfilled"?u.supervisor={status:"available",data:i.value}:u.supervisor={status:"unavailable",error:Lt(i.reason,"supervisor health unavailable")},s.status==="fulfilled"?u.trend=s.value:f.push(Lt(s.reason,"dolt-noms trend unavailable")),f.length>0&&(u.dashboardError=f.join("; ")),u}function ek(t){const r={};for(const[i,s]of Object.entries(t))s!==void 0&&(r[i]=s);return r}async function nr(t){const r={Accept:"application/json","Content-Type":"application/json","X-GC-Request":"dashboard"};try{const i=await fetch("/api/client-errors",{method:"POST",headers:r,credentials:"same-origin",keepalive:!0,body:JSON.stringify(t)});return i.ok?{status:"reported"}:{status:"failed",error:`client error report failed with ${i.status}`}}catch(i){return{status:"failed",error:Yo(i)}}}class kv extends T.Component{state={crashed:!1};static getDerivedStateFromError(){return{crashed:!0}}componentDidCatch(r,i){nr({component:"ErrorBoundary",operation:"componentDidCatch",message:Yo(r)})}render(){return this.state.crashed?M.jsx("main",{className:"max-w-dashboard mx-auto px-4 sm:px-6 lg:px-8 py-12",children:M.jsxs("section",{className:"space-y-4",role:"alert",children:[M.jsx("h1",{className:"text-display font-semibold text-fg",children:"Dashboard view failed."}),M.jsx("p",{className:"text-body text-fg-muted",children:"The error was reported to the local dashboard log. Refresh to retry this view."})]})}):this.props.children}}function tk({label:t,summary:r}){const i=r.attention+r.watch;if(i===0||r.severity===null)return null;const s=i===1?"item":"items";return M.jsx("span",{"aria-label":`${t}: ${i} ${r.severity} ${s}`,className:`ml-1 align-super text-[0.65rem] leading-none tnum ${nk(r.severity)}`,children:i})}function nk(t){return t==="attention"?"text-accent":"text-warn"}function Bv(t,r,i){try{const s=Ac(t).getItem(r);return s===null?{status:"missing"}:{status:"found",value:s}}catch(s){return Oc(t,"getItem",r,i,s)}}function zv(t,r,i,s){try{return Ac(t).setItem(r,i),{status:"stored"}}catch(u){return Oc(t,"setItem",r,s,u)}}function Tv(t,r,i){try{return Ac(t).removeItem(r),{status:"stored"}}catch(s){return Oc(t,"removeItem",r,i,s)}}function Ac(t){return t==="localStorage"?window.localStorage:window.sessionStorage}function Oc(t,r,i,s,u){const f=Yo(u);return nr({component:s,operation:`${t}.${r}`,message:`${i}: ${f}`}),{status:"unavailable",error:f}}const gu="gascity:theme",hu="ThemeContext",Cv=T.createContext(null);function ok(){const t=Bv("localStorage",gu,hu);return t.status==="found"&&(t.value==="light"||t.value==="dark")?t.value:"system"}function rk(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function ik(t){const r=document.documentElement;t==="system"?r.removeAttribute("data-theme"):r.setAttribute("data-theme",t)}function ak({children:t}){const[r,i]=T.useState(ok),[s,u]=T.useState(rk);T.useEffect(()=>{const I=window.matchMedia("(prefers-color-scheme: dark)"),w=()=>u(I.matches?"dark":"light");return I.addEventListener("change",w),()=>I.removeEventListener("change",w)},[]);const f=r==="system"?s:r,p=T.useCallback(I=>{i(I),I==="system"?Tv("localStorage",gu,hu):zv("localStorage",gu,I,hu),ik(I)},[]),v=T.useCallback(()=>{p(f==="dark"?"light":"dark")},[f,p]),x=T.useMemo(()=>({pref:r,resolved:f,set:p,toggle:v}),[r,f,p,v]);return M.jsx(Cv.Provider,{value:x,children:t})}function sk(){const t=T.useContext(Cv);if(t===null)throw new Error("useTheme must be used inside ");return t}const Rv={operatorAlias:"operator",operatorWireAlias:"human",decisionLabel:"needs/operator"},Nv=T.createContext(Rv);function lk({operator:t,children:r}){return M.jsx(Nv.Provider,{value:t,children:r})}function Pv(){return T.useContext(Nv)}function uk(t){return t===void 0?Rv:{operatorAlias:t.operatorAlias,operatorWireAlias:t.operatorWireAlias,decisionLabel:t.decisionLabel}}const ck={ok:"text-ok",warn:"text-warn",stuck:"text-accent",neutral:"text-fg-muted"},dk={ok:"●",warn:"▲",stuck:"■",neutral:"·"};function pk({tone:t,label:r,glyph:i,trailing:s,className:u="",title:f}){return M.jsxs("span",{className:`inline-flex items-baseline gap-1.5 text-body ${ck[t]} ${u}`,title:f,children:[M.jsx("span",{"aria-hidden":!0,className:"text-[0.85em] leading-none translate-y-[1px]",children:i??dk[t]}),M.jsx("span",{children:r}),s&&M.jsx("span",{className:"text-fg-faint text-label uppercase tracking-wider",children:s})]})}function $9(t){switch(t){case"closed":return"neutral";case"in_progress":return"ok";case"blocked":return"stuck";default:return"warn"}}function D9(t){switch(t){case"active":case"running":return"ok";case"rate-limited":case"rate_limited":case"waiting":return"warn";case"failed":case"closed":case"errored":case"stuck":return"stuck";default:return"neutral"}}const jv=T.createContext(!1);function fk({readOnly:t,children:r}){return M.jsx(jv.Provider,{value:t,children:r})}function mk(){return T.useContext(jv)}function vk(t,r){return t?t.readOnly:r!==null}const Av="Read-only mode: mutations are disabled";function M9(){return M.jsx(pk,{tone:"warn",label:"Read-only",title:Av})}const gk="mayor";function hk(t){const{operator:r,sessionAliases:i,mailFromOrTo:s}=t,u=new Map;for(const O of i){const L=O.toLowerCase();u.has(L)||u.set(L,O)}for(const O of s){const L=O.toLowerCase();u.has(L)||u.set(L,O)}const f=r.toLowerCase(),p=new Set(s.map(O=>O.toLowerCase())),v=[r],x=[],I=[],w=[];for(const[O,L]of u)if(O!==f){if(O===gk){x.push(L);continue}p.has(O)?I.push(L):w.push(L)}const b=(O,L)=>O.toLowerCase().localeCompare(L.toLowerCase());I.sort(b),w.sort(b);const C=[{tier:"you",aliases:v}];return x.length>0&&C.push({tier:"mayor",aliases:x}),I.length>0&&C.push({tier:"active",aliases:I}),w.length>0&&C.push({tier:"other",aliases:w}),C}function yk(t,r){return t===r?"user":t}function L9(t){switch(t){case"you":return"You";case"mayor":return"Mayor";case"active":return"Active";case"other":return"Other"}}async function _k(){return Qe().listSessions(pn("list supervisor sessions"))}async function q9(t){const r=await Qe().sessionTranscript(pn("fetch supervisor session transcript"),t,"conversation");return Ek(r)}async function F9(t){const r=await Qe().sessionTranscript(pn("fetch structured session transcript"),t,"structured");return xk(r)}function xk(t){if(t.format!=="structured")return null;if(!GE(t))throw new Error("Malformed structured transcript response.");return t}function U9(t){return(t.items??[]).map(Ik)}function Ik(t){const r={id:t.id,template:t.template,session_name:t.session_name,title:t.title,state:t.state,created_at:t.created_at,attached:t.attached,running:t.running,provider:t.provider};return t.alias!==void 0&&(r.alias=t.alias),t.reason!==void 0&&(r.reason=t.reason),t.display_name!==void 0&&(r.display_name=t.display_name),t.last_active!==void 0&&(r.last_active=t.last_active),t.rig!==void 0&&(r.rig=t.rig),t.pool!==void 0&&(r.pool=t.pool),t.agent_kind!==void 0&&(r.agent_kind=t.agent_kind),t.model!==void 0&&(r.model=t.model),t.context_pct!==void 0&&(r.context_pct=t.context_pct),t.context_window!==void 0&&(r.context_window=t.context_window),t.activity!==void 0&&(r.activity=t.activity),r}function Ek(t,r=new Date().toISOString()){if(t.format!=="conversation"&&t.format!=="text")throw new Error(`expected conversation transcript, got ${t.format}`);const i=t.turns??[];return{...t,turns:i,total_chars:i.reduce((s,u)=>s+u.text.length,0),captured_at:r,truncated:!1}}const yu="gascity.dashboard.viewingAs",or="ViewingAsContext",Pm=/^[a-z][a-z0-9_./-]{1,63}$/i,jm=[3e4,9e4,27e4];function wk(t){if(!Number.isInteger(t)||t<0||t>=jm.length)return null;const r=jm[t];return r===void 0?null:r}const Ov=T.createContext(null);function Am(t){const r=Bv("sessionStorage",yu,or);if(r.status==="found"){const i=r.value;if(i.length>0&&i.length<=64)return i}return t}function tu(t,r){t===r?Tv("sessionStorage",yu,or):zv("sessionStorage",yu,t,or)}function Sk({children:t}){const r=Pv(),{operatorAlias:i}=r,[s,u]=T.useState(()=>Am(i)),f=T.useRef(i),[p,v]=T.useState([]),[x,I]=T.useState([]),[w,b]=T.useState(!1),[C,O]=T.useState(!1),L=T.useRef(!1),W=T.useRef(!0),D=T.useRef(null),G=T.useCallback(de=>{u(de),tu(de,i)},[i]),ee=T.useCallback(()=>{u(i),tu(i,i)},[i]),J=T.useCallback(async()=>{try{const de=await _k();if(!W.current)return!0;const we=new Set,Se=[];for(const Ne of de.items??[]){if(typeof Ne.alias!="string"||!Pm.test(Ne.alias))continue;const Ae=Ne.alias.toLowerCase();we.has(Ae)||(we.add(Ae),Se.push(Ne.alias))}return v(Se),O(!1),!0}catch(de){return nr({component:or,operation:"loadAliases.sessions",message:Yo(de)}),!1}},[]),H=T.useCallback(de=>{if(!W.current)return;const we=wk(de);we!==null&&(D.current=setTimeout(()=>{D.current=null,W.current&&J().then(Se=>{W.current&&(Se||H(de+1))}).catch(Se=>{nr({component:or,operation:"loadAliases.sessionsRetry",message:Yo(Se)})})},we))},[J]),te=T.useCallback(()=>{if(L.current)return;L.current=!0,b(!0);let de=2;const we=()=>{de-=1,de===0&&W.current&&b(!1)};J().then(Se=>{W.current&&(Se||(O(!0),H(0)))}).finally(we),jc("all",i,r).then(Se=>{if(!W.current)return;const Ne=new Set,Ae=[];for(const nt of Se.items)for(const Ye of[nt.from,nt.to]){if(typeof Ye!="string"||Ye.length===0||!Pm.test(Ye))continue;const zt=Ye.toLowerCase();Ne.has(zt)||(Ne.add(zt),Ae.push(Ye))}I(Ae)}).catch(Se=>{nr({component:or,operation:"loadAliases.mail",message:Yo(Se)})}).finally(we)},[J,H,i,r]);T.useEffect(()=>(W.current=!0,()=>{W.current=!1,D.current!==null&&(clearTimeout(D.current),D.current=null)}),[]),T.useEffect(()=>{const de=f.current;f.current=i,de!==i&&s===de&&u(Am(i))},[i,s]);const ue=T.useMemo(()=>hk({operator:i,sessionAliases:p.includes(s)?p:[...p,s],mailFromOrTo:x}),[p,x,s,i]),ve=T.useMemo(()=>({viewingAs:{alias:s,isOperator:s===i},setAlias:G,resetToOperator:ee,aliasBuckets:ue,aliasesLoading:w,sessionsUnavailable:C,loadAliases:te}),[s,i,G,ee,ue,w,C,te]);return T.useEffect(()=>{const de=()=>{document.hidden&&s!==i&&(u(i),tu(i,i))};return document.addEventListener("visibilitychange",de),()=>document.removeEventListener("visibilitychange",de)},[s,i]),M.jsx(Ov.Provider,{value:ve,children:t})}function bk(){const t=T.useContext(Ov);if(t===null)throw new Error("useViewingAs must be inside ");return t}const kk={id:"activity",kind:"core",path:"/activity",nav:{label:"Activity",order:55},element:T.lazy(()=>Rn(()=>import("./Activity-ByhthQ6l.js"),__vite__mapDeps([0,1,2,3,4])).then(t=>({default:t.ActivityPage})))},Bk={id:"health",kind:"core",path:"/health",nav:{label:"Health",order:60},element:T.lazy(()=>Rn(()=>import("./Health-TkHQ7rEN.js"),__vite__mapDeps([5,1,2,4,6,3])).then(t=>({default:t.HealthPage})))},$v=[kk,Bk],zk={views:"views"};function Tk(t,r){console.warn(`[${t}] ${r}`)}function Dv(t,r){const i=new Set(r??[]);return t.filter(s=>s.kind==="core"||i.has(s.id))}const Ck={};function Rk(t,r){const i=[];if(r!==null){const p=Ck[r];if(p!==void 0){if(t.some(x=>x.id===p.target))return{view:null,redirectTo:p.redirectTo,source:"env",warnings:i};i.push(`DEFAULT_VIEW="${r}" alias targets the "${p.target}" view, which is not enabled in this deployment (known enabled ids: ${t.map(x=>x.id).join(", ")||"(none)"}); falling through to descriptor / ambient-home`)}else{const v=t.find(x=>x.id===r);if(v!==void 0)return{view:v,source:"env",warnings:i};i.push(`DEFAULT_VIEW="${r}" does not match any enabled view (known enabled ids: ${t.map(x=>x.id).join(", ")||"(none)"}); falling through to descriptor / ambient-home`)}}const s=t.filter(p=>p.defaultRoute===!0),[u,...f]=s;if(u!==void 0&&f.length===0)return{view:u,source:"descriptor",warnings:i};if(u!==void 0){const v=[...s].sort(Pk)[0]??u;return i.push(`multiple views declare defaultRoute: true (${s.map(x=>x.id).join(", ")}); picking "${v.id}" by lowest nav.order`),{view:v,source:"descriptor",warnings:i}}return{view:null,source:"fallback",warnings:i}}function Nk(t,r){const i=Rk(t,r);for(const s of i.warnings)Tk(zk.views,s);return i}function Pk(t,r){const i=t.nav?.order??Number.POSITIVE_INFINITY,s=r.nav?.order??Number.POSITIVE_INFINITY;return i!==s?i-s:t.id.localeCompare(r.id)}const jk=[{to:"/",label:"Home",end:!0,order:10},{to:"/agents",label:"Agents",order:20},{to:"/beads",label:"Beads",order:30},{to:"/runs",label:"Runs",order:40},{to:"/mail",label:"Mail",order:50}],Ak={"/agents":"agents","/beads":"beads","/runs":"runs","/mail":"mail","/activity":"activity","/health":"health"};function Ok(){const{resolved:t,toggle:r}=sk(),{viewingAs:i}=bk(),{operatorAlias:s}=Pv(),u=mk(),f=Tw(),{data:p}=En("config",()=>lr.config()),{data:v}=En("cities",()=>Qe().listCities()),x=Xa(),I=v?.items??[],w=x??p?.cityName??"",b=w===""||I.some(G=>G.name===w),C=I.length>1||!b,O=G=>{G!==x&&window.location.assign(`/city/${encodeURIComponent(G)}/`)},L=T.useMemo(()=>{const ee=Dv($v,p?.enabledModules??null).flatMap(J=>J.nav===null?[]:[{to:J.path,label:J.nav.label,end:J.path==="/",order:J.nav.order}]);return[...jk,...ee].sort((J,H)=>J.order-H.order)},[p?.enabledModules]),{pathname:W}=Tn(),D=!i.isOperator&&W.startsWith("/mail");return M.jsx("header",{className:"border-b border-rule",children:M.jsxs("div",{className:"max-w-dashboard mx-auto px-4 sm:px-6 lg:px-8 py-5 flex items-baseline gap-x-6 lg:gap-x-8 gap-y-2 flex-wrap",children:[M.jsxs("div",{className:"flex items-baseline gap-3 min-w-0",children:[M.jsx("span",{className:"text-title font-semibold tracking-tight text-fg",children:"gas city"}),M.jsx("span",{className:"text-fg-muted","aria-hidden":"true",children:"·"}),C?M.jsx("label",{className:"sr-only",htmlFor:"city-switcher",children:"Switch city"}):null,C?M.jsxs("select",{id:"city-switcher",value:w,onChange:G=>O(G.target.value),className:"text-label uppercase tracking-wider text-fg-muted bg-transparent border-0 focus-mark cursor-pointer hover:text-fg transition-colors duration-150 ease-out-quart",children:[!b&&w!==""?M.jsxs("option",{value:w,disabled:!0,children:[w," (unknown)"]}):null,I.map(G=>M.jsxs("option",{value:G.name,children:[G.name,G.running?"":" (stopped)"]},G.name))]}):M.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:w||"city"}),D&&M.jsxs("span",{className:"text-label uppercase tracking-wider text-accent ml-3",children:["· reading as ",yk(i.alias,s)]}),u&&M.jsx("span",{title:Av,className:"text-label uppercase tracking-wider text-warn ml-3",children:"· read-only"})]}),M.jsx("nav",{className:"flex-1",children:M.jsx("ul",{className:"flex items-baseline gap-x-5 lg:gap-x-7 gap-y-1 flex-wrap",children:L.map(G=>{const ee=Ak[G.to];return M.jsx("li",{children:M.jsxs(Y0,{to:G.to,end:G.end??!1,className:({isActive:J})=>["text-title transition-colors duration-150 ease-out-quart focus-mark",J?"text-fg font-semibold":"text-fg-muted font-medium hover:text-fg"].join(" "),children:[G.label,ee!==void 0&&M.jsx(tk,{label:G.label,summary:f.byDomain[ee]})]})},G.to)})})}),M.jsx("button",{type:"button",onClick:r,"aria-label":`Switch to ${t==="dark"?"light":"dark"} theme`,className:"text-label uppercase tracking-wider text-fg-muted hover:text-fg transition-colors duration-150 ease-out-quart focus-mark",children:t==="dark"?"Light":"Dark"})]})})}function $k({children:t}){return M.jsxs("div",{className:"min-h-screen bg-surface text-fg antialiased",children:[M.jsx(Ok,{}),M.jsx("main",{className:"max-w-dashboard mx-auto px-4 sm:px-6 lg:px-8 py-12",children:t})]})}const Mv=T.createContext(null);function Dk({children:t,intervalMs:r=1e3}){const[i,s]=T.useState(()=>Date.now());return T.useEffect(()=>{const u=window.setInterval(()=>{s(Date.now())},r);return()=>{window.clearInterval(u)}},[r]),M.jsx(Mv.Provider,{value:i,children:t})}function Z9(){const t=T.useContext(Mv);if(t===null)throw new Error("useNow must be called inside a NowProvider.");return t}const Mk=2e3,Lk=2500;function qk(t,r,i={}){const[s,u]=T.useState("connecting"),f=T.useRef(r);f.current=r;const p=T.useRef(i.matches);p.current=i.matches;const v=T.useRef(i.coalesceMs);v.current=i.coalesceMs;const x=t.join(","),I=T.useRef(0),w=T.useRef(null);return T.useEffect(()=>{if(t.length===0){u("closed");return}let b=null,C=!1,O=null,L=null,W=1e3,D=!1;const G=()=>{L!==null&&(clearTimeout(L),L=null)},ee=ue=>{D||(D=!0,Fk(ue))},J=()=>{I.current=Date.now(),f.current()},H=()=>{const ue=v.current??Lk,ve=Date.now()-I.current;ve>=ue?(w.current&&(clearTimeout(w.current),w.current=null),J()):w.current===null&&(w.current=setTimeout(()=>{w.current=null,C||J()},ue-ve))},te=()=>{const ue=globalThis.EventSource;if(typeof ue!="function"){u("closed");return}const ve=Xa();if(ve===null){u("closed");return}const de=new ue(Qe().cityEventStreamUrl(ve));b=de,u("connecting"),L=setTimeout(()=>{C||b!==de||de.readyState===ue.CLOSED||u("open")},Mk),b.onopen=()=>{C||(G(),u("open"),W=1e3)};const we=Se=>{if(C)return;let Ne=null;try{Ne=JSON.parse(Se.data)}catch{u("degraded"),ee("invalid JSON");return}if(!Uk(Ne)){u("degraded"),ee("missing string event type");return}const Ae=Ne.type;if(typeof Ae!="string"){u("degraded"),ee("missing string event type");return}u("open");for(const nt of t)if(Ae.startsWith(nt)){const Ye=Ne;(p.current?.(Ye)??!0)&&H();break}};b.onmessage=we,b.addEventListener("event",we),b.onerror=()=>{C||(G(),u("closed"),b?.close(),b=null,O=setTimeout(()=>{W=Math.min(W*2,3e4),te()},W))}};return te(),()=>{C=!0,O&&clearTimeout(O),G(),w.current&&(clearTimeout(w.current),w.current=null),b?.close()}},[x]),s}function Fk(t){nr({component:"gc-events",operation:"parse event",message:`Malformed gc event payload: ${t}.`})}function Uk(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}const Zk=60*1e3;async function $c(){const t=new Date().toISOString();try{const r=await lr.runSummary();return{source:"runs",status:"fresh",fetchedAt:t,staleAt:new Date(Date.parse(t)+Zk).toISOString(),error:{kind:"none"},data:r}}catch(r){return{source:"runs",status:"error",error:Hk(r,"formula runs unavailable")}}}function Vk(){return $c()}function Wk(){return $c()}function Gk(){return $c()}function Hk(t,r){return t instanceof Error&&t.message.trim().length>0?t.message:r}const Om=1e4,Xk=[2e3,5e3,1e4];function Kk(){const t=Xa(),r=T.useRef(null),i=T.useRef(!1),s=T.useCallback(async()=>{const te=await Vk().catch(ve=>({source:"runs",status:"error",error:ve instanceof Error?ve.message:"formula runs unavailable"}));if(te.status!=="error")return i.current=!1,te;const ue=r.current;return ue===null?te:(i.current=!0,{...ue,status:"stale"})},[]),u=T.useCallback(async()=>{const te=await Wk().catch(ve=>({source:"runs",status:"error",error:ve instanceof Error?ve.message:"formula runs unavailable"}));if(te.status!=="error")return te;const ue=r.current;return ue===null?te:(i.current=!0,{...ue,status:"stale"})},[]),{data:f,loading:p,error:v,refresh:x,cheapRefresh:I}=En(`runs:summary:${t??"no-city"}`,Gk,{refreshFetcher:s,sseRefreshFetcher:u});f!==void 0&&f.status!=="error"&&(r.current=f);const w=f??null,b=T.useRef(null);b.current=w?.status??null;const C=T.useRef(p);C.current=p;const O=T.useRef(0),L=T.useRef(null);T.useEffect(()=>{if(w===null||w.status==="error")return;const te=t??"no-city";L.current!==te&&(L.current=te,x().catch(()=>{L.current=null}))},[t,x,w]);const W=T.useRef(0);T.useEffect(()=>{if(w===null)return;if(!(w.status==="error"?!0:i.current||w.data.lanesPartial===!0&&w.data.lanes.length===0&&w.data.blockedLanes.length===0)){W.current=0;return}const ue=Xk[W.current];if(ue===void 0)return;W.current+=1;const ve=setTimeout(()=>{x()},ue);return()=>clearTimeout(ve)},[w,x]);const D=T.useRef(!1),G=T.useRef(null),ee=T.useCallback(()=>{G.current!==null&&(clearTimeout(G.current),G.current=null),O.current=Date.now(),I().catch(()=>{O.current=0})},[I]),J=T.useCallback(()=>{if(b.current===null||b.current==="fixture")return;if(C.current){D.current=!0;return}Date.now()-O.current{if(p||!D.current)return;D.current=!1;const te=Math.max(0,Om-(Date.now()-O.current));return G.current=setTimeout(ee,te),()=>{G.current!==null&&(clearTimeout(G.current),G.current=null)}},[p,ee]);const H=qk([v3.bead],J);return{source:f,loading:p,error:v,refresh:x,sseState:H}}const Lv=T.createContext(null);function Jk({children:t}){const r=Kk();return M.jsx(Lv.Provider,{value:r,children:t})}function Qk(){const t=T.useContext(Lv);if(t===null)throw new Error("useRunSummary must be used within a RunSummaryProvider");return t}const Yk=T.lazy(()=>Rn(()=>import("./Agents-5svbkUmF.js"),__vite__mapDeps([7,8,1,9,10,2,11,3,12,6,13,14])).then(t=>({default:t.AgentsPage}))),e9=T.lazy(()=>Rn(()=>import("./AgentDetail-LPnb-I_r.js"),__vite__mapDeps([15,16,6,17,12,3,10,2,8])).then(t=>({default:t.AgentDetailPage}))),t9=T.lazy(()=>Rn(()=>import("./CockpitHome-DJOqblJc.js"),__vite__mapDeps([18,2])).then(t=>({default:t.CockpitHomePage}))),n9=T.lazy(()=>Rn(()=>import("./Beads-BdIAJPDE.js"),__vite__mapDeps([19,1,16,6,17,12,3,10,20,9,2,14])).then(t=>({default:t.BeadsPage}))),o9=T.lazy(()=>Rn(()=>import("./Mail-BOec_zQx.js"),__vite__mapDeps([21,9,1,20,13,10,2,17,3])).then(t=>({default:t.MailPage}))),r9=T.lazy(()=>Rn(()=>import("./FormulaRunDetail-Cz_p7EMT.js"),__vite__mapDeps([22,2,16,6,17,12,3,10,23])).then(t=>({default:t.FormulaRunDetailPage}))),i9=T.lazy(()=>Rn(()=>import("./Runs-CdFC1a5g.js"),__vite__mapDeps([24,1,2,11,3,23])).then(t=>({default:t.RunsPage})));function a9(){const{data:t,error:r}=En("config",()=>lr.config()),i=t?.enabledModules??null,s=t?.defaultView??null,u=vk(t,r),f=uk(t),p=T.useMemo(()=>Dv($v,i),[i]),v=T.useMemo(()=>Nk(p,s),[p,s]),x=v.view?.element??null,I=v.redirectTo??null;return M.jsx(lk,{operator:f,children:M.jsx(Sk,{children:M.jsx(Dk,{children:M.jsx(fk,{readOnly:u,children:M.jsx(Jk,{children:M.jsx(s9,{operator:f,children:M.jsxs($k,{children:[r!==null&&M.jsx(u9,{message:r}),M.jsx(l9,{defaultRedirectTo:I,DefaultViewElement:x,enabledViews:p})]})})})})})})})}function s9({operator:t,children:r}){const{source:i}=Qk(),s=Zb(t,i);return M.jsx(zw,{contributors:s,children:r})}function l9({defaultRedirectTo:t,DefaultViewElement:r,enabledViews:i}){const{pathname:s}=Tn();return M.jsx(kv,{children:M.jsx(T.Suspense,{fallback:null,children:M.jsxs(L0,{children:[M.jsx(an,{path:"/",element:t!==null?M.jsx(D0,{to:t,replace:!0}):r!==null?M.jsx(r,{}):M.jsx(t9,{})}),M.jsx(an,{path:"/agents",element:M.jsx(Yk,{})}),M.jsx(an,{path:"/agents/:slug",element:M.jsx(e9,{})}),M.jsx(an,{path:"/beads",element:M.jsx(n9,{})}),M.jsx(an,{path:"/runs",element:M.jsx(i9,{})}),M.jsx(an,{path:"/runs/:runId",element:M.jsx(r9,{})}),M.jsx(an,{path:"/mail",element:M.jsx(o9,{})}),i.map(u=>{const f=u.element;return M.jsx(an,{path:u.path,element:M.jsx(f,{})},u.id)}),M.jsx(an,{path:"*",element:M.jsx(c9,{})})]})})},s)}function u9({message:t}){return M.jsxs("section",{role:"alert",className:"mb-8 border border-warn/40 rounded-sm px-4 py-3 text-body text-fg-muted",children:[M.jsx("span",{className:"text-warn",children:"config unavailable:"})," ",t," · some controls may be disabled until it loads."]})}function c9(){return M.jsxs("section",{"aria-labelledby":"not-found-title",className:"space-y-3",children:[M.jsx("h1",{id:"not-found-title",className:"text-5xl font-semibold tracking-tight text-fg",children:"Page not found"}),M.jsx("p",{className:"text-title text-fg-muted",children:"No dashboard route matches this path."})]})}const d9={default:"border border-rule text-fg-muted hover:text-fg hover:bg-surface-tint",accent:"border border-accent text-accent hover:bg-accent hover:text-surface",quiet:"border border-transparent text-fg-muted hover:text-fg"},p9={sm:"px-2.5 py-1 text-label uppercase tracking-wider",md:"px-3.5 py-1.5 text-body"};function f9({tone:t="default",size:r="sm",className:i="",children:s,...u}){return M.jsx("button",{...u,className:`inline-flex items-center gap-1.5 rounded-sm transition-colors duration-150 ease-out-quart focus-mark disabled:opacity-40 disabled:cursor-not-allowed ${d9[t]} ${p9[r]} ${i}`,children:s})}const m9="https://docs.gascity.com/getting-started/quickstart",v9=/^\/city\/([^/]+)(?:\/|$)/;function g9(t){const r=v9.exec(t);if(r===null)return null;const i=r[1];if(i===void 0)return null;let s;try{s=decodeURIComponent(i)}catch{return null}return Jm.test(s)?{cityName:s,basename:`/city/${i}`}:null}function h9(){const t=T.useMemo(()=>g9(window.location.pathname),[]),[r,i]=T.useState({phase:"loading"}),[s,u]=T.useState(0),f=T.useCallback(()=>{i({phase:"loading"}),u(p=>p+1)},[]);return T.useEffect(()=>{let p=!1;return i({phase:"loading"}),Qe().listCities().then(v=>{if(p)return;const x=v.items??[];if(t!==null){const w=x.some(b=>b.name===t.cityName);i(w?{phase:"mount"}:{phase:"unknown-city",cities:x});return}const I=x[0];if(I===void 0){i({phase:"empty"});return}window.location.replace(`/city/${encodeURIComponent(I.name)}/`)}).catch(v=>{if(!p){if(t!==null){i({phase:"mount"});return}i({phase:"error",message:v instanceof Error?v.message:"failed to load cities"})}}),()=>{p=!0}},[t,s]),t!==null&&r.phase==="mount"?(tw(t.cityName),M.jsx(X0,{basename:t.basename,future:{v7_relativeSplatPath:!0,v7_startTransition:!0},children:M.jsx(a9,{})})):r.phase==="unknown-city"&&t!==null?M.jsx(y9,{cityName:t.cityName,cities:r.cities}):r.phase==="empty"?M.jsx(_9,{}):r.phase==="error"?M.jsx(x9,{message:r.message,onRetry:f}):M.jsx(Ja,{children:M.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Resolving city…"})})}function Ja({children:t}){return M.jsx("div",{className:"min-h-screen bg-surface text-fg antialiased flex items-center justify-center px-6",children:M.jsx("div",{className:"max-w-prose w-full space-y-4",children:t})})}function y9({cityName:t,cities:r}){return M.jsx(Ja,{children:M.jsxs("section",{role:"alert",className:"space-y-4",children:[M.jsxs("h1",{className:"text-display font-semibold text-fg",children:["City “",t,"” is not registered on this supervisor."]}),r.length>0?M.jsxs("div",{className:"space-y-2",children:[M.jsx("p",{className:"text-body text-fg-muted",children:"Available cities:"}),M.jsx("ul",{className:"space-y-1",children:r.map(i=>M.jsxs("li",{children:[M.jsx("a",{href:`/city/${encodeURIComponent(i.name)}/`,className:"text-body text-accent hover:underline focus-mark",children:i.name}),i.running?null:M.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted ml-2",children:"· stopped"})]},i.name))})]}):M.jsx(qv,{})]})})}function _9(){return M.jsx(Ja,{children:M.jsxs("section",{className:"space-y-4",children:[M.jsx("h1",{className:"text-display font-semibold text-fg",children:"No cities are registered on this supervisor."}),M.jsx(qv,{})]})})}function qv(){return M.jsxs("div",{className:"space-y-3",children:[M.jsx("p",{className:"text-body text-fg-muted",children:"Create one from a terminal:"}),M.jsx("pre",{className:"text-body bg-surface-tint rounded-sm px-3 py-2 overflow-x-auto",children:M.jsx("code",{children:"gc init ~/my-city"})}),M.jsxs("p",{className:"text-body text-fg-muted",children:[M.jsx("code",{children:"gc init"})," bootstraps the city directory, registers it with the supervisor, and starts the orchestrator. Then refresh this page. See the"," ",M.jsx("a",{href:m9,target:"_blank",rel:"noreferrer",className:"text-accent hover:underline focus-mark",children:"getting-started guide"})," ","for the full walkthrough."]})]})}function x9({message:t,onRetry:r}){return M.jsx(Ja,{children:M.jsxs("section",{role:"alert",className:"space-y-4",children:[M.jsx("h1",{className:"text-display font-semibold text-fg",children:"Could not load cities."}),M.jsx("p",{className:"text-body text-fg-muted",children:t}),M.jsx(f9,{onClick:r,children:"Retry"})]})})}const Fv=document.getElementById("root");if(!Fv)throw new Error("missing #root");X2.createRoot(Fv).render(M.jsx(Dm.StrictMode,{children:M.jsx(ak,{children:M.jsx(kv,{children:M.jsx(h9,{})})})}));export{P9 as $,Yo as A,f9 as B,nr as C,B9 as D,I9 as E,wu as F,v3 as G,bk as H,Pv as I,C9 as J,Lt as K,Q0 as L,jc as M,Cm as N,Qk as O,wS as P,Xa as Q,M9 as R,pk as S,E9 as T,yk as U,L9 as V,Pc as W,DS as X,j9 as Y,_3 as Z,y3 as _,Tw as a,N9 as a0,Bv as a1,zv as a2,lr as a3,av as a4,Cw as a5,_w as a6,Yl as a7,R9 as a8,Sn as a9,U9 as aa,$9 as ab,q9 as ac,Ek as ad,d3 as ae,rb as af,ib as ag,SS as ah,En as b,jS as c,BS as d,a3 as e,qk as f,mk as g,z9 as h,Av as i,M as j,T9 as k,_k as l,tb as m,O9 as n,A9 as o,k9 as p,F9 as q,T as r,D9 as s,b9 as t,Z9 as u,Qe as v,pn as w,GE as x,w9 as y,S9 as z}; +Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const p of t.seen.entries()){const v=p[1];if(r===p[0]){f(p);continue}if(t.external){const I=t.external.registry.get(p[0])?.id;if(r!==p[0]&&I){f(p);continue}}if(t.metadataRegistry.get(p[0])?.id){f(p);continue}if(v.cycle){f(p);continue}if(v.count>1&&t.reused==="ref"){f(p);continue}}}function w7(t,r){const i=t.seen.get(r);if(!i)throw new Error("Unprocessed schema. This is a bug in Zod.");const s=v=>{const x=t.seen.get(v);if(x.ref===null)return;const I=x.def??x.schema,w={...I},b=x.ref;if(x.ref=null,b){s(b);const O=t.seen.get(b),L=O.schema;if(L.$ref&&(t.target==="draft-07"||t.target==="draft-04"||t.target==="openapi-3.0")?(I.allOf=I.allOf??[],I.allOf.push(L)):Object.assign(I,L),Object.assign(I,w),v._zod.parent===b)for(const D in I)D==="$ref"||D==="allOf"||D in w||delete I[D];if(L.$ref&&O.def)for(const D in I)D==="$ref"||D==="allOf"||D in O.def&&JSON.stringify(I[D])===JSON.stringify(O.def[D])&&delete I[D]}const C=v._zod.parent;if(C&&C!==b){s(C);const O=t.seen.get(C);if(O?.schema.$ref&&(I.$ref=O.schema.$ref,O.def))for(const L in I)L==="$ref"||L==="allOf"||L in O.def&&JSON.stringify(I[L])===JSON.stringify(O.def[L])&&delete I[L]}t.override({zodSchema:v,jsonSchema:I,path:x.path??[]})};for(const v of[...t.seen.entries()].reverse())s(v[0]);const u={};if(t.target==="draft-2020-12"?u.$schema="https://json-schema.org/draft/2020-12/schema":t.target==="draft-07"?u.$schema="http://json-schema.org/draft-07/schema#":t.target==="draft-04"?u.$schema="http://json-schema.org/draft-04/schema#":t.target,t.external?.uri){const v=t.external.registry.get(r)?.id;if(!v)throw new Error("Schema is missing an `id` property");u.$id=t.external.uri(v)}Object.assign(u,i.def??i.schema);const f=t.metadataRegistry.get(r)?.id;f!==void 0&&u.id===f&&delete u.id;const p=t.external?.defs??{};for(const v of t.seen.entries()){const x=v[1];x.def&&x.defId&&(x.def.id===x.defId&&delete x.def.id,p[x.defId]=x.def)}t.external||Object.keys(p).length>0&&(t.target==="draft-2020-12"?u.$defs=p:u.definitions=p);try{const v=JSON.parse(JSON.stringify(u));return Object.defineProperty(v,"~standard",{value:{...r["~standard"],jsonSchema:{input:Ma(r,"input",t.processors),output:Ma(r,"output",t.processors)}},enumerable:!1,writable:!1}),v}catch{throw new Error("Error converting schema to JSON.")}}function gt(t,r){const i=r??{seen:new Set};if(i.seen.has(t))return!1;i.seen.add(t);const s=t._zod.def;if(s.type==="transform")return!0;if(s.type==="array")return gt(s.element,i);if(s.type==="set")return gt(s.valueType,i);if(s.type==="lazy")return gt(s.getter(),i);if(s.type==="promise"||s.type==="optional"||s.type==="nonoptional"||s.type==="nullable"||s.type==="readonly"||s.type==="default"||s.type==="prefault")return gt(s.innerType,i);if(s.type==="intersection")return gt(s.left,i)||gt(s.right,i);if(s.type==="record"||s.type==="map")return gt(s.keyType,i)||gt(s.valueType,i);if(s.type==="pipe")return t._zod.traits.has("$ZodCodec")?!0:gt(s.in,i)||gt(s.out,i);if(s.type==="object"){for(const u in s.shape)if(gt(s.shape[u],i))return!0;return!1}if(s.type==="union"){for(const u of s.options)if(gt(u,i))return!0;return!1}if(s.type==="tuple"){for(const u of s.items)if(gt(u,i))return!0;return!!(s.rest&>(s.rest,i))}return!1}const I_=(t,r={})=>i=>{const s=I7({...i,processors:r});return Je(t,s),E7(s,t),w7(s,t)},Ma=(t,r,i={})=>s=>{const{libraryOptions:u,target:f}=s??{},p=I7({...u??{},target:f,io:r,processors:i});return Je(t,p),E7(p,t),w7(p,t)},E_={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},w_=(t,r,i,s)=>{const u=i;u.type="string";const{minimum:f,maximum:p,format:v,patterns:x,contentEncoding:I}=t._zod.bag;if(typeof f=="number"&&(u.minLength=f),typeof p=="number"&&(u.maxLength=p),v&&(u.format=E_[v]??v,u.format===""&&delete u.format,v==="time"&&delete u.format),I&&(u.contentEncoding=I),x&&x.size>0){const w=[...x];w.length===1?u.pattern=w[0].source:w.length>1&&(u.allOf=[...w.map(b=>({...r.target==="draft-07"||r.target==="draft-04"||r.target==="openapi-3.0"?{type:"string"}:{},pattern:b.source}))])}},S_=(t,r,i,s)=>{const u=i,{minimum:f,maximum:p,format:v,multipleOf:x,exclusiveMaximum:I,exclusiveMinimum:w}=t._zod.bag;typeof v=="string"&&v.includes("int")?u.type="integer":u.type="number";const b=typeof w=="number"&&w>=(f??Number.NEGATIVE_INFINITY),C=typeof I=="number"&&I<=(p??Number.POSITIVE_INFINITY),O=r.target==="draft-04"||r.target==="openapi-3.0";b?O?(u.minimum=w,u.exclusiveMinimum=!0):u.exclusiveMinimum=w:typeof f=="number"&&(u.minimum=f),C?O?(u.maximum=I,u.exclusiveMaximum=!0):u.exclusiveMaximum=I:typeof p=="number"&&(u.maximum=p),typeof x=="number"&&(u.multipleOf=x)},b_=(t,r,i,s)=>{i.type="boolean"},k_=(t,r,i,s)=>{if(r.unrepresentable==="throw")throw new Error("BigInt cannot be represented in JSON Schema")},B_=(t,r,i,s)=>{i.not={}},z_=(t,r,i,s)=>{},T_=(t,r,i,s)=>{const u=t._zod.def,f=Ym(u.entries);f.every(p=>typeof p=="number")&&(i.type="number"),f.every(p=>typeof p=="string")&&(i.type="string"),i.enum=f},C_=(t,r,i,s)=>{const u=t._zod.def,f=[];for(const p of u.values)if(p===void 0){if(r.unrepresentable==="throw")throw new Error("Literal `undefined` cannot be represented in JSON Schema")}else if(typeof p=="bigint"){if(r.unrepresentable==="throw")throw new Error("BigInt literals cannot be represented in JSON Schema");f.push(Number(p))}else f.push(p);if(f.length!==0)if(f.length===1){const p=f[0];i.type=p===null?"null":typeof p,r.target==="draft-04"||r.target==="openapi-3.0"?i.enum=[p]:i.const=p}else f.every(p=>typeof p=="number")&&(i.type="number"),f.every(p=>typeof p=="string")&&(i.type="string"),f.every(p=>typeof p=="boolean")&&(i.type="boolean"),f.every(p=>p===null)&&(i.type="null"),i.enum=f},R_=(t,r,i,s)=>{if(r.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},N_=(t,r,i,s)=>{if(r.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},P_=(t,r,i,s)=>{const u=i,f=t._zod.def,{minimum:p,maximum:v}=t._zod.bag;typeof p=="number"&&(u.minItems=p),typeof v=="number"&&(u.maxItems=v),u.type="array",u.items=Je(f.element,r,{...s,path:[...s.path,"items"]})},j_=(t,r,i,s)=>{const u=i,f=t._zod.def;u.type="object",u.properties={};const p=f.shape;for(const I in p)u.properties[I]=Je(p[I],r,{...s,path:[...s.path,"properties",I]});const v=new Set(Object.keys(p)),x=new Set([...v].filter(I=>{const w=f.shape[I]._zod;return r.io==="input"?w.optin===void 0:w.optout===void 0}));x.size>0&&(u.required=Array.from(x)),f.catchall?._zod.def.type==="never"?u.additionalProperties=!1:f.catchall?f.catchall&&(u.additionalProperties=Je(f.catchall,r,{...s,path:[...s.path,"additionalProperties"]})):r.io==="output"&&(u.additionalProperties=!1)},A_=(t,r,i,s)=>{const u=t._zod.def,f=u.inclusive===!1,p=u.options.map((v,x)=>Je(v,r,{...s,path:[...s.path,f?"oneOf":"anyOf",x]}));f?i.oneOf=p:i.anyOf=p},O_=(t,r,i,s)=>{const u=t._zod.def,f=Je(u.left,r,{...s,path:[...s.path,"allOf",0]}),p=Je(u.right,r,{...s,path:[...s.path,"allOf",1]}),v=I=>"allOf"in I&&Object.keys(I).length===1,x=[...v(f)?f.allOf:[f],...v(p)?p.allOf:[p]];i.allOf=x},$_=(t,r,i,s)=>{const u=i,f=t._zod.def;u.type="object";const p=f.keyType,x=p._zod.bag?.patterns;if(f.mode==="loose"&&x&&x.size>0){const w=Je(f.valueType,r,{...s,path:[...s.path,"patternProperties","*"]});u.patternProperties={};for(const b of x)u.patternProperties[b.source]=w}else(r.target==="draft-07"||r.target==="draft-2020-12")&&(u.propertyNames=Je(f.keyType,r,{...s,path:[...s.path,"propertyNames"]})),u.additionalProperties=Je(f.valueType,r,{...s,path:[...s.path,"additionalProperties"]});const I=p._zod.values;if(I){const w=[...I].filter(b=>typeof b=="string"||typeof b=="number");w.length>0&&(u.required=w)}},D_=(t,r,i,s)=>{const u=t._zod.def,f=Je(u.innerType,r,s),p=r.seen.get(t);r.target==="openapi-3.0"?(p.ref=u.innerType,i.nullable=!0):i.anyOf=[f,{type:"null"}]},M_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType},L_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType,i.default=JSON.parse(JSON.stringify(u.defaultValue))},q_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType,r.io==="input"&&(i._prefault=JSON.parse(JSON.stringify(u.defaultValue)))},F_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType;let p;try{p=u.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}i.default=p},U_=(t,r,i,s)=>{const u=t._zod.def,f=u.in._zod.traits.has("$ZodTransform"),p=r.io==="input"?f?u.out:u.in:u.out;Je(p,r,s);const v=r.seen.get(t);v.ref=p},Z_=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType,i.readOnly=!0},S7=(t,r,i,s)=>{const u=t._zod.def;Je(u.innerType,r,s);const f=r.seen.get(t);f.ref=u.innerType},V_=$("ZodISODateTime",(t,r)=>{Zh.init(t,r),Ve.init(t,r)});function k(t){return Ky(V_,t)}const W_=$("ZodISODate",(t,r)=>{Vh.init(t,r),Ve.init(t,r)});function G_(t){return Jy(W_,t)}const H_=$("ZodISOTime",(t,r)=>{Wh.init(t,r),Ve.init(t,r)});function X_(t){return Qy(H_,t)}const K_=$("ZodISODuration",(t,r)=>{Gh.init(t,r),Ve.init(t,r)});function J_(t){return Yy(K_,t)}const Q_=(t,r)=>{o7.init(t,r),t.name="ZodError",Object.defineProperties(t,{format:{value:i=>A3(t,i)},flatten:{value:i=>j3(t,i)},addIssue:{value:i=>{t.issues.push(i),t.message=JSON.stringify(t.issues,su,2)}},addIssues:{value:i=>{t.issues.push(...i),t.message=JSON.stringify(t.issues,su,2)}},isEmpty:{get(){return t.issues.length===0}}})},qt=$("ZodError",Q_,{Parent:Error}),Y_=zu(qt),e8=Tu(qt),t8=Za(qt),n8=Va(qt),o8=D3(qt),r8=M3(qt),i8=L3(qt),a8=q3(qt),s8=F3(qt),l8=U3(qt),u8=Z3(qt),c8=V3(qt),cm=new WeakMap;function ui(t,r,i){const s=Object.getPrototypeOf(t);let u=cm.get(s);if(u||(u=new Set,cm.set(s,u)),!u.has(r)){u.add(r);for(const f in i){const p=i[f];Object.defineProperty(s,f,{configurable:!0,enumerable:!1,get(){const v=p.bind(this);return Object.defineProperty(this,f,{configurable:!0,writable:!0,enumerable:!0,value:v}),v},set(v){Object.defineProperty(this,f,{configurable:!0,writable:!0,enumerable:!0,value:v})}})}}}const Le=$("ZodType",(t,r)=>(De.init(t,r),Object.assign(t["~standard"],{jsonSchema:{input:Ma(t,"input"),output:Ma(t,"output")}}),t.toJSONSchema=I_(t,{}),t.def=r,t.type=r.type,Object.defineProperty(t,"_def",{value:r}),t.parse=(i,s)=>Y_(t,i,s,{callee:t.parse}),t.safeParse=(i,s)=>t8(t,i,s),t.parseAsync=async(i,s)=>e8(t,i,s,{callee:t.parseAsync}),t.safeParseAsync=async(i,s)=>n8(t,i,s),t.spa=t.safeParseAsync,t.encode=(i,s)=>o8(t,i,s),t.decode=(i,s)=>r8(t,i,s),t.encodeAsync=async(i,s)=>i8(t,i,s),t.decodeAsync=async(i,s)=>a8(t,i,s),t.safeEncode=(i,s)=>s8(t,i,s),t.safeDecode=(i,s)=>l8(t,i,s),t.safeEncodeAsync=async(i,s)=>u8(t,i,s),t.safeDecodeAsync=async(i,s)=>c8(t,i,s),ui(t,"ZodType",{check(...i){const s=this.def;return this.clone(oo(s,{checks:[...s.checks??[],...i.map(u=>typeof u=="function"?{_zod:{check:u,def:{check:"custom"},onattach:[]}}:u)]}),{parent:!0})},with(...i){return this.check(...i)},clone(i,s){return ro(this,i,s)},brand(){return this},register(i,s){return i.add(this,s),this},refine(i,s){return this.check(t5(i,s))},superRefine(i,s){return this.check(n5(i,s))},overwrite(i){return this.check(dr(i))},optional(){return mm(this)},exactOptional(){return F8(this)},nullable(){return vm(this)},nullish(){return mm(vm(this))},nonoptional(i){return H8(this,i)},array(){return y(this)},or(i){return un([this,i])},and(i){return $8(this,i)},transform(i){return gm(this,L8(i))},default(i){return V8(this,i)},prefault(i){return G8(this,i)},catch(i){return K8(this,i)},pipe(i){return gm(this,i)},readonly(){return Y8(this)},describe(i){const s=this.clone();return ti.add(s,{description:i}),s},meta(...i){if(i.length===0)return ti.get(this);const s=this.clone();return ti.add(s,i[0]),s},isOptional(){return this.safeParse(void 0).success},isNullable(){return this.safeParse(null).success},apply(i){return i(this)}}),Object.defineProperty(t,"description",{get(){return ti.get(t)?.description},configurable:!0}),t)),b7=$("_ZodString",(t,r)=>{Cu.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(s,u,f)=>w_(t,s,u);const i=t._zod.bag;t.format=i.format??null,t.minLength=i.minimum??null,t.maxLength=i.maximum??null,ui(t,"_ZodString",{regex(...s){return this.check(a_(...s))},includes(...s){return this.check(u_(...s))},startsWith(...s){return this.check(c_(...s))},endsWith(...s){return this.check(d_(...s))},min(...s){return this.check(Da(...s))},max(...s){return this.check(_7(...s))},length(...s){return this.check(x7(...s))},nonempty(...s){return this.check(Da(1,...s))},lowercase(s){return this.check(s_(s))},uppercase(s){return this.check(l_(s))},trim(){return this.check(f_())},normalize(...s){return this.check(p_(...s))},toLowerCase(){return this.check(m_())},toUpperCase(){return this.check(v_())},slugify(){return this.check(g_())}})}),d8=$("ZodString",(t,r)=>{Cu.init(t,r),b7.init(t,r),t.email=i=>t.check(Cy(p8,i)),t.url=i=>t.check(y7(k7,i)),t.jwt=i=>t.check(Xy(B8,i)),t.emoji=i=>t.check(Ay(f8,i)),t.guid=i=>t.check(um(dm,i)),t.uuid=i=>t.check(Ry(za,i)),t.uuidv4=i=>t.check(Ny(za,i)),t.uuidv6=i=>t.check(Py(za,i)),t.uuidv7=i=>t.check(jy(za,i)),t.nanoid=i=>t.check(Oy(m8,i)),t.guid=i=>t.check(um(dm,i)),t.cuid=i=>t.check($y(v8,i)),t.cuid2=i=>t.check(Dy(g8,i)),t.ulid=i=>t.check(My(h8,i)),t.base64=i=>t.check(Wy(S8,i)),t.base64url=i=>t.check(Gy(b8,i)),t.xid=i=>t.check(Ly(y8,i)),t.ksuid=i=>t.check(qy(_8,i)),t.ipv4=i=>t.check(Fy(x8,i)),t.ipv6=i=>t.check(Uy(I8,i)),t.cidrv4=i=>t.check(Zy(E8,i)),t.cidrv6=i=>t.check(Vy(w8,i)),t.e164=i=>t.check(Hy(k8,i)),t.datetime=i=>t.check(k(i)),t.date=i=>t.check(G_(i)),t.time=i=>t.check(X_(i)),t.duration=i=>t.check(J_(i))});function e(t){return Ty(d8,t)}const Ve=$("ZodStringFormat",(t,r)=>{Me.init(t,r),b7.init(t,r)}),p8=$("ZodEmail",(t,r)=>{Ah.init(t,r),Ve.init(t,r)}),dm=$("ZodGUID",(t,r)=>{Ph.init(t,r),Ve.init(t,r)}),za=$("ZodUUID",(t,r)=>{jh.init(t,r),Ve.init(t,r)}),k7=$("ZodURL",(t,r)=>{Oh.init(t,r),Ve.init(t,r)});function pm(t){return y7(k7,t)}const f8=$("ZodEmoji",(t,r)=>{$h.init(t,r),Ve.init(t,r)}),m8=$("ZodNanoID",(t,r)=>{Dh.init(t,r),Ve.init(t,r)}),v8=$("ZodCUID",(t,r)=>{Mh.init(t,r),Ve.init(t,r)}),g8=$("ZodCUID2",(t,r)=>{Lh.init(t,r),Ve.init(t,r)}),h8=$("ZodULID",(t,r)=>{qh.init(t,r),Ve.init(t,r)}),y8=$("ZodXID",(t,r)=>{Fh.init(t,r),Ve.init(t,r)}),_8=$("ZodKSUID",(t,r)=>{Uh.init(t,r),Ve.init(t,r)}),x8=$("ZodIPv4",(t,r)=>{Hh.init(t,r),Ve.init(t,r)}),I8=$("ZodIPv6",(t,r)=>{Xh.init(t,r),Ve.init(t,r)}),E8=$("ZodCIDRv4",(t,r)=>{Kh.init(t,r),Ve.init(t,r)}),w8=$("ZodCIDRv6",(t,r)=>{Jh.init(t,r),Ve.init(t,r)}),S8=$("ZodBase64",(t,r)=>{Qh.init(t,r),Ve.init(t,r)}),b8=$("ZodBase64URL",(t,r)=>{ey.init(t,r),Ve.init(t,r)}),k8=$("ZodE164",(t,r)=>{ty.init(t,r),Ve.init(t,r)}),B8=$("ZodJWT",(t,r)=>{oy.init(t,r),Ve.init(t,r)}),B7=$("ZodNumber",(t,r)=>{f7.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(s,u,f)=>S_(t,s,u),ui(t,"ZodNumber",{gt(s,u){return this.check($a(s,u))},gte(s,u){return this.check(Jn(s,u))},min(s,u){return this.check(Jn(s,u))},lt(s,u){return this.check(Oa(s,u))},lte(s,u){return this.check(tr(s,u))},max(s,u){return this.check(tr(s,u))},int(s){return this.check(Ue(s))},safe(s){return this.check(Ue(s))},positive(s){return this.check($a(0,s))},nonnegative(s){return this.check(Jn(0,s))},negative(s){return this.check(Oa(0,s))},nonpositive(s){return this.check(tr(0,s))},multipleOf(s,u){return this.check(uu(s,u))},step(s,u){return this.check(uu(s,u))},finite(){return this}});const i=t._zod.bag;t.minValue=Math.max(i.minimum??Number.NEGATIVE_INFINITY,i.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,t.maxValue=Math.min(i.maximum??Number.POSITIVE_INFINITY,i.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,t.isInt=(i.format??"").includes("int")||Number.isSafeInteger(i.multipleOf??.5),t.isFinite=!0,t.format=i.format??null});function pt(t){return e_(B7,t)}const z8=$("ZodNumberFormat",(t,r)=>{ry.init(t,r),B7.init(t,r)});function Ue(t){return t_(z8,t)}const T8=$("ZodBoolean",(t,r)=>{iy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>b_(t,i,s)});function R(t){return n_(T8,t)}const C8=$("ZodBigInt",(t,r)=>{ay.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(s,u,f)=>k_(t,s),t.gte=(s,u)=>t.check(Jn(s,u)),t.min=(s,u)=>t.check(Jn(s,u)),t.gt=(s,u)=>t.check($a(s,u)),t.gte=(s,u)=>t.check(Jn(s,u)),t.min=(s,u)=>t.check(Jn(s,u)),t.lt=(s,u)=>t.check(Oa(s,u)),t.lte=(s,u)=>t.check(tr(s,u)),t.max=(s,u)=>t.check(tr(s,u)),t.positive=s=>t.check($a(BigInt(0),s)),t.negative=s=>t.check(Oa(BigInt(0),s)),t.nonpositive=s=>t.check(tr(BigInt(0),s)),t.nonnegative=s=>t.check(Jn(BigInt(0),s)),t.multipleOf=(s,u)=>t.check(uu(s,u));const i=t._zod.bag;t.minValue=i.minimum??null,t.maxValue=i.maximum??null,t.format=i.format??null}),R8=$("ZodUnknown",(t,r)=>{sy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>z_()});function no(){return r_(R8)}const N8=$("ZodNever",(t,r)=>{ly.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>B_(t,i,s)});function Ga(t){return i_(N8,t)}const P8=$("ZodArray",(t,r)=>{uy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>P_(t,i,s,u),t.element=r.element,ui(t,"ZodArray",{min(i,s){return this.check(Da(i,s))},nonempty(i){return this.check(Da(1,i))},max(i,s){return this.check(_7(i,s))},length(i,s){return this.check(x7(i,s))},unwrap(){return this.element}})});function y(t,r){return h_(P8,t,r)}const j8=$("ZodObject",(t,r)=>{dy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>j_(t,i,s,u),ze(t,"shape",()=>r.shape),ui(t,"ZodObject",{keyof(){return me(Object.keys(this._zod.def.shape))},catchall(i){return this.clone({...this._zod.def,catchall:i})},passthrough(){return this.clone({...this._zod.def,catchall:no()})},loose(){return this.clone({...this._zod.def,catchall:no()})},strict(){return this.clone({...this._zod.def,catchall:Ga()})},strip(){return this.clone({...this._zod.def,catchall:void 0})},extend(i){return z3(this,i)},safeExtend(i){return T3(this,i)},merge(i){return C3(this,i)},pick(i){return k3(this,i)},omit(i){return B3(this,i)},partial(...i){return R3(T7,this,i[0])},required(...i){return N3(C7,this,i[0])}})});function c(t,r){const i={type:"object",shape:t??{},...ie(r)};return new j8(i)}const z7=$("ZodUnion",(t,r)=>{g7.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>A_(t,i,s,u),t.options=r.options});function un(t,r){return new z7({type:"union",options:t,...ie(r)})}const A8=$("ZodDiscriminatedUnion",(t,r)=>{z7.init(t,r),py.init(t,r)});function pr(t,r,i){return new A8({type:"union",options:r,discriminator:t,...ie(i)})}const O8=$("ZodIntersection",(t,r)=>{fy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>O_(t,i,s,u)});function $8(t,r){return new O8({type:"intersection",left:t,right:r})}const fm=$("ZodRecord",(t,r)=>{my.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>$_(t,i,s,u),t.keyType=r.keyType,t.valueType=r.valueType});function fe(t,r,i){return!r||!r._zod?new fm({type:"record",keyType:e(),valueType:t,...ie(r)}):new fm({type:"record",keyType:t,valueType:r,...ie(i)})}const cu=$("ZodEnum",(t,r)=>{vy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(s,u,f)=>T_(t,s,u),t.enum=r.entries,t.options=Object.values(r.entries);const i=new Set(Object.keys(r.entries));t.extract=(s,u)=>{const f={};for(const p of s)if(i.has(p))f[p]=r.entries[p];else throw new Error(`Key ${p} not found in enum`);return new cu({...r,checks:[],...ie(u),entries:f})},t.exclude=(s,u)=>{const f={...r.entries};for(const p of s)if(i.has(p))delete f[p];else throw new Error(`Key ${p} not found in enum`);return new cu({...r,checks:[],...ie(u),entries:f})}});function me(t,r){const i=Array.isArray(t)?Object.fromEntries(t.map(s=>[s,s])):t;return new cu({type:"enum",entries:i,...ie(r)})}const D8=$("ZodLiteral",(t,r)=>{gy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>C_(t,i,s),t.values=new Set(r.values),Object.defineProperty(t,"value",{get(){if(r.values.length>1)throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");return r.values[0]}})});function g(t,r){return new D8({type:"literal",values:Array.isArray(t)?t:[t],...ie(r)})}const M8=$("ZodTransform",(t,r)=>{hy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>N_(t,i),t._zod.parse=(i,s)=>{if(s.direction==="backward")throw new Qm(t.constructor.name);i.addIssue=f=>{if(typeof f=="string")i.issues.push(si(f,i.value,r));else{const p=f;p.fatal&&(p.continue=!1),p.code??(p.code="custom"),p.input??(p.input=i.value),p.inst??(p.inst=t),i.issues.push(si(p))}};const u=r.transform(i.value,i);return u instanceof Promise?u.then(f=>(i.value=f,i.fallback=!0,i)):(i.value=u,i.fallback=!0,i)}});function L8(t){return new M8({type:"transform",transform:t})}const T7=$("ZodOptional",(t,r)=>{h7.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>S7(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function mm(t){return new T7({type:"optional",innerType:t})}const q8=$("ZodExactOptional",(t,r)=>{yy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>S7(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function F8(t){return new q8({type:"optional",innerType:t})}const U8=$("ZodNullable",(t,r)=>{_y.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>D_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function vm(t){return new U8({type:"nullable",innerType:t})}const Z8=$("ZodDefault",(t,r)=>{xy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>L_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType,t.removeDefault=t.unwrap});function V8(t,r){return new Z8({type:"default",innerType:t,get defaultValue(){return typeof r=="function"?r():t7(r)}})}const W8=$("ZodPrefault",(t,r)=>{Iy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>q_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function G8(t,r){return new W8({type:"prefault",innerType:t,get defaultValue(){return typeof r=="function"?r():t7(r)}})}const C7=$("ZodNonOptional",(t,r)=>{Ey.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>M_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function H8(t,r){return new C7({type:"nonoptional",innerType:t,...ie(r)})}const X8=$("ZodCatch",(t,r)=>{wy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>F_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType,t.removeCatch=t.unwrap});function K8(t,r){return new X8({type:"catch",innerType:t,catchValue:typeof r=="function"?r:()=>r})}const J8=$("ZodPipe",(t,r)=>{Sy.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>U_(t,i,s,u),t.in=r.in,t.out=r.out});function gm(t,r){return new J8({type:"pipe",in:t,out:r})}const Q8=$("ZodReadonly",(t,r)=>{by.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>Z_(t,i,s,u),t.unwrap=()=>t._zod.def.innerType});function Y8(t){return new Q8({type:"readonly",innerType:t})}const e5=$("ZodCustom",(t,r)=>{ky.init(t,r),Le.init(t,r),t._zod.processJSONSchema=(i,s,u)=>R_(t,i)});function t5(t,r={}){return y_(e5,t,r)}function n5(t,r){return __(t,r)}function h(t){return o_(C8,t)}const o5=c({MaxMessageLength:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),SupportsAttachments:R(),SupportsChildConversations:R()}),ci=c({account_id:e(),provider:e()});c({dir:e().optional(),name:e().min(1),provider:e().min(1),scope:e().optional()});c({agent:e(),status:e()});const r5=c({agent_id:e(),parent_tool_use_id:e()});c({dir:e().optional(),env:fe(e(),e()).optional(),name:e().optional(),provider:e().optional(),scope:e().optional(),suspended:R().optional(),tmux_alias:e().optional(),work_dir:e().optional()});c({provider:e().optional(),scope:e().optional(),suspended:R().optional()});c({provider:e().optional(),scope:e().optional(),suspended:R().optional()});const i5=c({dir:e().optional(),is_pool:R().optional(),name:e(),origin:e(),provider:e().optional(),scope:e().optional(),suspended:R()}),a5=c({acp_args:y(e()).optional(),acp_command:e().optional(),args:y(e()).nullish(),command:e().optional(),display_name:e().optional(),env:fe(e(),e()).optional(),origin:e(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({event_cursor:e(),request_id:e(),status:e()});c({event_cursor:e(),request_id:e()});c({assignee:e().optional()});const Ru=c({attempted_claimant:e(),bead_id:e(),existing_claimant:e()});c({assignee:e().optional(),defer_until:k().optional(),description:e().optional(),labels:y(e()).nullish(),metadata:fe(e(),e()).optional(),parent:e().optional(),priority:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),rig:e().optional(),title:e().min(1),type:e().optional()});const Nu=c({bead_id:e(),dead_assignee:e().optional(),routed_to:e().optional()});c({assignee:e().optional(),description:e().optional(),labels:y(e()).nullish(),metadata:fe(e(),e()).optional(),parent:e().nullish(),priority:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),remove_labels:y(e()).nullish(),status:e().optional(),title:e().optional(),type:e().optional()});const Pu=c({bead_id:e(),path:e(),reason:e(),rig:e()}),ju=c({bead_id:e(),branch:e(),path:e(),rig:e()}),s5=c({beads_store:e(),degraded:R().optional(),gc_bd_inflight:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),native_store_eligible:R(),preflight_gate:e().optional(),preflight_reason:e().optional()}),l5=me(["active","ended"]),Au=c({agent_name:e().optional(),conversation_id:e(),provider:e(),session_id:e()}),Ou=c({backoff_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),failures:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),from:e(),op_class:e(),scope:e(),to:e()});c({bootstrap_profile:me(["k8s-cell","kubernetes","kubernetes-cell","single-host-compat"]).optional(),dir:e().min(1),provider:e().min(1).optional(),start_command:e().optional()});const $u=c({name:e(),path:e(),request_id:e()});c({agent_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),name:e(),path:e(),provider:e().optional(),rig_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_template:e().optional(),suspended:R(),uptime_sec:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),version:e().optional()});const u5=c({error:e().optional(),name:e(),path:e(),phases_completed:y(e()).nullish(),running:R(),status:e().optional()}),di=c({name:e(),path:e()});c({suspended:R().optional()});const c5=c({kind:e(),request_id:e(),session_id:e()}),Du=c({name:e(),path:e(),request_id:e()}),Mu=c({bd_version:e().optional(),mode:e(),origin:e(),reason:e(),store_id:e(),store_kind:e()}),d5=c({dir:e().optional(),is_pool:R().optional(),name:e(),provider:e().optional(),scope:e().optional(),suspended:R()}),p5=c({agents:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),providers:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),rigs:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({agents:y(i5).nullable(),patches:p5,providers:fe(e(),a5)});const f5=c({agent_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),provider_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),rig_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),m5=c({name:e(),path:e(),prefix:e().optional(),suspended:R()});c({errors:y(e()).nullable(),valid:R(),warnings:y(e()).nullable()});const Lu=c({duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),phase:e(),threshold_breach:R().optional()});c({GroupID:e(),Handle:e(),ID:e(),Metadata:fe(e(),e()),Public:R(),SessionID:e(),SessionName:e()});const v5=me(["dm","room","thread"]),Yt=c({account_id:e(),conversation_id:e(),kind:v5,parent_conversation_id:e().optional(),provider:e(),scope_id:e()});c({items:y(e()).nullish()});c({closed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),complete:R(),convoy_id:e(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({items:y(e()).nullish(),rig:e().optional(),title:e().min(1)});const g5=c({closed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({items:y(e()).nullish()});const h5=c({BindingGeneration:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),Conversation:Yt,ID:e(),LastMessageID:e(),LastPublishedAt:k(),Metadata:fe(e(),e()),SchemaVersion:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),SessionID:e(),SourceSessionID:e()}),y5=c({depends_on_id:e(),issue_id:e(),type:e()}),xo=c({assignee:e().optional(),created_at:k(),defer_until:k().optional(),dependencies:y(y5).nullish(),description:e().optional(),ephemeral:R().optional(),from:e().optional(),id:e(),is_blocked:R().optional(),issue_type:e(),labels:y(e()).nullish(),metadata:fe(e(),e()).optional(),needs:y(e()).nullish(),no_history:R().optional(),parent:e().optional(),priority:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),ref:e().optional(),status:e(),title:e(),updated_at:k().optional()});c({children:y(xo).nullable()});const Cn=c({bead:xo});c({children:y(xo).nullish(),convoy:xo.optional(),progress:g5.optional()});const qu=c({check:e(),city:e().optional(),detail:e(),subject:e().optional()}),_5=c({location:e().optional(),message:e().optional(),value:no().optional()});c({code:e().optional(),detail:e().optional(),errors:y(_5).nullish(),instance:pm().optional(),status:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),title:e().optional(),type:pm().optional().default("about:blank")});c({status:e()});c({actor:e().min(1),message:e().optional(),subject:e().optional(),type:e().min(1)});const x5=c({seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),ts:k(),type:e()}),I5=c({compression_status:me(["pending","complete"]),first_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),last_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),path:e()});c({anchor_event:x5.optional(),archive:I5.optional(),reason:e().optional(),rotated:R()});c({account_id:e().min(1),callback_url:e().optional(),capabilities:o5.optional(),name:e().optional(),provider:e().min(1)});c({account_id:e(),name:e(),provider:e(),status:e()});c({account_id:e().min(1),provider:e().min(1)});c({agent_name:e().optional(),conversation:Yt.optional(),metadata:fe(e(),e()).optional(),replace:R().optional(),session_id:e().optional()});c({default_handle:e().optional(),metadata:fe(e(),e()).optional(),mode:e().optional(),root_conversation:Yt.optional()});c({conversation:Yt.optional(),idempotency_key:e().optional(),reply_to_message_id:e().optional(),session_id:e().min(1),text:e().optional()});c({group_id:e().min(1),handle:e().min(1)});c({group_id:e().min(1),handle:e().min(1),metadata:fe(e(),e()).optional(),public:R().optional(),session_id:e().min(1)});c({conversation:Yt.optional(),sequence:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),session_id:e().min(1)});c({agent_name:e().optional(),conversation:Yt.optional(),session_id:e().optional()});const R7=c({display_name:e(),id:e(),is_bot:R()}),N7=c({mime_type:e(),provider_id:e(),url:e()}),P7=c({actor:R7,attachments:y(N7).nullish(),conversation:Yt,dedup_key:e().optional(),explicit_target:e().optional(),provider_message_id:e(),received_at:k(),reply_to_message_id:e().optional(),text:e()});c({account_id:e().optional(),message:P7.optional(),payload:e().optional(),provider:e().optional()});const E5=c({account_id:e(),name:e(),provider:e()}),w5=c({AllowUntargetedPublication:R(),Enabled:R(),MaxPeerTriggeredPublishes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),MaxTotalPeerDeliveries:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({DefaultHandle:e(),FanoutPolicy:w5,ID:e(),LastAddressedHandle:e(),Metadata:fe(e(),e()),Mode:e(),RootConversation:Yt,SchemaVersion:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({scope_kind:e().optional(),scope_ref:e().optional(),target:e().min(1),vars:fe(e(),e()).optional()});const j7=c({from:e(),kind:e().optional(),to:e()}),S5=c({id:e(),kind:e(),scope_ref:e().optional(),title:e()}),b5=c({edges:y(j7).nullable(),nodes:y(S5).nullable()}),A7=c({started_at:e(),status:e(),target:e(),updated_at:e(),workflow_id:e()});c({formula:e(),partial:R(),partial_errors:y(e()).nullish(),recent_runs:y(A7).nullable(),run_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({name:e(),source:e()});const k5=c({assignee:e().optional(),id:e(),kind:e(),labels:y(e()).nullish(),metadata:fe(e(),e()).optional(),title:e(),type:e().optional()});c({errors:y(e()).nullish(),valid:R()});const O7=c({default:no().optional(),description:e().optional(),enum:y(e()).nullish(),name:e(),pattern:e().optional(),required:R().optional(),type:e()});c({deps:y(j7).nullable(),description:e(),name:e(),preview:b5,steps:y(k5).nullable(),var_defs:y(O7).nullable()});const B5=c({description:e(),name:e(),recent_runs:y(A7).nullable(),run_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),var_defs:y(O7).nullable()});c({items:y(B5).nullable(),partial:R(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const z5=c({ahead:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),behind:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),branch:e(),changed_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),clean:R()}),Fu=c({conversation_id:e(),mode:e(),provider:e()}),T5=c({Match:e(),TargetSessionID:e(),UpdateCursor:R()});c({city:e().optional(),status:e(),uptime_sec:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),version:e().optional()});const fr=c({timestamp:e()}),Uu=c({actor:e(),conversation_id:e(),provider:e(),target_agent:e().optional(),target_session:e()});c({items:y(xo).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({items:y(c5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({items:y(E5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const C5=fe(e(),Ga());c({partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),unread:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({body:e().optional(),from:e().optional(),subject:e().optional()});c({body:e().optional(),from:e().optional(),rig:e().optional(),subject:e().min(1),to:e().min(1)});const du=c({after_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),before_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),duration_s:pt(),err:e().optional(),finished_at:e(),snapshot_path:e().optional(),stage:e(),started_at:e()});c({enabled:R(),history:y(du).nullable(),in_flight:R(),in_flight_start:e().optional(),interval_seconds:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),last_run:du.optional(),next_scheduled:e().optional()});c({accepted:R(),run:du.optional(),started_at:e().optional()});const $7=c({body:e(),cc:y(e()).nullish(),created_at:k(),from:e(),id:e(),priority:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),read:R(),reply_to:e().optional(),rig:e().optional(),subject:e(),thread_id:e().optional(),to:e()}),ht=c({message:$7.optional(),rig:e()});c({items:y($7).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const Zu=c({actor:e(),close_reason:e().optional(),from_status:e(),issue_id:e(),session_id:e().optional(),session_name:e().optional(),to_status:e(),ts:k(),work_dir:e().optional()}),D7=c({attached_bead_id:e().optional(),bead_id:e().optional(),detail_available:R().optional(),id:e(),logical_bead_id:e().optional(),root_bead_id:e().optional(),root_store_ref:e().optional(),run_detail_available:R().optional(),scope_kind:e(),scope_ref:e(),started_at:e(),status:e(),store_ref:e().optional(),target:e(),title:e(),type:e(),updated_at:e(),workflow_id:e().optional()});c({items:y(D7).nullable(),partial:R(),partial_errors:y(e()).nullish()});const de=fe(e(),Ga());c({status:e()});c({id:e().optional(),status:e()});const R5=c({label:e(),value:e()}),N5=c({due:R(),last_run:e().optional(),last_run_outcome:e().optional(),name:e(),reason:e(),rig:e().optional(),scoped_name:e()});c({checks:y(N5).nullable()});const Vu=c({elapsed_s:pt(),order:e(),scope:e().optional()});c({bead_id:e(),created_at:e(),labels:y(e()).nullable(),output:e(),store_ref:e()});const P5=c({bead_id:e(),capture_output:R(),created_at:e(),duration_ms:e().optional(),error:e().optional(),exit_code:e().optional(),has_output:R(),labels:y(e()).nullable(),name:e(),rig:e().optional(),scoped_name:e(),signal:e().optional(),store_ref:e(),wisp_root_id:e().optional()});c({entries:y(P5).nullable()});const j5=c({capture_output:R(),check:e().optional(),check_timeout:e().optional(),check_timeout_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),description:e().optional(),enabled:R(),env:fe(e(),e()).optional(),exec:e().optional(),formula:e().optional(),gate:e().optional(),interval:e().optional(),name:e(),on:e().optional(),pool:e().optional(),rig:e().optional(),schedule:e().optional(),scoped_name:e(),timeout:e().optional(),timeout_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),trigger:e().optional(),type:e()});c({orders:y(j5).nullable()});c({vars:fe(e(),e()).optional()});c({scoped_name:e().optional(),status:e(),tracking_id:e().optional()});c({items:y(D7).nullable(),partial:R(),partial_errors:y(e()).nullish()});const Wu=c({conversation_id:e(),owner_session:e(),posting_session:e(),provider:e()}),Gu=c({conversation_id:e(),message_id:e(),provider:e(),session:e()}),Hu=c({role:e(),text:e(),timestamp:e().optional()});c({name:e().optional(),source:e().min(1),version:e().optional()});c({git_backed:R(),name:e(),source:e(),version:e().optional()});c({name:e()});const A5=c({name:e(),source:e().optional(),version:e().optional()});c({packs:y(A5).nullable()});const So=c({has_newer_messages:R().optional(),has_older_messages:R(),returned_message_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total_compactions:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total_message_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),truncated_before_message:e().optional()}),M7=c({agent:e(),format:e(),pagination:So.optional(),turns:y(Hu).nullable()});c({agent_patch:e().optional(),provider_patch:e().optional(),rig_patch:e().optional(),status:e()});c({agent_patch:e().optional(),provider_patch:e().optional(),rig_patch:e().optional(),status:e()});const Xu=c({kind:e(),metadata:fe(e(),e()).optional(),options:y(e()).nullish(),prompt:e().optional(),request_id:e()}),O5=c({Check:e().nullable(),DrainTimeout:e().nullable(),Max:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),Min:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),OnBoot:e().nullable(),OnDeath:e().nullable()}),$5=c({AppendFragments:y(e()).nullable(),Args:y(e()).nullable(),AssignedWorkDeferLimit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),Attach:R().nullable(),DefaultSlingFormula:e().nullable(),DependsOn:y(e()).nullable(),Dir:e(),Env:fe(e(),e()),EnvRemove:y(e()).nullable(),HooksInstalled:R().nullable(),IdleTimeout:e().nullable(),InjectAssignedSkills:R().nullable(),InjectFragments:y(e()).nullable(),InjectFragmentsAppend:y(e()).nullable(),InstallAgentHooks:y(e()).nullable(),InstallAgentHooksAppend:y(e()).nullable(),Lifecycle:e().nullable(),MCP:y(e()).nullable(),MCPAppend:y(e()).nullable(),MaxActiveSessions:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),MaxSessionAge:e().nullable(),MaxSessionAgeJitter:e().nullable(),MinActiveSessions:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),MouseMode:e().nullable(),Name:e(),Nudge:e().nullable(),OptionDefaults:fe(e(),e()),OverlayDir:e().nullable(),Pool:O5,PreStart:y(e()).nullable(),PreStartAppend:y(e()).nullable(),PromptTemplate:e().nullable(),Provider:e().nullable(),ResumeCommand:e().nullable(),ScaleCheck:e().nullable(),Scope:e().nullable(),Session:e().nullable(),SessionLive:y(e()).nullable(),SessionLiveAppend:y(e()).nullable(),SessionSetup:y(e()).nullable(),SessionSetupAppend:y(e()).nullable(),SessionSetupScript:e().nullable(),Skills:y(e()).nullable(),SkillsAppend:y(e()).nullable(),SleepAfterIdle:e().nullable(),StartCommand:e().nullable(),Suspended:R().nullable(),Tier:e().nullable(),TmuxAlias:e().nullable(),Upstream:e().nullable(),WakeMode:e().nullable(),WorkDir:e().nullable()});c({items:y($5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const Ku=c({host:e(),port:e(),scope_kind:e(),scope_name:e(),source:e(),user:e()}),Ju=c({layer:e(),new_id:e(),old_id:e().optional(),scope_root:e(),source:e()});c({acp_args:y(e()).nullish(),acp_command:e().optional(),args:y(e()).nullish(),args_append:y(e()).nullish(),base:e().optional(),command:e().optional(),display_name:e().optional(),env:fe(e(),e()).optional(),name:e().min(1),option_defaults:fe(e(),e()).optional(),options_schema_merge:e().optional(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({provider:e(),status:e()});const D5=c({choices:y(R5).nullable(),default:e(),key:e(),label:e(),type:e()}),M5=c({ACPArgs:y(e()).nullable(),ACPCommand:e().nullable(),AcceptStartupDialogs:R().nullable(),Args:y(e()).nullable(),ArgsAppend:y(e()).nullable(),Base:e().nullable(),Command:e().nullable(),Env:fe(e(),e()),EnvRemove:y(e()).nullable(),Name:e(),OptionsSchemaMerge:e().nullable(),PromptFlag:e().nullable(),PromptMode:e().nullable(),ReadyDelayMs:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).nullable(),Replace:R()});c({items:y(M5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({accept_startup_dialogs:R().optional(),acp_args:y(e()).nullish(),acp_command:e().optional(),args:y(e()).nullish(),command:e().optional(),env:fe(e(),e()).optional(),name:e().optional(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});const L5=c({builtin:R(),city_level:R(),display_name:e().optional(),effective_defaults:fe(e(),e()).optional(),name:e(),options_schema:y(D5).nullish()});c({items:y(L5).nullable(),next_cursor:e().optional(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const q5=c({detail:e().optional(),display_name:e(),status:e()});c({providers:fe(e(),q5)});const F5=c({acp_args:y(e()).optional(),acp_command:e().optional(),args:y(e()).nullish(),builtin:R(),city_level:R(),command:e().optional(),display_name:e().optional(),env:fe(e(),e()).optional(),name:e(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({items:y(F5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const U5=c({acp_args:y(e()).optional(),acp_command:e().optional(),args:y(e()).nullish(),command:e().optional(),display_name:e().optional(),env:fe(e(),e()).optional(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({acp_args:y(e()).nullish(),acp_command:e().optional(),args:y(e()).nullish(),args_append:y(e()).nullish(),base:e().optional(),command:e().optional(),display_name:e().optional(),env:fe(e(),e()).optional(),option_defaults:fe(e(),e()).optional(),options_schema_merge:e().optional(),prompt_flag:e().optional(),prompt_mode:e().optional(),ready_delay_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});const Qu=c({pids_signaled:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),quarantine_dir:e(),rate_limited:R().optional(),scope:e()}),Z5=c({Conversation:Yt,Delivered:R(),FailureKind:e(),MessageID:e(),Metadata:fe(e(),e()),RetryAfter:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),Yu=c({five_hour_resets_at:e().optional(),five_hour_util:pt(),opus_util:pt().optional(),provider:e(),seven_day_resets_at:e().optional(),seven_day_util:pt(),sonnet_util:pt().optional()}),ec=c({provider:e(),reason_class:e()}),V5=c({detail:e().optional(),display_name:e(),kind:e(),name:e(),status:e()});c({items:fe(e(),V5)});const pi=c({actor:e(),created_at:k(),hostname:e().optional(),id:e(),message:e(),metadata:fe(e(),e()).optional(),ref_bead:e().optional(),severity:e(),source_path:e().optional(),source_pid:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),tc=c({error_code:e(),error_message:e(),operation:me(["city.create","city.unregister","session.create","session.message","session.submit","rig.create"]),request_id:e()});c({action:e(),failed:y(e()).nullish(),killed:y(e()).nullish(),rig:e(),status:e()});c({default_branch:e().optional(),git_url:e().optional(),name:e().min(1),path:e().optional(),prefix:e().optional(),request_id:e().optional()});c({default_branch:e().optional(),event_cursor:e().optional(),prefix:e().optional(),request_id:e().optional(),rig:e().optional(),status:me(["created","accepted","exists"])});const nc=c({default_branch:e(),prefix:e(),request_id:e(),rig:e()}),W5=c({DefaultBranch:e().nullable(),FormulaVars:fe(e(),e()),Name:e(),Path:e().nullable(),Prefix:e().nullable(),Suspended:R().nullable(),SuspendedOnStart:R().nullable()});c({items:y(W5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({default_branch:e().optional(),name:e().optional(),path:e().optional(),prefix:e().optional(),suspended:R().optional()});const oc=c({detail:e().optional(),request_id:e().optional(),rig:e(),step:e(),warn:R().optional()}),G5=c({agent_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),default_branch:e().optional(),git:z5.optional(),last_activity:k().optional(),name:e(),path:e(),prefix:e().optional(),running_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),suspended:R()});c({items:y(G5).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({default_branch:e().optional(),path:e().optional(),prefix:e().optional(),suspended:R().optional()});const rc=c({prior_archive:e(),prior_first_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),prior_last_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),H5=c({code:e(),message:e().optional()}),X5=c({kind:e().optional(),ref:e().optional()}),ic=me(["pending","active","waiting","canceling","completed","failed","canceled","skipped"]),K5=c({formula:e().optional(),last_error:H5.optional(),run_id:e(),scope:X5,started_at:e().optional(),status:ic,target:e().optional(),title:e(),updated_at:e().optional()});c({closed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),run_id:e(),status:ic});const J5=c({kind:me(["sling","order"]),run_id:e(),status:ic}),L7=c({active:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),canceled:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),canceling:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),completed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),failed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),pending:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),skipped:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),waiting:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),Q5=me(["pending","active","blocked","completed","failed","skipped","canceled"]),Y5=c({assignee:e().optional(),id:e(),kind:e().optional(),status:Q5,title:e()});c({run_id:e(),steps:y(Y5).nullable()});c({partial:R().optional(),partial_errors:y(e()).nullish(),status_counts:L7});c({partial:R().optional(),partial_errors:y(e()).nullish(),runs:y(K5).nullable(),status_counts:L7});const ex=fe(e(),Ga());c({action:e(),service:e(),status:e()});const q7=c({activity:e()});c({messages:y(no()).nullable(),status:e().optional()});c({agents:y(r5).nullable()});const ac=c({AgentName:e(),BindingGeneration:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),BoundAt:k(),Conversation:Yt,ExpiresAt:k().nullable(),ID:e(),Metadata:fe(e(),e()),SchemaVersion:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),SessionID:e(),SessionName:e(),Status:l5});c({unbound:y(ac).nullable()});c({items:y(ac).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({alias:e().optional(),async:R().optional(),kind:e().optional(),message:e().optional(),name:e().optional(),options:fe(e(),e()).optional(),project_id:e().optional(),session_name:e().optional(),title:e().optional()});const sc=c({bead_id:e(),bead_status:e().optional(),reason:e().optional(),session_id:e(),template:e().optional()}),tx=c({attached:R(),last_activity:k().optional(),name:e()}),nx=c({active_bead:e().optional(),activity:e().optional(),available:R(),context_pct:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_window:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),description:e().optional(),display_name:e().optional(),last_output:e().optional(),model:e().optional(),name:e(),pack:e().optional(),pack_derived:R(),pool:e().optional(),provider:e().optional(),rig:e().optional(),running:R(),session:tx.optional(),state:e(),suspended:R(),unavailable_reason:e().optional()});c({items:y(nx).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const bo=c({reason:e().optional(),session_id:e(),template:e().optional()});c({message:e().min(1).regex(/\S/)});const lc=c({request_id:e(),session_id:e()});c({alias:e().optional(),title:e().min(1).optional()});const F7=c({request_id:e()});c({pending:Xu.optional(),supported:R()});c({permission_mode:e().min(1).regex(/\S/)});const U7=no();c({title:e().min(1)});const uc=c({elapsed_s:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),reset_committed_at:e(),session_name:e(),template:e()});c({action:e().min(1),metadata:fe(e(),e()).optional(),request_id:e().optional(),text:e().optional()});c({id:e(),status:e()});const cc=c({session_id:e(),session_name:e().optional(),template:e().optional(),work_bead_ids:y(e()).nullish()});un([q7,Xu,F7,fr]);const ox=c({format:e(),id:e(),pagination:So.optional(),provider:e(),template:e(),turns:y(Hu).nullable()}),rx=c({format:e(),id:e(),messages:y(U7).nullable(),pagination:So.optional(),provider:e(),template:e()}),cn=c({name:e(),value:e()}),ix=c({file_path:e().optional(),image_url:e().optional(),mime_type:e().optional(),text:e().optional(),type:g("image")}),ax=c({text:e().optional(),type:g("text")}),sx=c({signature:e().optional(),thinking:e().optional(),type:g("thinking")}),lx=c({compaction_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),has_branches:R().optional(),note:e().optional(),status:e()}),ux=c({after_entry_id:e().optional(),resume_token:e()}),cx=c({code:e(),count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),message:e().optional()}),dx=c({id:e(),observed_at:e().optional()}),px=c({text:e().optional()}),Z7=c({action:e().optional(),kind:e().optional(),options:y(e()).nullish(),prompt:e().optional(),request_id:e().optional(),state:e()}),fx=c({interaction:Z7.optional(),type:g("interaction")}),dc=c({file_path:e().optional(),lines:y(e()).nullish(),new_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),new_start:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),old_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),old_start:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),Ha=c({status:e().optional(),step:e().optional()}),mx=c({description:e().optional(),label:e().optional()}),V7=c({header:e().optional(),multi_select:R().optional(),options:y(mx).nullish(),question:e().optional()}),pc=c({snippet:e().optional(),title:e().optional(),url:e().optional()}),W7=c({category:e().optional(),code:e().optional(),kind:e().optional(),message:e().optional()}),vx=c({activity:e(),degraded:R().optional(),degraded_reason:e().optional(),last_entry_id:e().optional(),open_tool_call_ids:y(e()).nullish(),pending_interaction_ids:y(e()).nullish()}),G7=c({continuity:lx,cursor:ux,diagnostics:y(cx).nullish(),gc_session_id:e().optional(),generation:dx,logical_conversation_id:e().optional(),provider_session_id:e().optional(),tail_state:vx,transcript_stream_id:e()}),sr=c({active_form:e().optional(),content:e().optional(),id:e().optional(),priority:e().optional(),status:e().optional()}),ft=c({category:me(["user_rejection","user_rejection_with_reason","command_failure","file_error","validation_error","timeout","network_error","unknown"]),message:e().optional(),user_reason:e().optional()}),gx=c({arguments:y(cn),kind:g("arguments")}),hx=c({code:e(),kind:g("code"),language:e().optional()}),yx=c({arguments:y(cn).nullish(),command:e(),kind:g("command")}),_x=c({kind:g("fetch"),prompt:e().optional(),url:e().optional()}),xx=c({command:e().optional(),file_path:e(),kind:g("file"),language:e().optional()}),Ix=c({arguments:y(cn).nullish(),file_path:e().optional(),kind:g("glob"),pattern:e().optional(),query:e().optional()}),Ex=c({file_path:e().optional(),kind:g("patch"),language:e().optional(),patch:e()}),wx=c({explanation:e().optional(),kind:g("plan"),plan:e().optional(),steps:y(Ha).nullish()}),Sx=c({kind:g("question"),options:y(e()).nullish(),question:e().optional()}),bx=c({arguments:y(cn).nullish(),command:e().optional(),file_path:e().optional(),kind:g("search"),pattern:e().optional(),query:e().optional()}),kx=c({kind:g("stdin"),linked_command:e().optional(),task_id:e().optional(),text:e().optional()}),Bx=c({description:e().optional(),kind:g("task"),prompt:e().optional(),task_id:e().optional(),task_status:e().optional(),task_type:e().optional()}),zx=c({kind:g("text"),text:e()}),Tx=c({kind:g("todo"),todos:y(sr).nullish()}),Cx=c({arguments:y(cn).nullish(),code:e().optional(),command:e().optional(),description:e().optional(),explanation:e().optional(),file_path:e().optional(),kind:g("unknown"),language:e().optional(),linked_command:e().optional(),options:y(e()).nullish(),patch:e().optional(),pattern:e().optional(),plan:e().optional(),prompt:e().optional(),query:e().optional(),question:e().optional(),steps:y(Ha).nullish(),task_id:e().optional(),task_status:e().optional(),task_type:e().optional(),text:e().optional(),todos:y(sr).nullish(),url:e().optional()}),Rx=c({file_path:e().optional(),kind:g("write"),language:e().optional(),text:e().optional()}),H7=pr("kind",[Cx.extend({kind:g("unknown")}),yx.extend({kind:g("command")}),kx.extend({kind:g("stdin")}),hx.extend({kind:g("code")}),Ex.extend({kind:g("patch")}),Rx.extend({kind:g("write")}),Ix.extend({kind:g("glob")}),_x.extend({kind:g("fetch")}),bx.extend({kind:g("search")}),xx.extend({kind:g("file")}),Tx.extend({kind:g("todo")}),wx.extend({kind:g("plan")}),Sx.extend({kind:g("question")}),Bx.extend({kind:g("task")}),zx.extend({kind:g("text")}),gx.extend({kind:g("arguments")})]),Nx=c({file_path:e().optional(),id:e().optional(),input:H7.optional(),name:e().optional(),type:g("tool_use")}),Px=c({command:e().optional(),content:e().optional(),error:ft.optional(),exit_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),interrupted:R().optional(),is_image:R().optional(),kind:g("bash"),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),stderr:e().optional(),stderr_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),stdout:e().optional(),stdout_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),task_id:e().optional(),task_status:e().optional(),text:e().optional(),timestamp:e().optional(),truncated:R().optional()}),jx=c({content:e().optional(),error:ft.optional(),file_path:e().optional(),file_paths:y(e()).nullish(),kind:g("edit"),new_string:e().optional(),old_string:e().optional(),original_file:e().optional(),patch:e().optional(),patch_hunks:y(dc).nullish(),replace_all:R().optional(),user_modified:R().optional()}),Ax=c({bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),content:e().optional(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),kind:g("fetch"),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),status_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),status_text:e().optional(),text:e().optional(),url:e().optional()}),Ox=c({content:e().optional(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),filenames:y(e()).nullish(),kind:g("glob"),num_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),truncated:R().optional()}),$x=c({applied_limit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),content:e().optional(),counts:y(cn).nullish(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),filenames:y(e()).nullish(),kind:g("grep"),mode:e().optional(),num_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_results:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),query:e().optional(),result_items:y(pc).nullish()}),Dx=c({content:e().optional(),error:ft.optional(),explanation:e().optional(),kind:g("plan"),plan:e().optional(),steps:y(Ha).nullish(),text:e().optional()}),Mx=c({code:e().optional(),error:ft.optional(),exit_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),interrupted:R().optional(),is_image:R().optional(),kind:g("python"),stderr:e().optional(),stdout:e().optional(),text:e().optional(),truncated:R().optional()}),Lx=c({answer:e().optional(),answers:y(cn).nullish(),content:e().optional(),error:ft.optional(),kind:g("question"),options:y(e()).nullish(),question:e().optional(),questions:y(V7).nullish(),text:e().optional()}),qx=c({content:e().optional(),error:ft.optional(),file_path:e().optional(),kind:g("read"),language:e().optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),start_line:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),Fx=c({applied_limit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),content:e().optional(),counts:y(cn).nullish(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),filenames:y(e()).nullish(),kind:g("search"),mode:e().optional(),num_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_results:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),query:e().optional(),result_items:y(pc).nullish()}),Ux=c({content:e().optional(),error:ft.optional(),kind:g("stdin"),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),task_id:e().optional(),text:e().optional()}),Zx=c({content:e().optional(),description:e().optional(),error:ft.optional(),exit_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),kind:g("task"),output:e().optional(),stderr:e().optional(),stdout:e().optional(),task_id:e().optional(),task_status:e().optional(),task_type:e().optional(),text:e().optional(),total_duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_tool_use_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),Vx=c({content:e().optional(),error:ft.optional(),kind:g("text"),text:e().optional()}),Wx=c({content:e().optional(),error:ft.optional(),kind:g("todo"),new_todos:y(sr).nullish(),old_todos:y(sr).nullish(),text:e().optional()}),Gx=c({answer:e().optional(),answers:y(cn).nullish(),applied_limit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),code:e().optional(),command:e().optional(),content:e().optional(),counts:y(cn).nullish(),description:e().optional(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),error:ft.optional(),exit_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),explanation:e().optional(),file_path:e().optional(),file_paths:y(e()).nullish(),filenames:y(e()).nullish(),interrupted:R().optional(),is_image:R().optional(),kind:g("unknown"),language:e().optional(),mode:e().optional(),new_string:e().optional(),new_todos:y(sr).nullish(),num_files:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),num_results:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),old_string:e().optional(),old_todos:y(sr).nullish(),options:y(e()).nullish(),original_file:e().optional(),output:e().optional(),patch:e().optional(),patch_hunks:y(dc).nullish(),plan:e().optional(),query:e().optional(),question:e().optional(),questions:y(V7).nullish(),replace_all:R().optional(),result_items:y(pc).nullish(),start_line:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),status_code:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),status_text:e().optional(),stderr:e().optional(),stderr_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),stdout:e().optional(),stdout_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),steps:y(Ha).nullish(),task_id:e().optional(),task_status:e().optional(),task_type:e().optional(),text:e().optional(),timestamp:e().optional(),total_duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),total_tool_use_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),truncated:R().optional(),url:e().optional(),user_modified:R().optional()}),Hx=c({content:e().optional(),error:ft.optional(),file_path:e().optional(),file_paths:y(e()).nullish(),kind:g("write"),language:e().optional(),num_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),patch:e().optional(),patch_hunks:y(dc).nullish(),start_line:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),text:e().optional(),total_lines:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),X7=pr("kind",[Gx.extend({kind:g("unknown")}),Px.extend({kind:g("bash")}),Mx.extend({kind:g("python")}),qx.extend({kind:g("read")}),Ox.extend({kind:g("glob")}),$x.extend({kind:g("grep")}),Fx.extend({kind:g("search")}),Ax.extend({kind:g("fetch")}),Wx.extend({kind:g("todo")}),Dx.extend({kind:g("plan")}),Lx.extend({kind:g("question")}),Ux.extend({kind:g("stdin")}),Zx.extend({kind:g("task")}),Hx.extend({kind:g("write")}),jx.extend({kind:g("edit")}),Vx.extend({kind:g("text")})]),Xx=c({content:e().optional(),file_path:e().optional(),is_error:R().optional(),name:e().optional(),structured:X7.optional(),tool_call_id:e().optional(),type:g("tool_result")}),Kx=c({content:e().optional(),file_path:e().optional(),id:e().optional(),image_url:e().optional(),input:H7.optional(),interaction:Z7.optional(),is_error:R().optional(),mime_type:e().optional(),name:e().optional(),signature:e().optional(),structured:X7.optional(),text:e().optional(),thinking:e().optional(),tool_call_id:e().optional(),type:g("unknown")}),fi=pr("type",[ax.extend({type:g("text")}),sx.extend({type:g("thinking")}),Nx.extend({type:g("tool_use")}),Xx.extend({type:g("tool_result")}),fx.extend({type:g("interaction")}),ix.extend({type:g("image")}),Kx.extend({type:g("unknown")})]),Jx=c({blocks:y(fi),id:e(),provider:e().optional(),role:g("system"),status:me(["unknown","final","partial","superseded"]),system_event:W7.optional(),timestamp:e().optional()}),Qx=c({blocks:y(fi),id:e(),provider:e().optional(),role:g("tool"),status:me(["unknown","final","partial","superseded"]),timestamp:e().optional()}),Yx=c({file_path:e().optional(),mime_type:e().optional(),original_name:e().optional(),preview_url:e().optional(),size:e().optional()}),K7=c({cache_creation_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),cache_read_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_percent:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_used_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_window_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),input_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),output_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),reasoning_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),e4=c({blocks:y(fi),id:e(),model:e().optional(),provider:e().optional(),role:g("assistant"),status:me(["unknown","final","partial","superseded"]),stop_reason:e().optional(),timestamp:e().optional(),usage:K7.optional()}),J7=c({opened_files:y(e()).nullish(),selections:y(px).nullish(),text:e().optional(),uploaded_files:y(Yx).nullish()}),t4=c({blocks:y(fi),id:e(),model:e().optional(),provider:e().optional(),role:g("unknown"),status:me(["unknown","final","partial","superseded"]),stop_reason:e().optional(),system_event:W7.optional(),timestamp:e().optional(),usage:K7.optional(),user_prompt:J7.optional()}),n4=c({blocks:y(fi),id:e(),provider:e().optional(),role:g("user"),status:me(["unknown","final","partial","superseded"]),timestamp:e().optional(),user_prompt:J7.optional()}),Q7=pr("role",[t4.extend({role:g("unknown")}),n4.extend({role:g("user")}),e4.extend({role:g("assistant")}),Jx.extend({role:g("system")}),Qx.extend({role:g("tool")})]),Y7=c({format:g("structured"),history:G7,id:e(),operation:me(["snapshot","upsert","reset"]),pagination:So.optional(),provider:e(),reset_reason:me(["resume_invalid","stream_changed","cursor_invalidated","history_rewritten"]).optional(),schema_version:g("session.structured.v1"),structured_messages:y(Q7),template:e()}),fc=c({intent:e(),queued:R(),request_id:e(),session_id:e()}),o4=c({format:me(["conversation","text"]),id:e(),pagination:So.optional(),provider:e(),template:e(),turns:y(Hu).nullish()}),r4=c({format:me(["raw"]),id:e(),messages:y(U7).nullable(),pagination:So.optional(),provider:e(),template:e()}),i4=c({format:g("structured"),history:G7,id:e(),operation:g("snapshot"),pagination:So.optional(),provider:e(),schema_version:g("session.structured.v1"),structured_messages:y(Q7),template:e()});un([c({format:un([g("conversation"),g("text")])}).and(o4),c({format:g("raw")}).and(r4),c({format:g("structured")}).and(i4)]);const mc=c({escalated:R(),first_seen:e().optional(),session_id:e(),session_name:e().optional(),state:e()});c({attached_bead_id:e().optional(),bead:e().optional(),force:R().optional(),formula:e().optional(),merge:e().optional(),no_convoy:R().optional(),no_formula:R().optional(),owned:R().optional(),reassign:R().optional(),rig:e().optional(),scope_kind:e().optional(),scope_ref:e().optional(),target:e().min(1),title:e().optional(),vars:fe(e(),e()).optional()});c({attached_bead_id:e().optional(),bead:e().optional(),dashboard_url:e().optional(),formula:e().optional(),mode:e().optional(),root_bead_id:e().optional(),run:J5.optional(),status:e(),target:e(),warnings:y(e()).nullish(),workflow_id:e().optional()});const a4=c({allow_websockets:R().optional(),hostname:e().optional(),kind:e().optional(),local_state:e(),mount_path:e(),publication_state:e(),publish_mode:e(),reason:e().optional(),service_name:e(),state:e().optional(),state_root:e(),updated_at:k(),url:e().optional(),visibility:e().optional(),workflow_contract:e().optional()});c({items:y(a4).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const s4=c({quarantined:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),running:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),suspended:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),l4=c({draining:R().optional(),expanded:R().optional(),group_name:e().optional(),name:e(),qualified_name:e(),running:R(),scale_label:e().optional(),scope:e(),session_name:e().optional(),suspended:R()}),u4=c({capable:R(),kind:e(),latch:me(["incapable","unlatched"]),probe:me(["capable","incapable","unprobed"]),reason:e().optional(),store_id:e()}),c4=c({total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),unread:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),d4=c({identity:e(),mode:e(),status:e()}),p4=c({suspended:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),f4=c({name:e(),path:e(),suspended:R()}),m4=c({config_value:e().optional(),env_value:e().optional(),env_var:e().optional(),flag_key:e(),kind:e(),message:e()}),v4=c({effective:me(["off","active","degraded","fail_closed","pending_restart"]),mode:me(["off","auto","require"]),notices:y(m4).nullish(),origin:me(["builtin","config","env"]),stores:y(u4).nullish()}),g4=c({active:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),suspended:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),h4=c({last_gc_at:e().optional(),last_gc_status:e().optional(),live_rows:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),path:e(),ratio_mb_per_row:pt(),size_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),threshold_mb_per_row:pt(),warning:R()}),y4=c({in_progress:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),open:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),ready:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({agent_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),agent_details:y(l4).nullish(),agents:s4,beads:s5.optional(),beads_version:e().optional(),conditional_writes:v4.optional(),dolt_version:e().optional(),mail:c4,name:e(),named_session_details:y(d4).nullish(),partial:R().optional(),partial_errors:y(e()).nullish(),path:e(),rig_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),rig_details:y(f4).nullish(),rigs:p4,running:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_counts_detail:g4.optional(),store_health:h4.optional(),suspended:R(),uptime_sec:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),version:e().optional(),work:y4});const vc=c({class:e(),consecutive_fails:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),reason:e().optional(),scope:e()}),gc=c({data_dir:e(),floor_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),free_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),hc=c({data_dir:e(),floor_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),free_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),warn_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),yc=c({after_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),before_bytes:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),duration_s:pt(),snapshot_path:e()}),_c=c({duration_s:pt(),error_msg:e(),snapshot_path:e().optional(),stage:e()}),xc=c({probe:e(),reason:e().optional(),scope:e()}),Ic=c({class:e().optional(),scope:e()}),_4=c({supports_follow_up:R(),supports_interrupt_now:R()}),ev=c({active_bead:e().optional(),activity:e().optional(),agent_kind:e().optional(),alias:e().optional(),attached:R(),configured_named_session:R().optional(),context_pct:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),context_window:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),created_at:e(),display_name:e().optional(),id:e(),kind:e().optional(),last_active:e().optional(),last_nudge_delivered_at:e().optional(),last_output:e().optional(),metadata:fe(e(),e()).optional(),model:e().optional(),options:fe(e(),e()).optional(),pool:e().optional(),provider:e(),reason:e().optional(),rig:e().optional(),running:R(),session_name:e(),state:e(),submission_capabilities:_4.optional(),template:e(),title:e(),work_dir:e().optional()});c({items:y(ev).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const Ec=c({request_id:e(),session:ev}),x4=me(["default","follow_up","interrupt_now"]);c({intent:x4.optional(),message:e().min(1).regex(/\S/)});c({items:y(u5).nullable(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const wc=c({avg60:pt(),consecutive_skips:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),max_consecutive_skips:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),outcome:e(),threshold:pt(),trigger:e().optional()}),Sc=c({duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),host:e().optional(),method:e(),origin_allowed:R(),path:e(),phase:me(["start","complete"]),remote_addr_class:me(["loopback","private","public","unknown"]),request_id:e().optional(),status:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),bc=c({client_addr:e().optional(),mode:me(["destructive","preserve_sessions","unknown"]),signal:e().optional(),source:me(["signal","socket_stop"])}),kc=c({previous_exit:me(["clean","crash","unknown"])}),I4=c({phase:e().optional(),phases_completed:y(e()).nullish(),ready:R()});c({build_id:e().optional(),cities_running:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cities_total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),packs_lock_sha256:e().optional(),startup:I4.optional(),status:e(),uptime_sec:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),version:e()});const E4=me(["inbound","outbound"]),w4=me(["live","hydrated"]),Bc=c({Actor:R7,Attachments:y(N7).nullable(),Conversation:Yt,CreatedAt:k(),ExplicitTarget:e(),ID:e(),Kind:E4,Metadata:fe(e(),e()),Provenance:w4,ProviderMessageID:e(),ReplyToMessageID:e(),SchemaVersion:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),Sequence:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),SourceSessionID:e(),Text:e()});c({Binding:ac,GroupRoute:T5,Message:P7,TargetAgentName:e(),TargetSessionID:e(),TranscriptEntry:Bc});c({items:y(Bc).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({DeliveryContext:h5,Receipt:Z5,TranscriptEntry:Bc});const zc=c({count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e()}),S4=c({cache_creation_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cache_read_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cost_usd_estimate:pt(),input_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),output_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session:e(),session_id:e().optional(),unpriced:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})}),Jl=c({cache_creation_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cache_read_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),compute_facts:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),cost_usd_estimate:pt(),input_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),invocations:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),output_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),unpriced:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),wall_seconds:pt()});c({available:R(),last_24h:Jl.optional(),observed_from:e().optional(),partial:R().optional(),partial_reasons:y(e()).nullish(),recent:Jl,recent_by_session:y(S4).nullish(),recent_window_secs:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),recording:R(),source:me(["local_estimate","unavailable"]),today:Jl,updated_at:e()});const b4=c({created_at:e().optional(),delivery_attempt:e().optional(),dep_ids:y(e()).nullish(),dep_mode:e().optional(),expires_at:e().optional(),id:e(),kind:e(),labels:y(e()).nullish(),note:e().optional(),nudge_id:e().optional(),registered_epoch:e().optional(),session_id:e(),session_name:e().optional(),state:e(),status:e()});c({capped:R(),partial:R().optional(),partial_errors:y(e()).nullish(),waits:y(b4).nullable()});const Tc=c({body_size:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),dedup_id:e().optional(),deduped:R(),dispatched:R(),event_type:e().optional(),matched:R(),order:e().optional(),rig:e().optional(),rule_index:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),scheme:e().optional(),scoped_name:e().optional(),tracking_id:e().optional(),webhook:e()}),Cc=c({body_size:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),dedup_id:e().optional(),event_type:e().optional(),reason:e(),scheme:e().optional(),status:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),webhook:e()}),Rc=c({agent_name:e().optional(),bead_id:e().optional(),cache_creation_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),cache_read_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),completion_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),cost_usd_estimate:pt().optional(),delivered:R().optional(),duration_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),error:e().optional(),finished_at:k(),latency_ms:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),model:e().optional(),op_id:e(),operation:e(),prompt_sha:e().optional(),prompt_tokens:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),prompt_version:e().optional(),provider:e().optional(),queued:R().optional(),result:e(),run_id:e().optional(),session_id:e().optional(),session_name:e().optional(),started_at:k(),template:e().optional(),transport:e().optional(),unpriced:R().optional()}),tv=un([ci,Ru,Nu,Cn,Pu,ju,Au,Ou,$u,di,Du,Mu,Lu,qu,Fu,Uu,ht,Zu,de,Vu,Wu,Gu,Ku,Ju,Qu,Yu,ec,pi,tc,nc,oc,rc,Ec,sc,bo,lc,uc,cc,fc,mc,vc,gc,hc,yc,_c,xc,Ic,wc,Sc,bc,kc,zc,Tc,Cc,Rc]),k4=c({active_attempt:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),attempt_count:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),max_attempts:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()}),nv=c({assignee:e().optional(),attempt:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),id:e(),kind:e(),logical_bead_id:e().optional(),metadata:fe(e(),e()),scope_ref:e().optional(),status:e(),step_ref:e().optional(),title:e()});c({closed:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),deleted:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),partial:R().optional(),partial_errors:y(e()).nullish(),workflow_id:e()});const pu=c({from:e(),kind:e().optional(),to:e()});c({beads:y(xo).nullable(),deps:y(pu).nullable(),root:xo});const z=c({attempt_summary:k4.optional(),bead:nv,changed_fields:y(e()).nullable(),event_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),event_ts:e(),event_type:e(),logical_node_id:e(),requires_resync:R().optional(),root_bead_id:e(),root_store_ref:e(),scope_kind:e(),scope_ref:e(),type:e(),watch_generation:e(),workflow_id:e(),workflow_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:tv.optional(),run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:e(),workflow:z.optional()});c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:tv.optional(),run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:e(),workflow:z.optional()});const B4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ru,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.claim_rejected"),workflow:z.optional()}),z4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.closed"),workflow:z.optional()}),T4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.created"),workflow:z.optional()}),C4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Nu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.dead_assignee_reopened"),workflow:z.optional()}),R4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.deleted"),workflow:z.optional()}),N4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.updated"),workflow:z.optional()}),P4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Pu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.worktree.reap_skipped"),workflow:z.optional()}),j4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ju,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.worktree.reaped"),workflow:z.optional()}),A4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Mu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("beads.conditional_writes.degraded"),workflow:z.optional()}),O4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ou,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("breaker.state_changed"),workflow:z.optional()}),$4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:di,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.created"),workflow:z.optional()}),D4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.resumed"),workflow:z.optional()}),M4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.suspended"),workflow:z.optional()}),L4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:di,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.unregister_requested"),workflow:z.optional()}),q4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.started"),workflow:z.optional()}),F4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.stopped"),workflow:z.optional()}),U4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Lu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.tick_completed"),workflow:z.optional()}),Z4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("convoy.closed"),workflow:z.optional()}),V4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("convoy.created"),workflow:z.optional()}),W4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:no(),run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:e(),workflow:z.optional()}),G4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:qu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("doctor.alert"),workflow:z.optional()}),H4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:pi,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("emergency.acked"),workflow:z.optional()}),X4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:pi,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("emergency.signaled"),workflow:z.optional()}),K4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:rc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("events.rotated"),workflow:z.optional()}),J4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.step_completed"),workflow:z.optional()}),Q4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.step_defined"),workflow:z.optional()}),Y4=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.step_started"),workflow:z.optional()}),e6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.work_associated"),workflow:z.optional()}),t6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ci,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.adapter_added"),workflow:z.optional()}),n6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ci,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.adapter_removed"),workflow:z.optional()}),o6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Au,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.bound"),workflow:z.optional()}),r6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Fu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.group_created"),workflow:z.optional()}),i6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Uu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.inbound"),workflow:z.optional()}),a6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Gu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.outbound"),workflow:z.optional()}),s6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Wu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.outbound_channel_mismatch"),workflow:z.optional()}),l6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:zc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.unbound"),workflow:z.optional()}),u6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:gc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.disk_critical"),workflow:z.optional()}),c6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:hc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.disk_warn"),workflow:z.optional()}),d6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:yc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.maintenance.done"),workflow:z.optional()}),p6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:_c,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.maintenance.failed"),workflow:z.optional()}),f6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.archived"),workflow:z.optional()}),m6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.deleted"),workflow:z.optional()}),v6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.marked_read"),workflow:z.optional()}),g6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.marked_unread"),workflow:z.optional()}),h6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.read"),workflow:z.optional()}),y6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.replied"),workflow:z.optional()}),_6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.sent"),workflow:z.optional()}),x6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Zu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("molecule.resolved"),workflow:z.optional()}),I6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.completed"),workflow:z.optional()}),E6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.failed"),workflow:z.optional()}),w6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.fired"),workflow:z.optional()}),S6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Vu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.gate_timeout_fail_open"),workflow:z.optional()}),b6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ku,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("pg.credential_resolved"),workflow:z.optional()}),k6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ju,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("project.identity.stamped"),workflow:z.optional()}),B6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Yu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.quota_observed"),workflow:z.optional()}),z6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ec,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.quota_poll_failed"),workflow:z.optional()}),T6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.swapped"),workflow:z.optional()}),C6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Qu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("proxy.reaped"),workflow:z.optional()}),R6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:tc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.failed"),workflow:z.optional()}),N6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:$u,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.city.create"),workflow:z.optional()}),P6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Du,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.city.unregister"),workflow:z.optional()}),j6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:nc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.rig.create"),workflow:z.optional()}),A6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ec,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.create"),workflow:z.optional()}),O6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:lc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.message"),workflow:z.optional()}),$6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.submit"),workflow:z.optional()}),D6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:oc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("rig.provision.progress"),workflow:z.optional()}),M6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.cold_start_timeout"),workflow:z.optional()}),L6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.crashed"),workflow:z.optional()}),q6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:sc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.drain_acked_with_assigned_work"),workflow:z.optional()}),F6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.draining"),workflow:z.optional()}),U6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.idle_killed"),workflow:z.optional()}),Z6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.max_age_killed"),workflow:z.optional()}),V6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.quarantined"),workflow:z.optional()}),W6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:uc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.reset_stalled"),workflow:z.optional()}),G6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.stopped"),workflow:z.optional()}),H6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:cc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.stranded"),workflow:z.optional()}),X6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.suspended"),workflow:z.optional()}),K6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.undrained"),workflow:z.optional()}),J6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:mc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.unknown_state"),workflow:z.optional()}),Q6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.updated"),workflow:z.optional()}),Y6=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.woke"),workflow:z.optional()}),eI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.work_query_failed"),workflow:z.optional()}),tI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:vc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.degraded"),workflow:z.optional()}),nI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:xc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.probe_failed"),workflow:z.optional()}),oI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ic,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.recovered"),workflow:z.optional()}),rI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:wc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.fs_pressure.skipped_tick"),workflow:z.optional()}),iI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Sc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.request"),workflow:z.optional()}),aI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.shutdown_requested"),workflow:z.optional()}),sI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:kc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.started"),workflow:z.optional()}),lI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Tc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("webhook.received"),workflow:z.optional()}),uI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("webhook.rejected"),workflow:z.optional()}),cI=c({actor:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Rc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("worker.operation"),workflow:z.optional()}),ov=pr("type",[B4.extend({type:g("bead.claim_rejected")}),z4.extend({type:g("bead.closed")}),T4.extend({type:g("bead.created")}),C4.extend({type:g("bead.dead_assignee_reopened")}),R4.extend({type:g("bead.deleted")}),N4.extend({type:g("bead.updated")}),P4.extend({type:g("bead.worktree.reap_skipped")}),j4.extend({type:g("bead.worktree.reaped")}),A4.extend({type:g("beads.conditional_writes.degraded")}),O4.extend({type:g("breaker.state_changed")}),$4.extend({type:g("city.created")}),D4.extend({type:g("city.resumed")}),M4.extend({type:g("city.suspended")}),L4.extend({type:g("city.unregister_requested")}),q4.extend({type:g("controller.started")}),F4.extend({type:g("controller.stopped")}),U4.extend({type:g("controller.tick_completed")}),Z4.extend({type:g("convoy.closed")}),V4.extend({type:g("convoy.created")}),G4.extend({type:g("doctor.alert")}),H4.extend({type:g("emergency.acked")}),X4.extend({type:g("emergency.signaled")}),K4.extend({type:g("events.rotated")}),J4.extend({type:g("execution.step_completed")}),Q4.extend({type:g("execution.step_defined")}),Y4.extend({type:g("execution.step_started")}),e6.extend({type:g("execution.work_associated")}),t6.extend({type:g("extmsg.adapter_added")}),n6.extend({type:g("extmsg.adapter_removed")}),o6.extend({type:g("extmsg.bound")}),r6.extend({type:g("extmsg.group_created")}),i6.extend({type:g("extmsg.inbound")}),a6.extend({type:g("extmsg.outbound")}),s6.extend({type:g("extmsg.outbound_channel_mismatch")}),l6.extend({type:g("extmsg.unbound")}),u6.extend({type:g("gc.store.disk_critical")}),c6.extend({type:g("gc.store.disk_warn")}),d6.extend({type:g("gc.store.maintenance.done")}),p6.extend({type:g("gc.store.maintenance.failed")}),f6.extend({type:g("mail.archived")}),m6.extend({type:g("mail.deleted")}),v6.extend({type:g("mail.marked_read")}),g6.extend({type:g("mail.marked_unread")}),h6.extend({type:g("mail.read")}),y6.extend({type:g("mail.replied")}),_6.extend({type:g("mail.sent")}),x6.extend({type:g("molecule.resolved")}),I6.extend({type:g("order.completed")}),E6.extend({type:g("order.failed")}),w6.extend({type:g("order.fired")}),S6.extend({type:g("order.gate_timeout_fail_open")}),b6.extend({type:g("pg.credential_resolved")}),k6.extend({type:g("project.identity.stamped")}),B6.extend({type:g("provider.quota_observed")}),z6.extend({type:g("provider.quota_poll_failed")}),T6.extend({type:g("provider.swapped")}),C6.extend({type:g("proxy.reaped")}),R6.extend({type:g("request.failed")}),N6.extend({type:g("request.result.city.create")}),P6.extend({type:g("request.result.city.unregister")}),j6.extend({type:g("request.result.rig.create")}),A6.extend({type:g("request.result.session.create")}),O6.extend({type:g("request.result.session.message")}),$6.extend({type:g("request.result.session.submit")}),D6.extend({type:g("rig.provision.progress")}),M6.extend({type:g("session.cold_start_timeout")}),L6.extend({type:g("session.crashed")}),q6.extend({type:g("session.drain_acked_with_assigned_work")}),F6.extend({type:g("session.draining")}),U6.extend({type:g("session.idle_killed")}),Z6.extend({type:g("session.max_age_killed")}),V6.extend({type:g("session.quarantined")}),W6.extend({type:g("session.reset_stalled")}),G6.extend({type:g("session.stopped")}),H6.extend({type:g("session.stranded")}),X6.extend({type:g("session.suspended")}),K6.extend({type:g("session.undrained")}),J6.extend({type:g("session.unknown_state")}),Q6.extend({type:g("session.updated")}),Y6.extend({type:g("session.woke")}),eI.extend({type:g("session.work_query_failed")}),tI.extend({type:g("store.degraded")}),nI.extend({type:g("store.probe_failed")}),oI.extend({type:g("store.recovered")}),rI.extend({type:g("supervisor.fs_pressure.skipped_tick")}),iI.extend({type:g("supervisor.request")}),aI.extend({type:g("supervisor.shutdown_requested")}),sI.extend({type:g("supervisor.started")}),lI.extend({type:g("webhook.received")}),uI.extend({type:g("webhook.rejected")}),cI.extend({type:g("worker.operation")}),W4.extend({type:g("TypedEventStreamEnvelopeCustom")})]);c({items:y(ov).nullable(),next_cursor:e().optional(),partial:R().optional(),partial_errors:y(e()).nullish(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});const dI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ru,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.claim_rejected"),workflow:z.optional()}),pI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.closed"),workflow:z.optional()}),fI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.created"),workflow:z.optional()}),mI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Nu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.dead_assignee_reopened"),workflow:z.optional()}),vI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.deleted"),workflow:z.optional()}),gI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cn,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.updated"),workflow:z.optional()}),hI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Pu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.worktree.reap_skipped"),workflow:z.optional()}),yI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ju,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("bead.worktree.reaped"),workflow:z.optional()}),_I=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Mu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("beads.conditional_writes.degraded"),workflow:z.optional()}),xI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ou,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("breaker.state_changed"),workflow:z.optional()}),II=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:di,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.created"),workflow:z.optional()}),EI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.resumed"),workflow:z.optional()}),wI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.suspended"),workflow:z.optional()}),SI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:di,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("city.unregister_requested"),workflow:z.optional()}),bI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.started"),workflow:z.optional()}),kI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.stopped"),workflow:z.optional()}),BI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Lu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("controller.tick_completed"),workflow:z.optional()}),zI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("convoy.closed"),workflow:z.optional()}),TI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("convoy.created"),workflow:z.optional()}),CI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:no(),run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:e(),workflow:z.optional()}),RI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:qu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("doctor.alert"),workflow:z.optional()}),NI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:pi,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("emergency.acked"),workflow:z.optional()}),PI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:pi,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("emergency.signaled"),workflow:z.optional()}),jI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:rc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("events.rotated"),workflow:z.optional()}),AI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.step_completed"),workflow:z.optional()}),OI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.step_defined"),workflow:z.optional()}),$I=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.step_started"),workflow:z.optional()}),DI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("execution.work_associated"),workflow:z.optional()}),MI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ci,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.adapter_added"),workflow:z.optional()}),LI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ci,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.adapter_removed"),workflow:z.optional()}),qI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Au,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.bound"),workflow:z.optional()}),FI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Fu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.group_created"),workflow:z.optional()}),UI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Uu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.inbound"),workflow:z.optional()}),ZI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Gu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.outbound"),workflow:z.optional()}),VI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Wu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.outbound_channel_mismatch"),workflow:z.optional()}),WI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:zc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("extmsg.unbound"),workflow:z.optional()}),GI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:gc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.disk_critical"),workflow:z.optional()}),HI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:hc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.disk_warn"),workflow:z.optional()}),XI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:yc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.maintenance.done"),workflow:z.optional()}),KI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:_c,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("gc.store.maintenance.failed"),workflow:z.optional()}),JI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.archived"),workflow:z.optional()}),QI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.deleted"),workflow:z.optional()}),YI=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.marked_read"),workflow:z.optional()}),eE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.marked_unread"),workflow:z.optional()}),tE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.read"),workflow:z.optional()}),nE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.replied"),workflow:z.optional()}),oE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ht,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("mail.sent"),workflow:z.optional()}),rE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Zu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("molecule.resolved"),workflow:z.optional()}),iE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.completed"),workflow:z.optional()}),aE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.failed"),workflow:z.optional()}),sE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.fired"),workflow:z.optional()}),lE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Vu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("order.gate_timeout_fail_open"),workflow:z.optional()}),uE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ku,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("pg.credential_resolved"),workflow:z.optional()}),cE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ju,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("project.identity.stamped"),workflow:z.optional()}),dE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Yu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.quota_observed"),workflow:z.optional()}),pE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:ec,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.quota_poll_failed"),workflow:z.optional()}),fE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("provider.swapped"),workflow:z.optional()}),mE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Qu,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("proxy.reaped"),workflow:z.optional()}),vE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:tc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.failed"),workflow:z.optional()}),gE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:$u,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.city.create"),workflow:z.optional()}),hE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Du,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.city.unregister"),workflow:z.optional()}),yE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:nc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.rig.create"),workflow:z.optional()}),_E=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ec,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.create"),workflow:z.optional()}),xE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:lc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.message"),workflow:z.optional()}),IE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:fc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("request.result.session.submit"),workflow:z.optional()}),EE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:oc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("rig.provision.progress"),workflow:z.optional()}),wE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.cold_start_timeout"),workflow:z.optional()}),SE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.crashed"),workflow:z.optional()}),bE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:sc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.drain_acked_with_assigned_work"),workflow:z.optional()}),kE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.draining"),workflow:z.optional()}),BE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.idle_killed"),workflow:z.optional()}),zE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.max_age_killed"),workflow:z.optional()}),TE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.quarantined"),workflow:z.optional()}),CE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:uc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.reset_stalled"),workflow:z.optional()}),RE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.stopped"),workflow:z.optional()}),NE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:cc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.stranded"),workflow:z.optional()}),PE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.suspended"),workflow:z.optional()}),jE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.undrained"),workflow:z.optional()}),AE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:mc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.unknown_state"),workflow:z.optional()}),OE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.updated"),workflow:z.optional()}),$E=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:de,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.woke"),workflow:z.optional()}),DE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bo,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("session.work_query_failed"),workflow:z.optional()}),ME=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:vc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.degraded"),workflow:z.optional()}),LE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:xc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.probe_failed"),workflow:z.optional()}),qE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Ic,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("store.recovered"),workflow:z.optional()}),FE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:wc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.fs_pressure.skipped_tick"),workflow:z.optional()}),UE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Sc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.request"),workflow:z.optional()}),ZE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:bc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.shutdown_requested"),workflow:z.optional()}),VE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:kc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("supervisor.started"),workflow:z.optional()}),WE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Tc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("webhook.received"),workflow:z.optional()}),GE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Cc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("webhook.rejected"),workflow:z.optional()}),HE=c({actor:e(),city:e(),depends_on_step_ids:y(e()).optional(),message:e().optional(),payload:Rc,run_id:e().optional(),seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),session_id:e().optional(),step_id:e().optional(),subject:e().optional(),ts:k(),type:g("worker.operation"),workflow:z.optional()}),rv=pr("type",[dI.extend({type:g("bead.claim_rejected")}),pI.extend({type:g("bead.closed")}),fI.extend({type:g("bead.created")}),mI.extend({type:g("bead.dead_assignee_reopened")}),vI.extend({type:g("bead.deleted")}),gI.extend({type:g("bead.updated")}),hI.extend({type:g("bead.worktree.reap_skipped")}),yI.extend({type:g("bead.worktree.reaped")}),_I.extend({type:g("beads.conditional_writes.degraded")}),xI.extend({type:g("breaker.state_changed")}),II.extend({type:g("city.created")}),EI.extend({type:g("city.resumed")}),wI.extend({type:g("city.suspended")}),SI.extend({type:g("city.unregister_requested")}),bI.extend({type:g("controller.started")}),kI.extend({type:g("controller.stopped")}),BI.extend({type:g("controller.tick_completed")}),zI.extend({type:g("convoy.closed")}),TI.extend({type:g("convoy.created")}),RI.extend({type:g("doctor.alert")}),NI.extend({type:g("emergency.acked")}),PI.extend({type:g("emergency.signaled")}),jI.extend({type:g("events.rotated")}),AI.extend({type:g("execution.step_completed")}),OI.extend({type:g("execution.step_defined")}),$I.extend({type:g("execution.step_started")}),DI.extend({type:g("execution.work_associated")}),MI.extend({type:g("extmsg.adapter_added")}),LI.extend({type:g("extmsg.adapter_removed")}),qI.extend({type:g("extmsg.bound")}),FI.extend({type:g("extmsg.group_created")}),UI.extend({type:g("extmsg.inbound")}),ZI.extend({type:g("extmsg.outbound")}),VI.extend({type:g("extmsg.outbound_channel_mismatch")}),WI.extend({type:g("extmsg.unbound")}),GI.extend({type:g("gc.store.disk_critical")}),HI.extend({type:g("gc.store.disk_warn")}),XI.extend({type:g("gc.store.maintenance.done")}),KI.extend({type:g("gc.store.maintenance.failed")}),JI.extend({type:g("mail.archived")}),QI.extend({type:g("mail.deleted")}),YI.extend({type:g("mail.marked_read")}),eE.extend({type:g("mail.marked_unread")}),tE.extend({type:g("mail.read")}),nE.extend({type:g("mail.replied")}),oE.extend({type:g("mail.sent")}),rE.extend({type:g("molecule.resolved")}),iE.extend({type:g("order.completed")}),aE.extend({type:g("order.failed")}),sE.extend({type:g("order.fired")}),lE.extend({type:g("order.gate_timeout_fail_open")}),uE.extend({type:g("pg.credential_resolved")}),cE.extend({type:g("project.identity.stamped")}),dE.extend({type:g("provider.quota_observed")}),pE.extend({type:g("provider.quota_poll_failed")}),fE.extend({type:g("provider.swapped")}),mE.extend({type:g("proxy.reaped")}),vE.extend({type:g("request.failed")}),gE.extend({type:g("request.result.city.create")}),hE.extend({type:g("request.result.city.unregister")}),yE.extend({type:g("request.result.rig.create")}),_E.extend({type:g("request.result.session.create")}),xE.extend({type:g("request.result.session.message")}),IE.extend({type:g("request.result.session.submit")}),EE.extend({type:g("rig.provision.progress")}),wE.extend({type:g("session.cold_start_timeout")}),SE.extend({type:g("session.crashed")}),bE.extend({type:g("session.drain_acked_with_assigned_work")}),kE.extend({type:g("session.draining")}),BE.extend({type:g("session.idle_killed")}),zE.extend({type:g("session.max_age_killed")}),TE.extend({type:g("session.quarantined")}),CE.extend({type:g("session.reset_stalled")}),RE.extend({type:g("session.stopped")}),NE.extend({type:g("session.stranded")}),PE.extend({type:g("session.suspended")}),jE.extend({type:g("session.undrained")}),AE.extend({type:g("session.unknown_state")}),OE.extend({type:g("session.updated")}),$E.extend({type:g("session.woke")}),DE.extend({type:g("session.work_query_failed")}),ME.extend({type:g("store.degraded")}),LE.extend({type:g("store.probe_failed")}),qE.extend({type:g("store.recovered")}),FE.extend({type:g("supervisor.fs_pressure.skipped_tick")}),UE.extend({type:g("supervisor.request")}),ZE.extend({type:g("supervisor.shutdown_requested")}),VE.extend({type:g("supervisor.started")}),WE.extend({type:g("webhook.received")}),GE.extend({type:g("webhook.rejected")}),HE.extend({type:g("worker.operation")}),CI.extend({type:g("TypedTaggedEventStreamEnvelopeCustom")})]);c({event_cursor:e(),items:y(rv).nullable(),total:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"})});c({beads:y(nv).nullable(),deps:y(pu).nullable(),logical_edges:y(pu).nullable(),logical_nodes:y(C5).nullable(),partial:R(),resolved_root_store:e(),root_bead_id:e(),root_store_ref:e(),scope_groups:y(ex).nullable(),scope_kind:e(),scope_ref:e(),snapshot_event_seq:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),snapshot_version:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}),stores_scanned:y(e()).nullable(),workflow_id:e()});const XE=c({declared_name:e().optional(),declared_prefix:e().optional(),max_active_sessions:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),name:e(),prefix:e().optional(),provider:e().optional(),session_template:e().optional(),suspended:R()});c({agents:y(d5).nullable(),effective_api_url:e().optional(),patches:f5.optional(),providers:fe(e(),U5).optional(),rigs:y(m5).nullable(),workspace:XE});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),base:e()});c({cityName:e().min(1).regex(/\S/),base:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),base:e()});c({cityName:e().min(1).regex(/\S/),base:e()});c({tail:e().optional(),before:e().optional()});c({cityName:e().min(1).regex(/\S/),base:e()});y(un([c({data:fr,event:g("heartbeat"),id:Ue().optional(),retry:Ue().optional()}),c({data:M7,event:g("turn"),id:Ue().optional(),retry:Ue().optional()})]));c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),base:e(),action:me(["suspend","resume"])});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({tail:e().optional(),before:e().optional()});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});y(un([c({data:fr,event:g("heartbeat"),id:Ue().optional(),retry:Ue().optional()}),c({data:M7,event:g("turn"),id:Ue().optional(),retry:Ue().optional()})]));c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e(),action:me(["suspend","resume"])});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),pool:e().optional(),rig:e().optional(),running:me(["true","false"]).optional(),peek:R().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});fe(e(),e());c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100)),status:e().optional(),type:e().optional(),label:e().optional(),assignee:e().optional(),rig:e().optional(),all:R().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),rootID:e()});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100))});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100)),type:e().optional(),actor:e().optional(),since:e().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({wait:R().optional()});c({"Last-Event-ID":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({after_seq:e().optional()});y(un([c({data:ov,event:g("event"),id:Ue().optional(),retry:Ue().optional()}),c({data:fr,event:g("heartbeat"),id:Ue().optional(),retry:Ue().optional()})]));c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({session_id:e().optional()});c({cityName:e().min(1).regex(/\S/)});c({scope_id:e().optional(),provider:e().optional(),account_id:e().optional(),conversation_id:e().optional(),kind:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({scope_id:e().optional(),provider:e().optional(),account_id:e().optional(),conversation_id:e().optional(),parent_conversation_id:e().optional(),kind:e().optional(),after_sequence:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),limit:h().min(BigInt("-9223372036854775808"),{error:"Invalid value: Expected int64 to be >= -9223372036854775808"}).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),order:me(["asc","desc"]).optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),name:e()});c({scope_kind:e().optional(),scope_ref:e().optional(),target:e()});c({cityName:e().min(1).regex(/\S/)});c({scope_kind:e().optional(),scope_ref:e().optional()});c({cityName:e().min(1).regex(/\S/)});c({scope_kind:e().optional(),scope_ref:e().optional(),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),name:e()});c({scope_kind:e().optional(),scope_ref:e().optional(),target:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({scope_kind:e().optional(),scope_ref:e().optional(),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100)),agent:e().optional(),status:e().optional(),rig:e().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({agent:e().optional(),rig:e().optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({rig:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({wait:R().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),bead_id:e()});c({store_ref:e().optional()});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({fresh:R().optional()});c({cityName:e().min(1).regex(/\S/)});c({scope_kind:e().optional(),scope_ref:e().optional(),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({cityName:e().min(1).regex(/\S/)});c({scoped_name:e().min(1),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional(),before:e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),base:e()});c({cityName:e().min(1).regex(/\S/),base:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({cityName:e().min(1).regex(/\S/),dir:e(),base:e()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({providers:e().optional(),fresh:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({items:e().optional(),fresh:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/),name:e()});c({git:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e(),action:me(["suspend","resume","restart"])});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),git:R().optional()});c({"X-GC-Request":e().min(1),"Idempotency-Key":e().optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),run_id:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),run_id:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),run_id:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),name:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),name:e()});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/),id:e()});c({peek:R().optional(),peek_lines:h().gte(BigInt(0)).lte(BigInt(1e4)).optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e(),agentId:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({delete:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"Last-Event-ID":e().max(2048).optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({format:me(["conversation","raw","structured"]).optional(),include_thinking:R().optional(),after_cursor:e().max(2048).optional()});y(un([c({data:q7,event:g("activity"),id:e().optional(),retry:Ue().optional()}),c({data:fr,event:g("heartbeat"),id:e().optional(),retry:Ue().optional()}),c({data:rx,event:g("message").optional(),id:e().optional(),retry:Ue().optional()}),c({data:Xu,event:g("pending"),id:e().optional(),retry:Ue().optional()}),c({data:F7,event:g("pending_cleared"),id:e().optional(),retry:Ue().optional()}),c({data:Y7,event:g("structured"),id:e().optional(),retry:Ue().optional()}),c({data:ox,event:g("turn"),id:e().optional(),retry:Ue().optional()})]));c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/),id:e()});c({tail:e().optional(),format:me(["conversation","raw","structured"]).optional(),include_thinking:R().optional(),before:e().optional(),after:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/)});c({cursor:e().optional(),limit:h().gte(BigInt(0)).lte(BigInt(1e3)).optional().default(BigInt(100)),state:e().optional(),template:e().optional(),peek:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/)});c({cityName:e().min(1).regex(/\S/)});c({index:e().optional(),wait:e().optional(),lite:R().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e()});c({cityName:e().min(1).regex(/\S/)});c({aggregate_only:R().optional()});c({cityName:e().min(1).regex(/\S/),id:e()});c({cityName:e().min(1).regex(/\S/)});c({state:e().optional(),session:e().optional()});c({"X-GC-Request":e().min(1)});c({cityName:e().min(1).regex(/\S/),workflow_id:e()});c({scope_kind:e().optional(),scope_ref:e().optional(),delete:R().optional()});c({cityName:e().min(1).regex(/\S/),workflow_id:e()});c({scope_kind:e().optional(),scope_ref:e().optional()});c({type:e().optional(),actor:e().optional(),since:e().optional(),limit:h().gte(BigInt(0)).max(BigInt("9223372036854775807"),{error:"Invalid value: Expected int64 to be <= 9223372036854775807"}).optional()});c({"Last-Event-ID":e().optional()});c({after_cursor:e().optional()});y(un([c({data:fr,event:g("heartbeat"),id:e().optional(),retry:Ue().optional()}),c({data:rv,event:g("tagged_event"),id:e().optional(),retry:Ue().optional()})]));c({providers:e().optional(),fresh:R().optional()});c({items:e().optional(),fresh:R().optional()});const KE="session.structured.v1";function ln(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function JE(t){if(!ln(t)||t.format!=="structured"||t.schema_version!==KE||typeof t.id!="string"||typeof t.template!="string"||typeof t.provider!="string"||!Array.isArray(t.structured_messages)||!t.structured_messages.every(iv)||!Y7.safeParse(t).success||!YE(t.history))return!1;switch(t.operation){case"snapshot":case"upsert":return t.reset_reason===void 0;case"reset":return QE(t.reset_reason);default:return!1}}function QE(t){return t==="resume_invalid"||t==="stream_changed"||t==="cursor_invalidated"||t==="history_rewritten"}function B9(t){return ln(t)&&typeof t.activity=="string"}function z9(t){return ln(t)&&typeof t.timestamp=="string"}function YE(t){if(!ln(t)||typeof t.transcript_stream_id!="string")return!1;const r=t.generation;if(!ln(r)||typeof r.id!="string")return!1;const i=t.cursor;if(!ln(i)||typeof i.resume_token!="string"||i.resume_token==="")return!1;const s=t.continuity;if(!ln(s)||typeof s.status!="string")return!1;const u=t.tail_state;return!(!ln(u)||typeof u.activity!="string")}function iv(t){return ln(t)&&typeof t.id=="string"&&ew(t.role)&&typeof t.status=="string"&&Array.isArray(t.blocks)&&t.blocks.every(tw)}function ew(t){return t==="unknown"||t==="user"||t==="assistant"||t==="system"||t==="tool"}function tw(t){return ln(t)?t.type==="text"||t.type==="thinking"||t.type==="tool_use"||t.type==="tool_result"||t.type==="interaction"||t.type==="image"||t.type==="unknown":!1}function T9(t){return Array.isArray(t.structured_messages)?t.structured_messages.filter(iv):[]}function hm(t,r){const i=t??1;return r===void 0||r===1?String(i):`${i},${r}`}function nw(t){const r=t.old_start,i=t.new_start;return r===void 0&&i===void 0?"@@":`@@ -${hm(r,t.old_lines)} +${hm(i,t.new_lines)} @@`}function C9(t){if(t==null||t.length===0)return"";const r=[];let i="";for(const s of t){const u=s.file_path??"";if(u!==""&&u!==i&&(r.push(`*** Update File: ${u}`),i=u),r.push(nw(s)),s.lines!==void 0&&s.lines!==null)for(const f of s.lines)r.push(f)}return r.join(` +`)}function ei(t,r,i){i!==void 0&&i!==0&&t.push(`${r} ${i}`)}function R9(t){if(t===void 0)return"";const r=[];ei(r,"in",t.input_tokens),ei(r,"out",t.output_tokens),ei(r,"reason",t.reasoning_tokens),ei(r,"cache",t.cache_read_tokens),ei(r,"write",t.cache_creation_tokens);const i=t.context_used_tokens,s=t.context_window_tokens;i!==void 0&&s!==void 0&&r.push(`${i}/${s}`);const u=t.context_percent;return u!==void 0&&r.push(`${u}%`),r.length>0?`tokens ${r.join(" ")}`:""}const ow="modulepreload",rw=function(t){return"/"+t},ym={},Rn=function(r,i,s){let u=Promise.resolve();if(i&&i.length>0){let x=function(I){return Promise.all(I.map(w=>Promise.resolve(w).then(b=>({status:"fulfilled",value:b}),b=>({status:"rejected",reason:b}))))};document.getElementsByTagName("link");const p=document.querySelector("meta[property=csp-nonce]"),v=p?.nonce||p?.getAttribute("nonce");u=x(i.map(I=>{if(I=rw(I),I in ym)return;ym[I]=!0;const w=I.endsWith(".css"),b=w?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${I}"]${b}`))return;const C=document.createElement("link");if(C.rel=w?"stylesheet":ow,w||(C.as="script"),C.crossOrigin="",C.href=I,v&&C.setAttribute("nonce",v),document.head.appendChild(C),w)return new Promise((O,L)=>{C.addEventListener("load",O),C.addEventListener("error",()=>L(new Error(`Unable to preload CSS for ${I}`)))})}))}function f(p){const v=new Event("vite:preloadError",{cancelable:!0});if(v.payload=p,window.dispatchEvent(v),!v.defaultPrevented)throw p}return u.then(p=>{for(const v of p||[])v.status==="rejected"&&f(v.reason);return r().catch(f)})};let li=null;function iw(t){if(!Jm.test(t))throw new Error(`invalid city name: ${t}`);li=t}function Xa(){return li}function pn(t){const r=li;if(r===null)throw new Error(`${t} called before an active city was resolved`);return r}function _o(t){if(li===null)throw new Error(`cityPath("${t}") called before an active city was resolved`);return`/api/city/${encodeURIComponent(li)}${t}`}async function aw(t,r,i,s){const p=await fetch(r,{method:t,headers:{Accept:"application/json"},credentials:"same-origin"});if(!p.ok){const x=await p.text(),I=sw(x),w=I?.error??(x.trim()||p.statusText||`HTTP ${p.status}`);throw new av(p.status,w,I?.kind,I?.reason)}let v;try{v=await p.json()}catch(x){throw new sv(r,`body must be valid JSON: ${uw(x)}`)}return i(v,r)}function sw(t){if(t.trim().length!==0)try{const r=JSON.parse(t);return lw(r)?r:void 0}catch{return}}function lw(t){if(typeof t!="object"||t===null)return!1;const r=t;return typeof r.error!="string"||r.kind!==void 0&&typeof r.kind!="string"?!1:r.reason===void 0||typeof r.reason=="string"}async function Xt(t,r,i,s){return aw(t,r,i)}class av extends Error{constructor(r,i,s,u){super(i),this.status=r,this.kind=s,this.reason=u,this.name="ApiClientError"}status;kind;reason}class sv extends Error{constructor(r,i){super(`Invalid API response for ${r}: ${i}`),this.url=r,this.detail=i,this.name="ApiResponseDecodeError"}url;detail}function uw(t){return t instanceof Error?t.message:typeof t=="string"?t:"unknown error"}function dn(t,r){throw new sv(t,r)}function cw(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function wn(t,r,i){return cw(t)||dn(r,`${i} must be an object`),t}function bt(t,r,i,s){typeof t[s]!="string"&&dn(r,`${i}.${s} must be a string`)}function lv(t,r,i,s){const u=t[s];u!==null&&typeof u!="string"&&dn(r,`${i}.${s} must be a string or null`)}function Io(t,r,i,s){typeof t[s]!="boolean"&&dn(r,`${i}.${s} must be a boolean`)}function Jt(t,r,i,s){typeof t[s]!="number"&&dn(r,`${i}.${s} must be a number`)}function Qt(t,r,i,s){Array.isArray(t[s])||dn(r,`${i}.${s} must be an array`)}function sn(t,r,i,s){wn(t[s],r,`${i}.${s}`)}function dw(t,r,i,s){const u=t[s];u!==null&&(!Array.isArray(u)||u.some(f=>typeof f!="string"))&&dn(r,`${i}.${s} must be an array of strings or null`)}function fn(t,r){return(i,s)=>{const u=wn(i,s,t);return r?.(u,s),u}}function uv(t,r){return fn(t,(i,s)=>{Qt(i,s,t,"items"),r?.(i,s)})}const pw=fn("health",(t,r)=>{Io(t,r,"health","ok"),bt(t,r,"health","ts")}),fw=uv("commits",(t,r)=>{bt(t,r,"commits","view")}),mw=uv("builds",(t,r)=>{lv(t,r,"builds","source"),Io(t,r,"builds","failed_marker")}),vw=fn("config",(t,r)=>{bt(t,r,"config","cityName"),bt(t,r,"config","cityRoot"),Io(t,r,"config","useFixtures"),Io(t,r,"config","readOnly"),bt(t,r,"config","operatorAlias"),bt(t,r,"config","operatorWireAlias"),bt(t,r,"config","decisionLabel"),dw(t,r,"config","enabledModules"),lv(t,r,"config","defaultView")}),gw=new Set(["sample_failed","invalid_sample","value_overflow"]);function Ta(t,r,i,s,u){const f=wn(t[s],r,`${i}.${s}`);if(bt(f,r,`${i}.${s}`,"status"),f.status==="available"){u(f.value,r,`${i}.${s}.value`);return}f.status!=="unavailable"&&dn(r,`${i}.${s}.status must be available or unavailable`),bt(f,r,`${i}.${s}`,"reason"),gw.has(f.reason)||dn(r,`${i}.${s}.reason is not recognized`)}function _m(t,r,i){typeof t!="number"&&dn(r,`${i} must be a number`)}const hw=fn("system health",(t,r)=>{const i=wn(t.admin,r,"system health.admin"),s=wn(t.host,r,"system health.host");Jt(i,r,"system health.admin","pid"),Jt(i,r,"system health.admin","uptime_sec"),Jt(i,r,"system health.admin","heap_used_bytes"),bt(i,r,"system health.admin","node_version"),Ta(i,r,"system health.admin","rss",_m),Jt(s,r,"system health.host","cpu_count"),Ta(s,r,"system health.host","uptime",_m),Ta(s,r,"system health.host","load",(u,f,p)=>{const v=wn(u,f,p);Jt(v,f,p,"load_avg_1"),Jt(v,f,p,"load_avg_5"),Jt(v,f,p,"load_avg_15")}),Ta(s,r,"system health.host","memory",(u,f,p)=>{const v=wn(u,f,p);Jt(v,f,p,"total_mem_bytes"),Jt(v,f,p,"free_mem_bytes")})});function Ql(t,r,i,s){sn(t,r,i,s);const u=t[s],f=`${i}.${s}`;bt(u,r,f,"status")}const yw=fn("local tool versions",(t,r)=>{Ql(t,r,"local tool versions","dolt"),Ql(t,r,"local tool versions","beads"),Ql(t,r,"local tool versions","gc")}),_w=fn("dolt trend",(t,r)=>{Io(t,r,"dolt trend","available"),Qt(t,r,"dolt trend","samples")}),xw=fn("rig store health",(t,r)=>{Io(t,r,"rig store health","available"),Qt(t,r,"rig store health","rigs")});function xm(t,r){const i=wn(t,r,"supervisor status.status");sn(i,r,"supervisor status.status","work")}const Iw=fn("supervisor status",(t,r)=>{Io(t,r,"supervisor status","available"),t.available===!0?(bt(t,r,"supervisor status","sampledAt"),xm(t.status,r)):(bt(t,r,"supervisor status","reason"),t.status!==null&&xm(t.status,r))}),Ew=fn("run summary",(t,r)=>{Jt(t,r,"run summary","totalActive"),Jt(t,r,"run summary","totalHistorical"),Qt(t,r,"run summary","lanes"),Qt(t,r,"run summary","historicalLanes"),Qt(t,r,"run summary","blockedLanes"),Qt(t,r,"run summary","recentChanges"),sn(t,r,"run summary","runCounts"),sn(t,r,"run summary","census")}),ww=fn("formula run detail",(t,r)=>{bt(t,r,"formula run detail","runId"),sn(t,r,"formula run detail","formula"),sn(t,r,"formula run detail","formulaDetail"),sn(t,r,"formula run detail","executionPath"),sn(t,r,"formula run detail","snapshotEventSeq"),sn(t,r,"formula run detail","completeness");const i=wn(t.progress,r,"formula run detail.progress");sn(i,r,"formula run detail.progress","statusCounts"),Qt(t,r,"formula run detail","stages"),Qt(t,r,"formula run detail","nodes"),Qt(t,r,"formula run detail","edges"),Qt(t,r,"formula run detail","lanes")});function Sw(t,r="request failed"){if(t instanceof av){const i={message:t.message,status:t.status};return t.kind!==void 0&&(i.kind=t.kind),i}return t instanceof Error?{message:t.message}:{message:r}}function Lt(t,r="request failed"){const i=Sw(t,r);return i.status===void 0?i.message:`${i.status} ${i.message}`}const lr={health(){return Xt("GET","/api/health",pw)},listCommits(t){return Xt("GET",`/api/git/commits?view=${encodeURIComponent(t)}`,fw)},listBuilds(){return Xt("GET","/api/builds",mw)},config(){return Xt("GET",_o("/config"),vw)},systemHealth(){return Xt("GET","/api/health/system",hw)},localToolVersions(){return Xt("GET","/api/health/local-tools",yw)},doltTrend(){return Xt("GET",_o("/dolt-noms/trend"),_w)},rigStoreHealth(){return Xt("GET",_o("/rig-store-health"),xw)},supervisorStatus(){return Xt("GET",_o("/supervisor-status"),Iw)},runSummary(){return Xt("GET",_o("/runs/summary"),Ew)},runDetail(t){return Xt("GET",_o(`/runs/${encodeURIComponent(t)}/detail`),ww)},runDetailStreamUrl(t){return _o(`/runs/${encodeURIComponent(t)}/detail/stream`)}},mi=["agents","beads","runs","mail","activity","health"],bw=5,kw=new Map(mi.map((t,r)=>[t,r]));function fu(t,r={}){const i=Bw(),s=[];let u=0;for(const I of t)for(const w of I.getItems()){s.push({item:w,index:u});const b=i[w.domain],C=[...b.items,w];i[w.domain]={domain:w.domain,attention:b.attention+(w.severity==="attention"?1:0),watch:b.watch+(w.severity==="watch"?1:0),unavailable:b.unavailable+(w.severity==="unavailable"?1:0),severity:w.severity==="unavailable"?b.severity:zw(b.severity,w.severity),items:C},u+=1}const f=s.sort((I,w)=>Tw(I.item,w.item)||I.index-w.index).map(({item:I})=>I),p=r.topLimit??bw,v=f.slice(0,p),x=Cw(f.slice(p));return{items:f,topItems:v,overflowByDomain:x,byDomain:i}}function Bw(){const t={};for(const r of mi)t[r]={domain:r,attention:0,watch:0,unavailable:0,severity:null,items:[]};return t}function zw(t,r){return t==="attention"||r==="attention"?"attention":"watch"}function Tw(t,r){return Im(t.severity)-Im(r.severity)||Ca(r.current??!0)-Ca(t.current??!0)||Ca(r.actionable??!1)-Ca(t.actionable??!1)||Em(r.updatedAt)-Em(t.updatedAt)||wm(t.domain)-wm(r.domain)}function Im(t){switch(t){case"attention":return 0;case"watch":return 1;case"unavailable":return 2}}function Ca(t){return t?1:0}function Em(t){if(t===void 0)return 0;const r=Date.parse(t);return Number.isFinite(r)?r:0}function wm(t){return kw.get(t)??mi.length}function Cw(t){const r=[];for(const i of mi){let s=0,u=0,f=0;for(const v of t)v.domain===i&&(v.severity==="attention"?s+=1:v.severity==="watch"?u+=1:f+=1);const p=s+u+f;p>0&&r.push({domain:i,attention:s,watch:u,unavailable:f,total:p})}return r}const Rw=fu([]),cv=T.createContext(Rw);function Nw({contributors:t,topLimit:r,children:i}){const s=T.useMemo(()=>r===void 0?fu(t):fu(t,{topLimit:r}),[t,r]);return M.jsx(cv.Provider,{value:s,children:i})}function Pw(){return T.useContext(cv)}const Nc=new Map;function Yl(t){return Nc.get(t)?.value}function Ra(t){return Nc.get(t)?.fetchedAt}function jw(t,r){Nc.set(t,{value:r,fetchedAt:new Date().toISOString()})}function En(t,r,i){const s=T.useRef(r);s.current=r;const u=T.useRef(i?.refreshFetcher);u.current=i?.refreshFetcher;const f=T.useRef(i?.sseRefreshFetcher);f.current=i?.sseRefreshFetcher;const p=T.useRef(i?.onError);p.current=i?.onError;const v=T.useRef(t);v.current=t;const x=T.useRef(0),I=T.useRef(null),[w,b]=T.useState(()=>Yl(t)),[C,O]=T.useState(()=>Yl(t)===void 0),[L,W]=T.useState(null),[D,G]=T.useState(()=>Ra(t)),ee=T.useCallback(async te=>{const ue=x.current+1;x.current=ue,I.current?.abort();const ve=new AbortController;I.current=ve;const pe=t;O(!0),W(null);try{const we=await te(ve.signal),Se=x.current===ue,Ne=v.current===pe;Se&&Ne?(jw(pe,we),b(we),G(Ra(pe))):Ne&&(b(Ae=>Ae===void 0?we:Ae),G(Ae=>Ae??Ra(pe)??new Date().toISOString()))}catch(we){x.current===ue&&(W(we instanceof Error?we.message:"failed to load"),p.current?.(we))}finally{I.current===ve&&(I.current=null),x.current===ue&&O(!1)}},[t]),J=T.useCallback(()=>ee(u.current??s.current),[ee]),H=T.useCallback(()=>ee(f.current??u.current??s.current),[ee]);return T.useEffect(()=>{const te=Yl(t);return b(te),O(te===void 0),G(Ra(t)),ee(s.current),()=>{x.current+=1,I.current?.abort(),I.current=null}},[t,ee]),{data:w,loading:C,error:L,fetchedAt:D,refresh:J,cheapRefresh:H}}var Aw=async(t,r)=>{let i=typeof r=="function"?await r(t):r;if(i)return t.scheme==="bearer"?`Bearer ${i}`:t.scheme==="basic"?`Basic ${btoa(i)}`:i},Ow={bodySerializer:t=>JSON.stringify(t,(r,i)=>typeof i=="bigint"?i.toString():i)},$w=t=>{switch(t){case"label":return".";case"matrix":return";";case"simple":return",";default:return"&"}},Dw=t=>{switch(t){case"form":return",";case"pipeDelimited":return"|";case"spaceDelimited":return"%20";default:return","}},Mw=t=>{switch(t){case"label":return".";case"matrix":return";";case"simple":return",";default:return"&"}},dv=({allowReserved:t,explode:r,name:i,style:s,value:u})=>{if(!r){let v=(t?u:u.map(x=>encodeURIComponent(x))).join(Dw(s));switch(s){case"label":return`.${v}`;case"matrix":return`;${i}=${v}`;case"simple":return v;default:return`${i}=${v}`}}let f=$w(s),p=u.map(v=>s==="label"||s==="simple"?t?v:encodeURIComponent(v):Ka({allowReserved:t,name:i,value:v})).join(f);return s==="label"||s==="matrix"?f+p:p},Ka=({allowReserved:t,name:r,value:i})=>{if(i==null)return"";if(typeof i=="object")throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");return`${r}=${t?i:encodeURIComponent(i)}`},pv=({allowReserved:t,explode:r,name:i,style:s,value:u,valueOnly:f})=>{if(u instanceof Date)return f?u.toISOString():`${i}=${u.toISOString()}`;if(s!=="deepObject"&&!r){let x=[];Object.entries(u).forEach(([w,b])=>{x=[...x,w,t?b:encodeURIComponent(b)]});let I=x.join(",");switch(s){case"form":return`${i}=${I}`;case"label":return`.${I}`;case"matrix":return`;${i}=${I}`;default:return I}}let p=Mw(s),v=Object.entries(u).map(([x,I])=>Ka({allowReserved:t,name:s==="deepObject"?`${i}[${x}]`:x,value:I})).join(p);return s==="label"||s==="matrix"?p+v:v},Lw=/\{[^{}]+\}/g,qw=({path:t,url:r})=>{let i=r,s=r.match(Lw);if(s)for(let u of s){let f=!1,p=u.substring(1,u.length-1),v="simple";p.endsWith("*")&&(f=!0,p=p.substring(0,p.length-1)),p.startsWith(".")?(p=p.substring(1),v="label"):p.startsWith(";")&&(p=p.substring(1),v="matrix");let x=t[p];if(x==null)continue;if(Array.isArray(x)){i=i.replace(u,dv({explode:f,name:p,style:v,value:x}));continue}if(typeof x=="object"){i=i.replace(u,pv({explode:f,name:p,style:v,value:x,valueOnly:!0}));continue}if(v==="matrix"){i=i.replace(u,`;${Ka({name:p,value:x})}`);continue}let I=encodeURIComponent(v==="label"?`.${x}`:x);i=i.replace(u,I)}return i},fv=({allowReserved:t,array:r,object:i}={})=>s=>{let u=[];if(s&&typeof s=="object")for(let f in s){let p=s[f];if(p!=null)if(Array.isArray(p)){let v=dv({allowReserved:t,explode:!0,name:f,style:"form",value:p,...r});v&&u.push(v)}else if(typeof p=="object"){let v=pv({allowReserved:t,explode:!0,name:f,style:"deepObject",value:p,...i});v&&u.push(v)}else{let v=Ka({allowReserved:t,name:f,value:p});v&&u.push(v)}}return u.join("&")},Fw=t=>{if(!t)return"stream";let r=t.split(";")[0]?.trim();if(r){if(r.startsWith("application/json")||r.endsWith("+json"))return"json";if(r==="multipart/form-data")return"formData";if(["application/","audio/","image/","video/"].some(i=>r.startsWith(i)))return"blob";if(r.startsWith("text/"))return"text"}},Uw=async({security:t,...r})=>{for(let i of t){let s=await Aw(i,r.auth);if(!s)continue;let u=i.name??"Authorization";switch(i.in){case"query":r.query||(r.query={}),r.query[u]=s;break;case"cookie":r.headers.append("Cookie",`${u}=${s}`);break;default:r.headers.set(u,s);break}return}},Sm=t=>Zw({baseUrl:t.baseUrl,path:t.path,query:t.query,querySerializer:typeof t.querySerializer=="function"?t.querySerializer:fv(t.querySerializer),url:t.url}),Zw=({baseUrl:t,path:r,query:i,querySerializer:s,url:u})=>{let f=u.startsWith("/")?u:`/${u}`,p=(t??"")+f;r&&(p=qw({path:r,url:p}));let v=i?s(i):"";return v.startsWith("?")&&(v=v.substring(1)),v&&(p+=`?${v}`),p},bm=(t,r)=>{let i={...t,...r};return i.baseUrl?.endsWith("/")&&(i.baseUrl=i.baseUrl.substring(0,i.baseUrl.length-1)),i.headers=mv(t.headers,r.headers),i},mv=(...t)=>{let r=new Headers;for(let i of t){if(!i||typeof i!="object")continue;let s=i instanceof Headers?i.entries():Object.entries(i);for(let[u,f]of s)if(f===null)r.delete(u);else if(Array.isArray(f))for(let p of f)r.append(u,p);else f!==void 0&&r.set(u,typeof f=="object"?JSON.stringify(f):f)}return r},eu=class{_fns;constructor(){this._fns=[]}clear(){this._fns=[]}getInterceptorIndex(t){return typeof t=="number"?this._fns[t]?t:-1:this._fns.indexOf(t)}exists(t){let r=this.getInterceptorIndex(t);return!!this._fns[r]}eject(t){let r=this.getInterceptorIndex(t);this._fns[r]&&(this._fns[r]=null)}update(t,r){let i=this.getInterceptorIndex(t);return this._fns[i]?(this._fns[i]=r,t):!1}use(t){return this._fns=[...this._fns,t],this._fns.length-1}},Vw=()=>({error:new eu,request:new eu,response:new eu}),Ww=fv({allowReserved:!1,array:{explode:!0,style:"form"},object:{explode:!0,style:"deepObject"}}),Gw={"Content-Type":"application/json"},vv=(t={})=>({...Ow,headers:Gw,parseAs:"auto",querySerializer:Ww,...t}),gv=(t={})=>{let r=bm(vv(),t),i=()=>({...r}),s=p=>(r=bm(r,p),i()),u=Vw(),f=async p=>{let v={...r,...p,fetch:p.fetch??r.fetch??globalThis.fetch,headers:mv(r.headers,p.headers)};v.security&&await Uw({...v,security:v.security}),v.body&&v.bodySerializer&&(v.body=v.bodySerializer(v.body)),(v.body===void 0||v.body==="")&&v.headers.delete("Content-Type");let x=Sm(v),I={redirect:"follow",...v},w=new Request(x,I);for(let D of u.request._fns)D&&(w=await D(w,v));let b=v.fetch,C=await b(w);for(let D of u.response._fns)D&&(C=await D(C,w,v));let O={request:w,response:C};if(C.ok){if(C.status===204||C.headers.get("Content-Length")==="0")return v.responseStyle==="data"?{}:{data:{},...O};let D=(v.parseAs==="auto"?Fw(C.headers.get("Content-Type")):v.parseAs)??"json";if(D==="stream")return v.responseStyle==="data"?C.body:{data:C.body,...O};let G=await C[D]();return D==="json"&&(v.responseValidator&&await v.responseValidator(G),v.responseTransformer&&(G=await v.responseTransformer(G))),v.responseStyle==="data"?G:{data:G,...O}}let L=await C.text();try{L=JSON.parse(L)}catch{}let W=L;for(let D of u.error._fns)D&&(W=await D(L,C,w,v));if(W=W||{},v.throwOnError)throw W;return v.responseStyle==="data"?void 0:{error:W,...O}};return{buildUrl:Sm,connect:p=>f({...p,method:"CONNECT"}),delete:p=>f({...p,method:"DELETE"}),get:p=>f({...p,method:"GET"}),getConfig:i,head:p=>f({...p,method:"HEAD"}),interceptors:u,options:p=>f({...p,method:"OPTIONS"}),patch:p=>f({...p,method:"PATCH"}),post:p=>f({...p,method:"POST"}),put:p=>f({...p,method:"PUT"}),request:f,setConfig:s,trace:p=>f({...p,method:"TRACE"})}};const Te=gv(vv()),Hw=t=>(t?.client??Te).get({url:"/health",...t}),Xw=t=>(t?.client??Te).get({url:"/v0/cities",...t}),Kw=t=>(t.client??Te).get({url:"/v0/city/{cityName}/agents",...t}),Jw=t=>(t.client??Te).get({url:"/v0/city/{cityName}/bead/{id}",...t}),Qw=t=>(t.client??Te).patch({url:"/v0/city/{cityName}/bead/{id}",...t,headers:{"Content-Type":"application/json",...t.headers}}),Yw=t=>(t.client??Te).post({url:"/v0/city/{cityName}/bead/{id}/close",...t}),eS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/beads",...t}),tS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/beads",...t,headers:{"Content-Type":"application/json",...t.headers}}),nS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/events",...t}),oS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/formulas/feed",...t}),rS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/formulas/{name}",...t}),iS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/health",...t}),aS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/mail",...t}),sS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail",...t,headers:{"Content-Type":"application/json",...t.headers}}),lS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/mail/thread/{id}",...t}),uS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail/{id}/archive",...t}),cS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail/{id}/mark-unread",...t}),dS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail/{id}/read",...t}),pS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/mail/{id}/reply",...t,headers:{"Content-Type":"application/json",...t.headers}}),fS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/rigs",...t}),mS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/runs/census",...t}),vS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/session/{id}/pending",...t}),gS=t=>(t.client??Te).post({url:"/v0/city/{cityName}/session/{id}/respond",...t,headers:{"Content-Type":"application/json",...t.headers}}),hS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/session/{id}/transcript",...t}),yS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/sessions",...t}),_S=t=>(t.client??Te).post({url:"/v0/city/{cityName}/sling",...t,headers:{"Content-Type":"application/json",...t.headers}}),xS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/status",...t}),IS=t=>(t.client??Te).get({url:"/v0/city/{cityName}/usage",...t}),ES=t=>(t.client??Te).get({url:"/v0/city/{cityName}/workflow/{workflow_id}",...t});class Sn extends Error{constructor(r,i,s,u){super(i),this.status=r,this.requestId=s,this.code=u}status;requestId;code;name="SupervisorApiError"}async function Be(t,r){let i;try{i=await t}catch(f){throw wS(f)}const{response:s}=i;if(s===void 0)throw new Sn(void 0,vu(i.error),void 0,mu(i.error));if(!s.ok||i.error!==void 0)throw new Sn(s.status,vu(i.error,s.statusText),s.headers.get("x-gc-request-id")??void 0,mu(i.error));const u=i.data;if(u===void 0)throw new Sn(s.status,r,s.headers.get("x-gc-request-id")??void 0);return u}function wS(t){return t instanceof Sn?t:new Sn(void 0,vu(t),void 0,mu(t))}function mu(t){if(!hv(t))return;const r=t.code;return typeof r=="string"&&r.trim().length>0?r.trim():void 0}function vu(t,r="gc supervisor request failed"){if(typeof t=="string"&&t.trim().length>0)return t.trim();if(t instanceof Error&&t.message.trim().length>0)return t.message.trim();if(hv(t))for(const i of["error","message","detail"]){const s=t[i];if(typeof s=="string"&&s.trim().length>0)return s.trim()}return r}function hv(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}const SS="";function bS(){const t=globalThis.location?.origin;return typeof t=="string"&&t.length>0&&t!=="null"?t:SS}function kS(t){if(!t.startsWith("/"))return t;const r=globalThis.location?.origin;return typeof r!="string"||r.length===0||r==="null"?t:new URL(t,r).toString().replace(/\/$/,"")}function km(t,r,i){const s=t.replace(/\/$/,""),u=new URLSearchParams(i).toString(),f=u.length>0?`${r}?${u}`:r;return s===""?f:s.startsWith("/")?`${s}${f}`:new URL(f,`${s}/`).toString()}const BS=6e4,Kt={"X-GC-Request":"dashboard"};let Bm=null;const zm=new Map;function yv(t={}){const r=t.baseUrl??bS(),s={baseUrl:kS(r),headers:{Accept:"application/json"},responseStyle:"fields",throwOnError:!1},u=t.client??gv({...s,fetch:TS(t.fetch??globalThis.fetch,_v(t.timeoutMs))});return{baseUrl:r,health(){return Be(Hw({client:u}),"gc supervisor health response was empty")},cityHealth(f){return Be(iS({client:u,path:{cityName:f}}),"gc supervisor city health response was empty")},cityStatus(f){return Be(xS({client:u,path:{cityName:f}}),"gc supervisor status response was empty")},cityUsage(f){return Be(IS({client:u,path:{cityName:f},query:{aggregate_only:!0}}),"gc supervisor usage response was empty")},runCensus(f){return Be(mS({client:u,path:{cityName:f}}),"gc supervisor run census response was empty")},listCities(){return Be(Xw({client:u}),"gc supervisor cities response was empty")},listAgents(f){return Be(Kw({client:u,path:{cityName:f}}),"gc supervisor agents response was empty")},listRigs(f){return Be(fS({client:u,path:{cityName:f}}),"gc supervisor rigs response was empty")},listBeads(f,p,v){return Be(eS({client:u,path:{cityName:f},...p===void 0?{}:{query:p},...v===void 0?{}:{signal:v}}),"gc supervisor beads response was empty")},listEvents(f,p){return Be(nS({client:u,path:{cityName:f},...p===void 0?{}:{query:p}}),"gc supervisor events response was empty")},getBead(f,p){return Be(Jw({client:u,path:{cityName:f,id:p}}),"gc supervisor bead response was empty")},createBead(f,p){return Be(tS({client:u,path:{cityName:f},headers:Kt,body:p}),"gc supervisor bead create response was empty")},updateBead(f,p,v){return Be(Qw({client:u,path:{cityName:f,id:p},headers:Kt,body:v}),"gc supervisor bead update response was empty")},closeBead(f,p){return Be(Yw({client:u,path:{cityName:f,id:p},headers:Kt}),"gc supervisor bead close response was empty")},sling(f,p){return Be(_S({client:u,path:{cityName:f},headers:Kt,body:p}),"gc supervisor sling response was empty")},listMail(f,p){return Be(aS({client:u,path:{cityName:f},...p===void 0?{}:{query:p}}),"gc supervisor mail response was empty")},formulaFeed(f,p){return Be(oS({client:u,path:{cityName:f},...p===void 0?{}:{query:p}}),"gc supervisor formula feed response was empty")},sendMail(f,p){return Be(sS({client:u,path:{cityName:f},headers:Kt,body:p}),"gc supervisor mail send response was empty")},mailThread(f,p){return Be(lS({client:u,path:{cityName:f,id:p}}),"gc supervisor mail thread response was empty")},markMailRead(f,p,v){return Be(dS({client:u,path:{cityName:f,id:p},headers:Kt,...v===void 0?{}:{query:v}}),"gc supervisor mail mark-read response was empty")},markMailUnread(f,p,v){return Be(cS({client:u,path:{cityName:f,id:p},headers:Kt,...v===void 0?{}:{query:v}}),"gc supervisor mail mark-unread response was empty")},archiveMail(f,p,v){return Be(uS({client:u,path:{cityName:f,id:p},headers:Kt,...v===void 0?{}:{query:v}}),"gc supervisor mail archive response was empty")},replyMail(f,p,v,x){return Be(pS({client:u,path:{cityName:f,id:p},headers:Kt,body:v,...x===void 0?{}:{query:x}}),"gc supervisor mail reply response was empty")},cityEventStreamUrl(f,p){return km(r,`/v0/city/${encodeURIComponent(f)}/events/stream`,p===void 0?void 0:{after_seq:p})},sessionStreamUrl(f,p,v,x){const I={};return v!==void 0&&(I.after_cursor=v),x!==void 0&&(I.format=x),km(r,`/v0/city/${encodeURIComponent(f)}/session/${encodeURIComponent(p)}/stream`,Object.keys(I).length>0?I:void 0)},async listSessions(f){const p=[],v=[];let x=0,I=!1,w;for(;;){const C=await Be(yS({client:u,path:{cityName:f},query:w===void 0?{limit:1e3}:{limit:1e3,cursor:w}}),"gc supervisor sessions response was empty");C.items&&p.push(...C.items),C.partial&&(I=!0),C.partial_errors&&v.push(...C.partial_errors),x=C.total;const O=C.next_cursor;if(O===void 0||O===""||O===w)break;w=O}const b={items:p,total:x};return I&&(b.partial=!0),v.length>0&&(b.partial_errors=v),b},sessionPending(f,p){return Be(vS({client:u,path:{cityName:f,id:p}}),"gc supervisor session pending response was empty")},respondSession(f,p,v){return Be(gS({client:u,path:{cityName:f,id:p},headers:Kt,body:v}),"gc supervisor session respond response was empty")},sessionTranscript(f,p,v){return Be(hS({client:u,path:{cityName:f,id:p},query:{format:v??"conversation"}}),"gc supervisor transcript response was empty")},workflowRun(f,p,v){return Be(ES({client:u,path:{cityName:f,workflow_id:p},...v===void 0?{}:{query:v}}),"gc supervisor workflow response was empty")},formulaDetail(f,p,v){return Be(rS({client:u,path:{cityName:f,name:p},query:v}),"gc supervisor formula detail response was empty")},mutationHeaders(){return{...Kt}}}}function Qe(){return Bm??=yv(),Bm}function zS(t){const r=_v(t),i=zm.get(r);if(i!==void 0)return i;const s=yv({timeoutMs:r});return zm.set(r,s),s}function _v(t){return typeof t=="number"&&Number.isFinite(t)&&t>0?t:BS}function TS(t,r){return async(i,s)=>{const u=new AbortController,f=new Sn(void 0,`gc supervisor request timed out after ${r}ms`,void 0),p=CS(i,s);p?.aborted&&u.abort(p.reason);const v=()=>u.abort(p?.reason);p?.addEventListener("abort",v,{once:!0});let x;const I=new Promise((C,O)=>{x=setTimeout(()=>{u.abort(f),O(f)},r)}),w=new Request(i,{...s,signal:u.signal}),b=t(w);try{return await Promise.race([b,I])}finally{x!==void 0&&clearTimeout(x),p?.removeEventListener("abort",v)}}}function CS(t,r){return r?.signal!==void 0?r.signal:t instanceof Request?t.signal:null}async function RS(t,r){const i=pn("list agent pending interactions"),s=NS(r),u=t.flatMap(p=>{const v=p.session?.name;if(v===void 0)return[];const x=s.get(v);return x===void 0?[]:[{agentName:p.name,sessionId:x,sessionName:v}]});return(await Promise.all(u.map(async p=>{const v=await Qe().sessionPending(i,p.sessionId);return v.pending===void 0?null:{...p,pending:v.pending}}))).filter(p=>p!==null)}async function N9(t,r){const i=pn("respond to agent pending interaction");return Qe().respondSession(i,t,r)}function P9(t){return`gc agent attach ${PS(t)}`}function NS(t){const r=new Map;for(const i of t)i.session_name!==void 0&&r.set(i.session_name,i.id);return r}function PS(t){return/^[A-Za-z0-9_./:-]+$/.test(t)?t:`'${t.replaceAll("'","'\\''")}'`}const jS=1e3,AS=200,OS=1e3,$S=new Set(["feature","bug","task","epic","chore","decision"]);async function DS(t={}){const r=t.city??pn("list supervisor beads"),i=t.limit??jS,s=t.rigFilter?.trim()??"",u=t.includeClosed??!1,f=t.includeBookkeeping??!1,p={limit:i,...u?{all:!0}:{},...s.length===0?{}:{rig:s}},v=t.signal===void 0?await Qe().listBeads(r,p):await Qe().listBeads(r,p,t.signal),x=Iv(v.items??[]),I=u?x:x.filter(C=>C.status!=="closed"),w=f?I:I.filter(MS),b=xv(v.total);return{items:w,total:w.length,...b===void 0?{}:{upstream_total:b},upstream_fetched:x.length,fetch_limit:i}}async function j9(t,r={}){const i=pn("list supervisor assigned beads"),s=qS(t),u=r.limit??AS,f=r.includeClosed??!1;if(s.length===0)return{items:[],total:0,upstream_fetched:0,fetch_limit:u};const p=await Promise.all(s.map(I=>Qe().listBeads(i,{assignee:I,limit:u,...f?{all:!0}:{}}))),v=Iv(p.flatMap(I=>I.items??[])),x=LS(p);return{items:v,total:v.length,...x===void 0?{}:{upstream_total:x},upstream_fetched:v.length,fetch_limit:u}}async function A9(t){const r=pn("fetch supervisor bead");try{return await Qe().getBead(r,t)}catch(i){if(!(i instanceof Sn)||i.status!==404)throw i;const u=((await Qe().listBeads(r,{limit:OS})).items??[]).find(f=>f.id===t);if(u!==void 0)return u;throw i}}function MS(t){return!(!$S.has(t.issue_type)||Array.isArray(t.labels)&&t.labels.some(r=>r.startsWith("gc:")))}function xv(t){if(typeof t=="number")return t;if(typeof t=="bigint")return Number(t)}function LS(t){let r=0;for(const i of t){const s=xv(i.total);if(s===void 0)return;r+=s}return r}function Iv(t){const r=new Set,i=[];for(const s of t)r.has(s.id)||(r.add(s.id),i.push(s));return i}function qS(t){const r=new Set,i=[];for(const s of t){const u=s.trim();u.length===0||r.has(u)||(r.add(u),i.push(u))}return i}const O9=[100,500,1e3],Pc=100,$9=["24h","7d","all"],FS="all",US={"24h":1440*60*1e3,"7d":10080*60*1e3};async function jc(t,r,i,s=Pc,u=FS,f=Date.now()){const p=pn("list supervisor mail"),v=await Qe().listMail(p,{limit:s}),x=v.items??[],I=VS(ZS(x,t,r,i),u,f);return I.sort(HS),{...v,items:I,total:I.length,upstream_total:x.length,upstream_fetched:x.length,fetch_limit:s}}async function D9(t,r,i,s=Pc){const u=pn("fetch supervisor mail thread");try{const f=await Qe().mailThread(u,t);return Tm(f)}catch(f){if(!(f instanceof Sn)||f.status!==404)throw f;const p=await jc("all",r,i,s),v=p.items.filter(x=>x.thread_id===t);return Tm({...p,items:v,total:v.length})}}function Tm(t){const r=GS(t.items??[]).sort(XS);return{...t,items:r,total:r.length}}function ZS(t,r,i,s){const u=WS(i,s);return r==="all"?[...t]:r==="inbox"?t.filter(f=>f.to.toLowerCase()===u):t.filter(f=>f.from.toLowerCase()===u)}function VS(t,r,i){if(r==="all")return[...t];const s=i-US[r];return t.filter(u=>{const f=Date.parse(u.created_at);return Number.isFinite(f)&&f>=s})}function WS(t,r){const i=t.toLowerCase();return i===r.operatorAlias.toLowerCase()?r.operatorWireAlias:i}function GS(t){const r=new Set,i=[];for(const s of t)r.has(s.id)||(r.add(s.id),i.push(s));return i}function HS(t,r){return r.created_at.localeCompare(t.created_at)}function XS(t,r){return t.created_at.localeCompare(r.created_at)}function Ev(t,r){if(t===void 0||t.length===0)return null;const i=Date.parse(t);if(!Number.isFinite(i))return null;const s=r-i;return s>=0?s:null}function wv(t){const r=Math.max(1,Math.round(t/36e5));return r<48?`${r}h`:`${Math.round(r/24)}d`}const KS=1440*60*1e3,JS=4320*60*1e3;function QS(t,r){const i=[];for(const s of t.escalations){const u=YS(s);u!==null&&i.push(u)}for(const s of t.beads){const u=eb(s,r);u!==null&&i.push(u)}return i}function YS(t){return t.status==="closed"?null:{beadId:t.id,reason:"escalated",severity:"attention",summary:`${t.title} — escalation raised`,updatedAt:t.updated_at??t.created_at}}function eb(t,r){if(t.status!=="open"||tb(t))return null;const i=Ev(t.created_at,r);if(i===null||i=JS;return{beadId:t.id,reason:"ready-unclaimed",severity:s?"attention":"watch",summary:`${t.title} opened ${wv(i)} ago`,updatedAt:t.created_at}}function tb(t){return t.assignee!==void 0&&t.assignee.trim().length>0}function Cm(t,r){const i=`/runs/${encodeURIComponent(t)}`;if(r.status!=="available")return i;const s=new URLSearchParams;return s.set("scope_kind",r.kind),s.set("scope_ref",r.ref),`${i}?${s.toString()}`}const nb={"awaiting-input":"awaiting input",errored:"errored","rate-limited":"rate limited",stalled:"stalled"},ob={respond:"Respond to its prompt.",reset:"Reset the agent.",nudge:"Nudge it to resume."},rb={"awaiting-input":"stuck",errored:"stuck","rate-limited":"warn",stalled:"warn"};function ib(t){return nb[t]}function M9(t){return ob[t]}function L9(t){return rb[t]}const ab=new Set(["gc.store.maintenance.failed","order.failed","request.failed","session.crashed","session.stranded","session.work_query_failed","supervisor.shutdown_requested"]),sb=new Set(["events.rotated","session.quarantined","session.suspended","supervisor.fs_pressure.skipped_tick"]);function lb(t){return ab.has(t.type)?"attention":sb.has(t.type)?"watch":"event"}function ub(t){return t.message??t.subject??t.type}const cb=1440*60*1e3,db=30,pb=2e9,fb=1e9,mb=1e9,vb=512e6,gb="gc:escalation",hb="decision.decide";function yb(t={}){return mi.map(r=>_b(r,t))}function _b(t,r){switch(t){case"activity":return bb(r.activity);case"agents":return Eb(r.agents);case"beads":return wb(r.beads);case"health":return xb(r.health);case"mail":return Sb(r.mail);case"runs":return Ib(r.runs)}}function xb(t){return{id:"health:derived",domain:"health",getItems:()=>$b(t)}}function Ib(t){return{id:"runs:derived",domain:"runs",getItems:()=>kb(t)}}function Eb(t){return{id:"agents:derived",domain:"agents",getItems:()=>Bb(t)}}function wb(t){return{id:"beads:derived",domain:"beads",getItems:()=>zb(t)}}function Sb(t){return{id:"mail:derived",domain:"mail",getItems:()=>Nb(t)}}function bb(t){return{id:"activity:derived",domain:"activity",getItems:()=>jb(t)}}function kb(t){const r=[];if(t===void 0)return r;const i={provenance:t.provenance,fetchedAt:t.fetchedAt};if(t.error!==void 0&&t.error.length>0)return r.push(kt("runs",{id:"runs:unavailable",title:"Run data unavailable",summary:t.error,href:"/runs"})),r;const s=t.summary;if(s===void 0)return r;s.lanesPartial===!0&&r.push(oi("runs",{id:"runs:partial",title:"Run list incomplete",href:"/runs"},i));for(const u of[...s.lanes,...s.blockedLanes])u.health.status!=="available"&&r.push(oi("runs",{id:`runs:${u.id}:health-unavailable`,title:`${u.title} health unavailable`,summary:u.health.error,href:Cm(u.id,u.scope)},i));for(const u of d3(s.blockedLanes))r.push(kt("runs",{id:`runs:${u.id}:blocked`,title:`${u.title} blocked`,summary:u.reason,href:Cm(u.id,u.scope)}));return r}function Bb(t){const r=[];if(t===void 0)return r;if(t.error!==void 0&&t.error.length>0)return r.push(oi("agents",{id:"agents:unavailable",title:"Agent data unavailable",summary:t.error,href:"/agents"})),r;t.partial===!0&&r.push(oi("agents",{id:"agents:partial",title:"Agent list incomplete",href:"/agents"})),t.pendingError!==void 0&&t.pendingError.length>0&&r.push(oi("agents",{id:"agents:pending-unavailable",title:"Agent pending state unavailable",summary:t.pendingError,href:"/agents"}));const i=(t.pendingInteractions??[]).map(s=>({agentName:s.agentName,...s.pending.prompt===void 0?{}:{prompt:s.pending.prompt}}));for(const s of a3(t.items??[],i))r.push(kt("agents",{id:`agents:${s.name}:needs-you`,title:`${s.name} ${ib(s.reason)}`,summary:s.detail,href:`/agents/${encodeURIComponent(s.name)}`}));return r}function zb(t){const r=[];if(t===void 0)return r;t.error!==void 0&&t.error.length>0&&r.push(kt("beads",{id:"beads:unavailable",title:"Bead data unavailable",summary:t.error,href:"/beads"})),t.partial===!0&&r.push(Yn("beads",{id:"beads:partial",title:"Bead list incomplete",href:"/beads"})),t.decisionsError!==void 0&&t.decisionsError.length>0&&r.push(kt("beads",{id:"beads:decisions-unavailable",title:"Decision queue unavailable",summary:t.decisionsError,href:"/beads"})),t.escalationsError!==void 0&&t.escalationsError.length>0&&r.push(kt("beads",{id:"beads:escalations-unavailable",title:"Escalation queue unavailable",summary:t.escalationsError,href:"/beads"}));for(const u of t.decisions??[])r.push(Rb(u));const i=t.nowMs??Date.now(),s=(t.items??[]).filter(u=>!Cb(u,t.decisionLabel));for(const u of QS({beads:s,escalations:t.escalations??[]},i)){const f=u.severity==="attention"?kt:Yn;r.push(f("beads",{id:`beads:${u.beadId}:${u.reason}`,title:`${u.beadId} ${Tb(u.reason)}`,summary:u.summary,href:Sv(u.beadId),updatedAt:u.updatedAt}))}return r}function Tb(t){return t==="escalated"?"escalated":"unclaimed"}function Sv(t){const r=new URLSearchParams;return r.set("bead",t),`/beads?${r.toString()}`}function Cb(t,r){return(t.labels??[]).includes(r)}function Rb(t){const r=t.metadata?.[hb];return kt("beads",{id:`beads:${t.id}:mayor-decision`,title:t.title,href:Sv(t.id),updatedAt:t.updated_at??t.created_at,...r!==void 0&&r.trim().length>0?{summary:r}:{}})}function Nb(t){const r=[];if(t===void 0)return r;t.error!==void 0&&t.error.length>0&&r.push(kt("mail",{id:"mail:unavailable",title:"Mail data unavailable",summary:t.error,href:"/mail"})),t.partial===!0&&r.push(Yn("mail",{id:"mail:partial",title:"Mail list incomplete",href:"/mail"}));const i=t.nowMs??Date.now();for(const s of _3(t.items??[])){const u=Ev(s.created_at,i),f=u!==null&&u>=cb;r.push(kt("mail",{id:`mail:${s.id}:${f?"unread-stale":"unread"}`,title:s.subject,summary:f?`from ${s.from}, unread for ${wv(u)}`:`from ${s.from}`,href:Pb(s.id),updatedAt:s.created_at}))}return r}function Pb(t){const r=new URLSearchParams;return r.set("message",t),`/mail?${r.toString()}`}function jb(t){const r=[];if(t===void 0)return r;t.deploysError!==void 0&&t.deploysError.length>0&&r.push(kt("activity",{id:"activity:deploys-unavailable",title:"Deploy data unavailable",summary:t.deploysError,href:"/activity"})),t.eventsDegraded!==void 0&&t.eventsDegraded.length>0&&r.push(Yn("activity",{id:"activity:events-degraded",title:"Event stream degraded",summary:t.eventsDegraded,href:"/activity"})),t.eventsError!==void 0&&t.eventsError.length>0&&r.push(Yn("activity",{id:"activity:events-unavailable",title:"Event history unavailable",summary:t.eventsError,href:"/activity"})),t.eventsPartial===!0&&r.push(Yn("activity",{id:"activity:events-partial",title:"Event history incomplete",href:"/activity"})),Ab(r,t.events??[]);const i=t.deploys;if(i===void 0)return r;i.failed_marker&&r.push(kt("activity",{id:"activity:failed-marker",title:"Deploy failed marker present",href:"/activity"}));for(const s of i.items)s.status==="failed"?r.push(kt("activity",{id:`activity:deploy:${s.at}:failed`,title:"Deploy failed",summary:s.detail,href:"/activity",updatedAt:s.at})):s.status==="in-progress"&&r.push(Yn("activity",{id:`activity:deploy:${s.at}:in-progress`,title:"Deploy in progress",summary:s.detail,href:"/activity",updatedAt:s.at}));return r}function Ab(t,r){for(const i of r){const s=lb(i);if(s==="event")continue;const u=s==="attention"?kt:Yn;t.push(u("activity",{id:`activity:event:${String(i.seq)}:${i.type}`,title:i.type,summary:ub(i),href:Ob(i),updatedAt:i.ts}))}}function Ob(t){return`/activity?${new URLSearchParams({mode:"events",type:t.type}).toString()}`}function $b(t){const r=[];return t===void 0||(t.dashboardError!==void 0&&t.dashboardError.length>0&&r.push(to({id:"health:dashboard-health-unavailable",title:"Dashboard health unavailable",summary:t.dashboardError})),t.supervisor!==void 0&&Db(r,t.supervisor),t.system!==void 0&&(Mb(r,t.system),Lb(r,t.system)),t.trend!==void 0&&!t.trend.available&&r.push(Eo({id:"health:dolt-noms-unavailable",title:"Dolt-noms trend unavailable",summary:t.trend.reason}))),r}function Db(t,r){if(r.status==="unavailable"){t.push(to({id:"health:supervisor-unreachable",title:"Supervisor unreachable",summary:r.error}));return}const i=r.data;i.status!=="ok"&&t.push(to({id:"health:supervisor-not-ok",title:`Supervisor ${i.status}`})),i.city===void 0&&t.push(Eo({id:"health:supervisor-city-missing",title:"Supervisor city missing",summary:"city was absent from generated supervisor health"})),i.version===void 0&&t.push(Eo({id:"health:supervisor-version-missing",title:"Supervisor version missing",summary:"version was absent from generated supervisor health"}))}function Mb(t,r){const i=r.admin;i.uptime_sec=pb?t.push(to({id:"health:dashboard-process-rss-high",title:"Dashboard RSS high",summary:Na(i.rss.value)})):i.rss.status==="available"&&i.rss.value>=fb&&t.push(Eo({id:"health:dashboard-process-rss-elevated",title:"Dashboard RSS elevated",summary:Na(i.rss.value)})),i.heap_used_bytes>=mb?t.push(to({id:"health:dashboard-process-heap-high",title:"Dashboard heap high",summary:Na(i.heap_used_bytes)})):i.heap_used_bytes>=vb&&t.push(Eo({id:"health:dashboard-process-heap-elevated",title:"Dashboard heap elevated",summary:Na(i.heap_used_bytes)}))}function Lb(t,r){const i=r.host.memory.status==="available"?Rm(r.host.memory.value.free_mem_bytes,r.host.memory.value.total_mem_bytes):null;i!==null&&i<.05?t.push(to({id:"health:memory-critical",title:"Host memory critical",summary:`${Math.round(i*100)}% free`})):i!==null&&i<.1&&t.push(Eo({id:"health:memory-low",title:"Host memory low",summary:`${Math.round(i*100)}% free`}));const s=r.host.load.status==="available"?r.host.load.value.load_avg_1:null;if(s===null)return;const u=Rm(s,r.host.cpu_count);u!==null&&u>1.5?t.push(to({id:"health:load-high",title:"Host load high",summary:`${s.toFixed(2)} load across ${r.host.cpu_count} CPUs`})):u!==null&&u>1&&t.push(Eo({id:"health:load-elevated",title:"Host load elevated",summary:`${s.toFixed(2)} load across ${r.host.cpu_count} CPUs`}))}function Na(t){return t>=1e9?`${(t/1e9).toFixed(1)} GB`:t>=1e6?`${Math.round(t/1e6)} MB`:t>=1e3?`${Math.round(t/1e3)} KB`:`${t} B`}function Rm(t,r){return r<=0?null:t/r}function to(t){return{domain:"health",severity:"attention",href:"/health",current:!0,actionable:!0,...t}}function kt(t,r){return{domain:t,severity:"attention",current:!0,actionable:!0,...r}}function Yn(t,r){return{domain:t,severity:"watch",current:!0,actionable:!1,...r}}function oi(t,r,i){return{domain:t,severity:"unavailable",current:!0,actionable:!1,...r,...i?.provenance===void 0?{}:{provenance:i.provenance},...i?.fetchedAt===void 0?{}:{fetchedAt:i.fetchedAt}}}function Eo(t){return{domain:"health",severity:"watch",href:"/health",current:!0,actionable:!1,...t}}const qb=1e3,Fb=100,Ub="24h",Zb=2500,Vb=[250,500,1e3,2e3],Wb=5e3,Gb="city-not-found";function Hb(t,r){const i=Xa(),s=i??"no-city",{decisionLabel:u,operatorWireAlias:f}=t,p=T.useMemo(()=>Xb(r),[r]),v=En(`attention:agents:${s}`,()=>Kb(i)),x=En(`attention:beads:${s}:${u}`,L=>Jb(i,u,L)),I=En(`attention:mail:${s}:${f}`,()=>tk(i,t)),w=En(`attention:activity:${s}`,()=>nk(i)),b=En(`attention:health:${s}`,()=>ok(i)),C=x.data,O=x.refresh;return T.useEffect(()=>{if(C?.cityUnavailable!==!0)return;const L=setTimeout(()=>{O()},Wb);return()=>clearTimeout(L)},[C,O]),T.useMemo(()=>yb(rk({activity:w.data,agents:v.data,beads:C,health:b.data,mail:I.data,runs:p})),[w.data,v.data,C,b.data,I.data,p])}function Xb(t){if(t!==void 0)return t.status==="error"?{error:t.error,provenance:"error"}:{summary:t.data,provenance:t.status,fetchedAt:t.fetchedAt}}async function Kb(t){if(t===null)return{};try{const r=await Qe().listAgents(t),i={items:r.items??[],partial:r.partial===!0};try{const s=await Qe().listSessions(t);i.pendingInteractions=await RS(r.items??[],s.items??[])}catch(s){i.pendingError=Lt(s,"agent pending state unavailable")}return i}catch(r){return{error:Lt(r,"agent list unavailable")}}}async function Jb(t,r,i){if(t===null)return{decisionLabel:r};const s=()=>Promise.allSettled([DS({limit:qb,city:t,...i===void 0?{}:{signal:i}}),Yb(t,r,i),ek(t,i)]);ni(i);let u=await s();ni(i);for(const w of Vb){if(!u.some(Nm))break;await Qb(w,i),ni(i),u=await s(),ni(i)}const[f,p,v]=u,x={nowMs:Date.now(),decisionLabel:r},I=u.find(Nm);if(I!==void 0&&I.status==="rejected"){const w=Lt(I.reason,"city unavailable");return{...x,cityUnavailable:!0,error:w,decisionsError:w,escalationsError:w}}return f.status==="fulfilled"?(x.items=f.value.items,x.partial=f.value.partial===!0):x.error=Lt(f.reason,"bead list unavailable"),p.status==="fulfilled"?x.decisions=p.value.items??[]:x.decisionsError=Lt(p.reason,"decision queue unavailable"),v.status==="fulfilled"?x.escalations=v.value.items??[]:x.escalationsError=Lt(v.reason,"escalation queue unavailable"),x}function Nm(t){return t.status==="rejected"&&t.reason instanceof Sn&&t.reason.status===404&&t.reason.code===Gb}function Qb(t,r){return r===void 0?new Promise(i=>setTimeout(i,t)):(ni(r),new Promise((i,s)=>{const u=setTimeout(()=>{r.removeEventListener("abort",f),i()},t),f=()=>{clearTimeout(u),s(bv(r))};r.addEventListener("abort",f,{once:!0})}))}function ni(t){if(t?.aborted===!0)throw bv(t)}function bv(t){return t.reason??new DOMException("The operation was aborted","AbortError")}async function Yb(t,r,i){return Qe().listBeads(t,{label:r,status:"open"},i)}async function ek(t,r){return Qe().listBeads(t,{label:gb,status:"open"},r)}async function tk(t,r){if(t===null)return{};try{const i=await jc("inbox",r.operatorAlias,r,Pc);return{items:i.items??[],nowMs:Date.now(),partial:i.partial===!0}}catch(i){return{error:Lt(i,"mail list unavailable")}}}async function nk(t){const[r,i]=await Promise.allSettled([lr.listBuilds(),t===null?Promise.resolve(null):Qe().listEvents(t,{limit:Fb,since:Ub})]),s={};return r.status==="fulfilled"?s.deploys=r.value:s.deploysError=Lt(r.reason,"deploy activity unavailable"),i.status==="fulfilled"?i.value!==null&&(s.events=i.value.items??[],s.eventsPartial=i.value.partial===!0,i.value.partial_errors!==null&&i.value.partial_errors!==void 0&&(s.eventsDegraded=i.value.partial_errors.join("; "))):s.eventsError=Lt(i.reason,"event history unavailable"),s}async function ok(t){if(t===null)return{};const[r,i,s]=await Promise.allSettled([lr.systemHealth(),zS(Zb).cityHealth(t),lr.doltTrend()]),u={},f=[];return r.status==="fulfilled"?u.system=r.value:f.push(Lt(r.reason,"dashboard health unavailable")),i.status==="fulfilled"?u.supervisor={status:"available",data:i.value}:u.supervisor={status:"unavailable",error:Lt(i.reason,"supervisor health unavailable")},s.status==="fulfilled"?u.trend=s.value:f.push(Lt(s.reason,"dolt-noms trend unavailable")),f.length>0&&(u.dashboardError=f.join("; ")),u}function rk(t){const r={};for(const[i,s]of Object.entries(t))s!==void 0&&(r[i]=s);return r}async function nr(t){const r={Accept:"application/json","Content-Type":"application/json","X-GC-Request":"dashboard"};try{const i=await fetch("/api/client-errors",{method:"POST",headers:r,credentials:"same-origin",keepalive:!0,body:JSON.stringify(t)});return i.ok?{status:"reported"}:{status:"failed",error:`client error report failed with ${i.status}`}}catch(i){return{status:"failed",error:Yo(i)}}}class kv extends T.Component{state={crashed:!1};static getDerivedStateFromError(){return{crashed:!0}}componentDidCatch(r,i){nr({component:"ErrorBoundary",operation:"componentDidCatch",message:Yo(r)})}render(){return this.state.crashed?M.jsx("main",{className:"max-w-dashboard mx-auto px-4 sm:px-6 lg:px-8 py-12",children:M.jsxs("section",{className:"space-y-4",role:"alert",children:[M.jsx("h1",{className:"text-display font-semibold text-fg",children:"Dashboard view failed."}),M.jsx("p",{className:"text-body text-fg-muted",children:"The error was reported to the local dashboard log. Refresh to retry this view."})]})}):this.props.children}}function ik({label:t,summary:r}){const i=r.attention+r.watch;if(i===0||r.severity===null)return null;const s=i===1?"item":"items";return M.jsx("span",{"aria-label":`${t}: ${i} ${r.severity} ${s}`,className:`ml-1 align-super text-[0.65rem] leading-none tnum ${ak(r.severity)}`,children:i})}function ak(t){return t==="attention"?"text-accent":"text-warn"}function Bv(t,r,i){try{const s=Ac(t).getItem(r);return s===null?{status:"missing"}:{status:"found",value:s}}catch(s){return Oc(t,"getItem",r,i,s)}}function zv(t,r,i,s){try{return Ac(t).setItem(r,i),{status:"stored"}}catch(u){return Oc(t,"setItem",r,s,u)}}function Tv(t,r,i){try{return Ac(t).removeItem(r),{status:"stored"}}catch(s){return Oc(t,"removeItem",r,i,s)}}function Ac(t){return t==="localStorage"?window.localStorage:window.sessionStorage}function Oc(t,r,i,s,u){const f=Yo(u);return nr({component:s,operation:`${t}.${r}`,message:`${i}: ${f}`}),{status:"unavailable",error:f}}const gu="gascity:theme",hu="ThemeContext",Cv=T.createContext(null);function sk(){const t=Bv("localStorage",gu,hu);return t.status==="found"&&(t.value==="light"||t.value==="dark")?t.value:"system"}function lk(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function uk(t){const r=document.documentElement;t==="system"?r.removeAttribute("data-theme"):r.setAttribute("data-theme",t)}function ck({children:t}){const[r,i]=T.useState(sk),[s,u]=T.useState(lk);T.useEffect(()=>{const I=window.matchMedia("(prefers-color-scheme: dark)"),w=()=>u(I.matches?"dark":"light");return I.addEventListener("change",w),()=>I.removeEventListener("change",w)},[]);const f=r==="system"?s:r,p=T.useCallback(I=>{i(I),I==="system"?Tv("localStorage",gu,hu):zv("localStorage",gu,I,hu),uk(I)},[]),v=T.useCallback(()=>{p(f==="dark"?"light":"dark")},[f,p]),x=T.useMemo(()=>({pref:r,resolved:f,set:p,toggle:v}),[r,f,p,v]);return M.jsx(Cv.Provider,{value:x,children:t})}function dk(){const t=T.useContext(Cv);if(t===null)throw new Error("useTheme must be used inside ");return t}const Rv={operatorAlias:"operator",operatorWireAlias:"human",decisionLabel:"needs/operator"},Nv=T.createContext(Rv);function pk({operator:t,children:r}){return M.jsx(Nv.Provider,{value:t,children:r})}function Pv(){return T.useContext(Nv)}function fk(t){return t===void 0?Rv:{operatorAlias:t.operatorAlias,operatorWireAlias:t.operatorWireAlias,decisionLabel:t.decisionLabel}}const mk={ok:"text-ok",warn:"text-warn",stuck:"text-accent",neutral:"text-fg-muted"},vk={ok:"●",warn:"▲",stuck:"■",neutral:"·"};function gk({tone:t,label:r,glyph:i,trailing:s,className:u="",title:f}){return M.jsxs("span",{className:`inline-flex items-baseline gap-1.5 text-body ${mk[t]} ${u}`,title:f,children:[M.jsx("span",{"aria-hidden":!0,className:"text-[0.85em] leading-none translate-y-[1px]",children:i??vk[t]}),M.jsx("span",{children:r}),s&&M.jsx("span",{className:"text-fg-faint text-label uppercase tracking-wider",children:s})]})}function q9(t){switch(t){case"closed":return"neutral";case"in_progress":return"ok";case"blocked":return"stuck";default:return"warn"}}function F9(t){switch(t){case"active":case"running":return"ok";case"rate-limited":case"rate_limited":case"waiting":return"warn";case"failed":case"closed":case"errored":case"stuck":return"stuck";default:return"neutral"}}const jv=T.createContext(!1);function hk({readOnly:t,children:r}){return M.jsx(jv.Provider,{value:t,children:r})}function yk(){return T.useContext(jv)}function _k(t,r){return t?t.readOnly:r!==null}const Av="Read-only mode: mutations are disabled";function U9(){return M.jsx(gk,{tone:"warn",label:"Read-only",title:Av})}const xk="mayor";function Ik(t){const{operator:r,sessionAliases:i,mailFromOrTo:s}=t,u=new Map;for(const O of i){const L=O.toLowerCase();u.has(L)||u.set(L,O)}for(const O of s){const L=O.toLowerCase();u.has(L)||u.set(L,O)}const f=r.toLowerCase(),p=new Set(s.map(O=>O.toLowerCase())),v=[r],x=[],I=[],w=[];for(const[O,L]of u)if(O!==f){if(O===xk){x.push(L);continue}p.has(O)?I.push(L):w.push(L)}const b=(O,L)=>O.toLowerCase().localeCompare(L.toLowerCase());I.sort(b),w.sort(b);const C=[{tier:"you",aliases:v}];return x.length>0&&C.push({tier:"mayor",aliases:x}),I.length>0&&C.push({tier:"active",aliases:I}),w.length>0&&C.push({tier:"other",aliases:w}),C}function Ek(t,r){return t===r?"user":t}function Z9(t){switch(t){case"you":return"You";case"mayor":return"Mayor";case"active":return"Active";case"other":return"Other"}}async function wk(){return Qe().listSessions(pn("list supervisor sessions"))}async function V9(t){const r=await Qe().sessionTranscript(pn("fetch supervisor session transcript"),t,"conversation");return kk(r)}async function W9(t){const r=await Qe().sessionTranscript(pn("fetch structured session transcript"),t,"structured");return Sk(r)}function Sk(t){if(t.format!=="structured")return null;if(!JE(t))throw new Error("Malformed structured transcript response.");return t}function G9(t){return(t.items??[]).map(bk)}function bk(t){const r={id:t.id,template:t.template,session_name:t.session_name,title:t.title,state:t.state,created_at:t.created_at,attached:t.attached,running:t.running,provider:t.provider};return t.alias!==void 0&&(r.alias=t.alias),t.reason!==void 0&&(r.reason=t.reason),t.display_name!==void 0&&(r.display_name=t.display_name),t.last_active!==void 0&&(r.last_active=t.last_active),t.rig!==void 0&&(r.rig=t.rig),t.pool!==void 0&&(r.pool=t.pool),t.agent_kind!==void 0&&(r.agent_kind=t.agent_kind),t.model!==void 0&&(r.model=t.model),t.context_pct!==void 0&&(r.context_pct=t.context_pct),t.context_window!==void 0&&(r.context_window=t.context_window),t.activity!==void 0&&(r.activity=t.activity),r}function kk(t,r=new Date().toISOString()){if(t.format!=="conversation"&&t.format!=="text")throw new Error(`expected conversation transcript, got ${t.format}`);const i=t.turns??[];return{...t,turns:i,total_chars:i.reduce((s,u)=>s+u.text.length,0),captured_at:r,truncated:!1}}const yu="gascity.dashboard.viewingAs",or="ViewingAsContext",Pm=/^[a-z][a-z0-9_./-]{1,63}$/i,jm=[3e4,9e4,27e4];function Bk(t){if(!Number.isInteger(t)||t<0||t>=jm.length)return null;const r=jm[t];return r===void 0?null:r}const Ov=T.createContext(null);function Am(t){const r=Bv("sessionStorage",yu,or);if(r.status==="found"){const i=r.value;if(i.length>0&&i.length<=64)return i}return t}function tu(t,r){t===r?Tv("sessionStorage",yu,or):zv("sessionStorage",yu,t,or)}function zk({children:t}){const r=Pv(),{operatorAlias:i}=r,[s,u]=T.useState(()=>Am(i)),f=T.useRef(i),[p,v]=T.useState([]),[x,I]=T.useState([]),[w,b]=T.useState(!1),[C,O]=T.useState(!1),L=T.useRef(!1),W=T.useRef(!0),D=T.useRef(null),G=T.useCallback(pe=>{u(pe),tu(pe,i)},[i]),ee=T.useCallback(()=>{u(i),tu(i,i)},[i]),J=T.useCallback(async()=>{try{const pe=await wk();if(!W.current)return!0;const we=new Set,Se=[];for(const Ne of pe.items??[]){if(typeof Ne.alias!="string"||!Pm.test(Ne.alias))continue;const Ae=Ne.alias.toLowerCase();we.has(Ae)||(we.add(Ae),Se.push(Ne.alias))}return v(Se),O(!1),!0}catch(pe){return nr({component:or,operation:"loadAliases.sessions",message:Yo(pe)}),!1}},[]),H=T.useCallback(pe=>{if(!W.current)return;const we=Bk(pe);we!==null&&(D.current=setTimeout(()=>{D.current=null,W.current&&J().then(Se=>{W.current&&(Se||H(pe+1))}).catch(Se=>{nr({component:or,operation:"loadAliases.sessionsRetry",message:Yo(Se)})})},we))},[J]),te=T.useCallback(()=>{if(L.current)return;L.current=!0,b(!0);let pe=2;const we=()=>{pe-=1,pe===0&&W.current&&b(!1)};J().then(Se=>{W.current&&(Se||(O(!0),H(0)))}).finally(we),jc("all",i,r).then(Se=>{if(!W.current)return;const Ne=new Set,Ae=[];for(const nt of Se.items)for(const Ye of[nt.from,nt.to]){if(typeof Ye!="string"||Ye.length===0||!Pm.test(Ye))continue;const zt=Ye.toLowerCase();Ne.has(zt)||(Ne.add(zt),Ae.push(Ye))}I(Ae)}).catch(Se=>{nr({component:or,operation:"loadAliases.mail",message:Yo(Se)})}).finally(we)},[J,H,i,r]);T.useEffect(()=>(W.current=!0,()=>{W.current=!1,D.current!==null&&(clearTimeout(D.current),D.current=null)}),[]),T.useEffect(()=>{const pe=f.current;f.current=i,pe!==i&&s===pe&&u(Am(i))},[i,s]);const ue=T.useMemo(()=>Ik({operator:i,sessionAliases:p.includes(s)?p:[...p,s],mailFromOrTo:x}),[p,x,s,i]),ve=T.useMemo(()=>({viewingAs:{alias:s,isOperator:s===i},setAlias:G,resetToOperator:ee,aliasBuckets:ue,aliasesLoading:w,sessionsUnavailable:C,loadAliases:te}),[s,i,G,ee,ue,w,C,te]);return T.useEffect(()=>{const pe=()=>{document.hidden&&s!==i&&(u(i),tu(i,i))};return document.addEventListener("visibilitychange",pe),()=>document.removeEventListener("visibilitychange",pe)},[s,i]),M.jsx(Ov.Provider,{value:ve,children:t})}function Tk(){const t=T.useContext(Ov);if(t===null)throw new Error("useViewingAs must be inside ");return t}const Ck={id:"activity",kind:"core",path:"/activity",nav:{label:"Activity",order:55},element:T.lazy(()=>Rn(()=>import("./Activity-ytxmdj4u.js"),__vite__mapDeps([0,1,2,3,4])).then(t=>({default:t.ActivityPage})))},Rk={id:"health",kind:"core",path:"/health",nav:{label:"Health",order:60},element:T.lazy(()=>Rn(()=>import("./Health-5RAwdGI6.js"),__vite__mapDeps([5,1,2,4,6,3])).then(t=>({default:t.HealthPage})))},$v=[Ck,Rk],Nk={views:"views"};function Pk(t,r){console.warn(`[${t}] ${r}`)}function Dv(t,r){const i=new Set(r??[]);return t.filter(s=>s.kind==="core"||i.has(s.id))}const jk={};function Ak(t,r){const i=[];if(r!==null){const p=jk[r];if(p!==void 0){if(t.some(x=>x.id===p.target))return{view:null,redirectTo:p.redirectTo,source:"env",warnings:i};i.push(`DEFAULT_VIEW="${r}" alias targets the "${p.target}" view, which is not enabled in this deployment (known enabled ids: ${t.map(x=>x.id).join(", ")||"(none)"}); falling through to descriptor / ambient-home`)}else{const v=t.find(x=>x.id===r);if(v!==void 0)return{view:v,source:"env",warnings:i};i.push(`DEFAULT_VIEW="${r}" does not match any enabled view (known enabled ids: ${t.map(x=>x.id).join(", ")||"(none)"}); falling through to descriptor / ambient-home`)}}const s=t.filter(p=>p.defaultRoute===!0),[u,...f]=s;if(u!==void 0&&f.length===0)return{view:u,source:"descriptor",warnings:i};if(u!==void 0){const v=[...s].sort($k)[0]??u;return i.push(`multiple views declare defaultRoute: true (${s.map(x=>x.id).join(", ")}); picking "${v.id}" by lowest nav.order`),{view:v,source:"descriptor",warnings:i}}return{view:null,source:"fallback",warnings:i}}function Ok(t,r){const i=Ak(t,r);for(const s of i.warnings)Pk(Nk.views,s);return i}function $k(t,r){const i=t.nav?.order??Number.POSITIVE_INFINITY,s=r.nav?.order??Number.POSITIVE_INFINITY;return i!==s?i-s:t.id.localeCompare(r.id)}const Dk=[{to:"/",label:"Home",end:!0,order:10},{to:"/agents",label:"Agents",order:20},{to:"/beads",label:"Beads",order:30},{to:"/runs",label:"Runs",order:40},{to:"/mail",label:"Mail",order:50}],Mk={"/agents":"agents","/beads":"beads","/runs":"runs","/mail":"mail","/activity":"activity","/health":"health"};function Lk(){const{resolved:t,toggle:r}=dk(),{viewingAs:i}=Tk(),{operatorAlias:s}=Pv(),u=yk(),f=Pw(),{data:p}=En("config",()=>lr.config()),{data:v}=En("cities",()=>Qe().listCities()),x=Xa(),I=v?.items??[],w=x??p?.cityName??"",b=w===""||I.some(G=>G.name===w),C=I.length>1||!b,O=G=>{G!==x&&window.location.assign(`/city/${encodeURIComponent(G)}/`)},L=T.useMemo(()=>{const ee=Dv($v,p?.enabledModules??null).flatMap(J=>J.nav===null?[]:[{to:J.path,label:J.nav.label,end:J.path==="/",order:J.nav.order}]);return[...Dk,...ee].sort((J,H)=>J.order-H.order)},[p?.enabledModules]),{pathname:W}=Tn(),D=!i.isOperator&&W.startsWith("/mail");return M.jsx("header",{className:"border-b border-rule",children:M.jsxs("div",{className:"max-w-dashboard mx-auto px-4 sm:px-6 lg:px-8 py-5 flex items-baseline gap-x-6 lg:gap-x-8 gap-y-2 flex-wrap",children:[M.jsxs("div",{className:"flex items-baseline gap-3 min-w-0",children:[M.jsx("span",{className:"text-title font-semibold tracking-tight text-fg",children:"gas city"}),M.jsx("span",{className:"text-fg-muted","aria-hidden":"true",children:"·"}),C?M.jsx("label",{className:"sr-only",htmlFor:"city-switcher",children:"Switch city"}):null,C?M.jsxs("select",{id:"city-switcher",value:w,onChange:G=>O(G.target.value),className:"text-label uppercase tracking-wider text-fg-muted bg-transparent border-0 focus-mark cursor-pointer hover:text-fg transition-colors duration-150 ease-out-quart",children:[!b&&w!==""?M.jsxs("option",{value:w,disabled:!0,children:[w," (unknown)"]}):null,I.map(G=>M.jsxs("option",{value:G.name,children:[G.name,G.running?"":" (stopped)"]},G.name))]}):M.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:w||"city"}),D&&M.jsxs("span",{className:"text-label uppercase tracking-wider text-accent ml-3",children:["· reading as ",Ek(i.alias,s)]}),u&&M.jsx("span",{title:Av,className:"text-label uppercase tracking-wider text-warn ml-3",children:"· read-only"})]}),M.jsx("nav",{className:"flex-1",children:M.jsx("ul",{className:"flex items-baseline gap-x-5 lg:gap-x-7 gap-y-1 flex-wrap",children:L.map(G=>{const ee=Mk[G.to];return M.jsx("li",{children:M.jsxs(Y0,{to:G.to,end:G.end??!1,className:({isActive:J})=>["text-title transition-colors duration-150 ease-out-quart focus-mark",J?"text-fg font-semibold":"text-fg-muted font-medium hover:text-fg"].join(" "),children:[G.label,ee!==void 0&&M.jsx(ik,{label:G.label,summary:f.byDomain[ee]})]})},G.to)})})}),M.jsx("button",{type:"button",onClick:r,"aria-label":`Switch to ${t==="dark"?"light":"dark"} theme`,className:"text-label uppercase tracking-wider text-fg-muted hover:text-fg transition-colors duration-150 ease-out-quart focus-mark",children:t==="dark"?"Light":"Dark"})]})})}function qk({children:t}){return M.jsxs("div",{className:"min-h-screen bg-surface text-fg antialiased",children:[M.jsx(Lk,{}),M.jsx("main",{className:"max-w-dashboard mx-auto px-4 sm:px-6 lg:px-8 py-12",children:t})]})}const Mv=T.createContext(null);function Fk({children:t,intervalMs:r=1e3}){const[i,s]=T.useState(()=>Date.now());return T.useEffect(()=>{const u=window.setInterval(()=>{s(Date.now())},r);return()=>{window.clearInterval(u)}},[r]),M.jsx(Mv.Provider,{value:i,children:t})}function H9(){const t=T.useContext(Mv);if(t===null)throw new Error("useNow must be called inside a NowProvider.");return t}const Uk=2e3,Zk=2500;function Vk(t,r,i={}){const[s,u]=T.useState("connecting"),f=T.useRef(r);f.current=r;const p=T.useRef(i.matches);p.current=i.matches;const v=T.useRef(i.coalesceMs);v.current=i.coalesceMs;const x=t.join(","),I=T.useRef(0),w=T.useRef(null);return T.useEffect(()=>{if(t.length===0){u("closed");return}let b=null,C=!1,O=null,L=null,W=1e3,D=!1;const G=()=>{L!==null&&(clearTimeout(L),L=null)},ee=ue=>{D||(D=!0,Wk(ue))},J=()=>{I.current=Date.now(),f.current()},H=()=>{const ue=v.current??Zk,ve=Date.now()-I.current;ve>=ue?(w.current&&(clearTimeout(w.current),w.current=null),J()):w.current===null&&(w.current=setTimeout(()=>{w.current=null,C||J()},ue-ve))},te=()=>{const ue=globalThis.EventSource;if(typeof ue!="function"){u("closed");return}const ve=Xa();if(ve===null){u("closed");return}const pe=new ue(Qe().cityEventStreamUrl(ve));b=pe,u("connecting"),L=setTimeout(()=>{C||b!==pe||pe.readyState===ue.CLOSED||u("open")},Uk),b.onopen=()=>{C||(G(),u("open"),W=1e3)};const we=Se=>{if(C)return;let Ne=null;try{Ne=JSON.parse(Se.data)}catch{u("degraded"),ee("invalid JSON");return}if(!Gk(Ne)){u("degraded"),ee("missing string event type");return}const Ae=Ne.type;if(typeof Ae!="string"){u("degraded"),ee("missing string event type");return}u("open");for(const nt of t)if(Ae.startsWith(nt)){const Ye=Ne;(p.current?.(Ye)??!0)&&H();break}};b.onmessage=we,b.addEventListener("event",we),b.onerror=()=>{C||(G(),u("closed"),b?.close(),b=null,O=setTimeout(()=>{W=Math.min(W*2,3e4),te()},W))}};return te(),()=>{C=!0,O&&clearTimeout(O),G(),w.current&&(clearTimeout(w.current),w.current=null),b?.close()}},[x]),s}function Wk(t){nr({component:"gc-events",operation:"parse event",message:`Malformed gc event payload: ${t}.`})}function Gk(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}const Hk=60*1e3;async function $c(){const t=new Date().toISOString();try{const r=await lr.runSummary();return{source:"runs",status:"fresh",fetchedAt:t,staleAt:new Date(Date.parse(t)+Hk).toISOString(),error:{kind:"none"},data:r}}catch(r){return{source:"runs",status:"error",error:Qk(r,"formula runs unavailable")}}}function Xk(){return $c()}function Kk(){return $c()}function Jk(){return $c()}function Qk(t,r){return t instanceof Error&&t.message.trim().length>0?t.message:r}const Om=1e4,Yk=[2e3,5e3,1e4];function e9(){const t=Xa(),r=T.useRef(null),i=T.useRef(!1),s=T.useCallback(async()=>{const te=await Xk().catch(ve=>({source:"runs",status:"error",error:ve instanceof Error?ve.message:"formula runs unavailable"}));if(te.status!=="error")return i.current=!1,te;const ue=r.current;return ue===null?te:(i.current=!0,{...ue,status:"stale"})},[]),u=T.useCallback(async()=>{const te=await Kk().catch(ve=>({source:"runs",status:"error",error:ve instanceof Error?ve.message:"formula runs unavailable"}));if(te.status!=="error")return te;const ue=r.current;return ue===null?te:(i.current=!0,{...ue,status:"stale"})},[]),{data:f,loading:p,error:v,refresh:x,cheapRefresh:I}=En(`runs:summary:${t??"no-city"}`,Jk,{refreshFetcher:s,sseRefreshFetcher:u});f!==void 0&&f.status!=="error"&&(r.current=f);const w=f??null,b=T.useRef(null);b.current=w?.status??null;const C=T.useRef(p);C.current=p;const O=T.useRef(0),L=T.useRef(null);T.useEffect(()=>{if(w===null||w.status==="error")return;const te=t??"no-city";L.current!==te&&(L.current=te,x().catch(()=>{L.current=null}))},[t,x,w]);const W=T.useRef(0);T.useEffect(()=>{if(w===null)return;if(!(w.status==="error"?!0:i.current||w.data.lanesPartial===!0&&w.data.lanes.length===0&&w.data.blockedLanes.length===0)){W.current=0;return}const ue=Yk[W.current];if(ue===void 0)return;W.current+=1;const ve=setTimeout(()=>{x()},ue);return()=>clearTimeout(ve)},[w,x]);const D=T.useRef(!1),G=T.useRef(null),ee=T.useCallback(()=>{G.current!==null&&(clearTimeout(G.current),G.current=null),O.current=Date.now(),I().catch(()=>{O.current=0})},[I]),J=T.useCallback(()=>{if(b.current===null||b.current==="fixture")return;if(C.current){D.current=!0;return}Date.now()-O.current{if(p||!D.current)return;D.current=!1;const te=Math.max(0,Om-(Date.now()-O.current));return G.current=setTimeout(ee,te),()=>{G.current!==null&&(clearTimeout(G.current),G.current=null)}},[p,ee]);const H=Vk([v3.bead],J);return{source:f,loading:p,error:v,refresh:x,sseState:H}}const Lv=T.createContext(null);function t9({children:t}){const r=e9();return M.jsx(Lv.Provider,{value:r,children:t})}function n9(){const t=T.useContext(Lv);if(t===null)throw new Error("useRunSummary must be used within a RunSummaryProvider");return t}const o9=T.lazy(()=>Rn(()=>import("./Agents-QKqo7Hxx.js"),__vite__mapDeps([7,8,1,9,10,2,11,3,12,6,13,14])).then(t=>({default:t.AgentsPage}))),r9=T.lazy(()=>Rn(()=>import("./AgentDetail-D04RKQJE.js"),__vite__mapDeps([15,16,6,17,12,3,10,2,8])).then(t=>({default:t.AgentDetailPage}))),i9=T.lazy(()=>Rn(()=>import("./CockpitHome-BpfJnXxo.js"),__vite__mapDeps([18,2])).then(t=>({default:t.CockpitHomePage}))),a9=T.lazy(()=>Rn(()=>import("./Beads-DIx9v9cO.js"),__vite__mapDeps([19,1,16,6,17,12,3,10,20,9,2,14])).then(t=>({default:t.BeadsPage}))),s9=T.lazy(()=>Rn(()=>import("./Mail-T1YOUrw8.js"),__vite__mapDeps([21,9,1,20,13,10,2,17,3])).then(t=>({default:t.MailPage}))),l9=T.lazy(()=>Rn(()=>import("./FormulaRunDetail-BceCG60V.js"),__vite__mapDeps([22,2,16,6,17,12,3,10,23])).then(t=>({default:t.FormulaRunDetailPage}))),u9=T.lazy(()=>Rn(()=>import("./Runs-BUkrIZEc.js"),__vite__mapDeps([24,1,2,11,3,23])).then(t=>({default:t.RunsPage})));function c9(){const{data:t,error:r}=En("config",()=>lr.config()),i=t?.enabledModules??null,s=t?.defaultView??null,u=_k(t,r),f=fk(t),p=T.useMemo(()=>Dv($v,i),[i]),v=T.useMemo(()=>Ok(p,s),[p,s]),x=v.view?.element??null,I=v.redirectTo??null;return M.jsx(pk,{operator:f,children:M.jsx(zk,{children:M.jsx(Fk,{children:M.jsx(hk,{readOnly:u,children:M.jsx(t9,{children:M.jsx(d9,{operator:f,children:M.jsxs(qk,{children:[r!==null&&M.jsx(f9,{message:r}),M.jsx(p9,{defaultRedirectTo:I,DefaultViewElement:x,enabledViews:p})]})})})})})})})}function d9({operator:t,children:r}){const{source:i}=n9(),s=Hb(t,i);return M.jsx(Nw,{contributors:s,children:r})}function p9({defaultRedirectTo:t,DefaultViewElement:r,enabledViews:i}){const{pathname:s}=Tn();return M.jsx(kv,{children:M.jsx(T.Suspense,{fallback:null,children:M.jsxs(L0,{children:[M.jsx(an,{path:"/",element:t!==null?M.jsx(D0,{to:t,replace:!0}):r!==null?M.jsx(r,{}):M.jsx(i9,{})}),M.jsx(an,{path:"/agents",element:M.jsx(o9,{})}),M.jsx(an,{path:"/agents/:slug",element:M.jsx(r9,{})}),M.jsx(an,{path:"/beads",element:M.jsx(a9,{})}),M.jsx(an,{path:"/runs",element:M.jsx(u9,{})}),M.jsx(an,{path:"/runs/:runId",element:M.jsx(l9,{})}),M.jsx(an,{path:"/mail",element:M.jsx(s9,{})}),i.map(u=>{const f=u.element;return M.jsx(an,{path:u.path,element:M.jsx(f,{})},u.id)}),M.jsx(an,{path:"*",element:M.jsx(m9,{})})]})})},s)}function f9({message:t}){return M.jsxs("section",{role:"alert",className:"mb-8 border border-warn/40 rounded-sm px-4 py-3 text-body text-fg-muted",children:[M.jsx("span",{className:"text-warn",children:"config unavailable:"})," ",t," · some controls may be disabled until it loads."]})}function m9(){return M.jsxs("section",{"aria-labelledby":"not-found-title",className:"space-y-3",children:[M.jsx("h1",{id:"not-found-title",className:"text-5xl font-semibold tracking-tight text-fg",children:"Page not found"}),M.jsx("p",{className:"text-title text-fg-muted",children:"No dashboard route matches this path."})]})}const v9={default:"border border-rule text-fg-muted hover:text-fg hover:bg-surface-tint",accent:"border border-accent text-accent hover:bg-accent hover:text-surface",quiet:"border border-transparent text-fg-muted hover:text-fg"},g9={sm:"px-2.5 py-1 text-label uppercase tracking-wider",md:"px-3.5 py-1.5 text-body"};function h9({tone:t="default",size:r="sm",className:i="",children:s,...u}){return M.jsx("button",{...u,className:`inline-flex items-center gap-1.5 rounded-sm transition-colors duration-150 ease-out-quart focus-mark disabled:opacity-40 disabled:cursor-not-allowed ${v9[t]} ${g9[r]} ${i}`,children:s})}const y9="https://docs.gascity.com/getting-started/quickstart",_9=/^\/city\/([^/]+)(?:\/|$)/;function x9(t){const r=_9.exec(t);if(r===null)return null;const i=r[1];if(i===void 0)return null;let s;try{s=decodeURIComponent(i)}catch{return null}return Jm.test(s)?{cityName:s,basename:`/city/${i}`}:null}function I9(){const t=T.useMemo(()=>x9(window.location.pathname),[]),[r,i]=T.useState({phase:"loading"}),[s,u]=T.useState(0),f=T.useCallback(()=>{i({phase:"loading"}),u(p=>p+1)},[]);return T.useEffect(()=>{let p=!1;return i({phase:"loading"}),Qe().listCities().then(v=>{if(p)return;const x=v.items??[];if(t!==null){const w=x.some(b=>b.name===t.cityName);i(w?{phase:"mount"}:{phase:"unknown-city",cities:x});return}const I=x[0];if(I===void 0){i({phase:"empty"});return}window.location.replace(`/city/${encodeURIComponent(I.name)}/`)}).catch(v=>{if(!p){if(t!==null){i({phase:"mount"});return}i({phase:"error",message:v instanceof Error?v.message:"failed to load cities"})}}),()=>{p=!0}},[t,s]),t!==null&&r.phase==="mount"?(iw(t.cityName),M.jsx(X0,{basename:t.basename,future:{v7_relativeSplatPath:!0,v7_startTransition:!0},children:M.jsx(c9,{})})):r.phase==="unknown-city"&&t!==null?M.jsx(E9,{cityName:t.cityName,cities:r.cities}):r.phase==="empty"?M.jsx(w9,{}):r.phase==="error"?M.jsx(S9,{message:r.message,onRetry:f}):M.jsx(Ja,{children:M.jsx("div",{className:"text-label uppercase tracking-wider text-fg-muted",children:"Resolving city…"})})}function Ja({children:t}){return M.jsx("div",{className:"min-h-screen bg-surface text-fg antialiased flex items-center justify-center px-6",children:M.jsx("div",{className:"max-w-prose w-full space-y-4",children:t})})}function E9({cityName:t,cities:r}){return M.jsx(Ja,{children:M.jsxs("section",{role:"alert",className:"space-y-4",children:[M.jsxs("h1",{className:"text-display font-semibold text-fg",children:["City “",t,"” is not registered on this supervisor."]}),r.length>0?M.jsxs("div",{className:"space-y-2",children:[M.jsx("p",{className:"text-body text-fg-muted",children:"Available cities:"}),M.jsx("ul",{className:"space-y-1",children:r.map(i=>M.jsxs("li",{children:[M.jsx("a",{href:`/city/${encodeURIComponent(i.name)}/`,className:"text-body text-accent hover:underline focus-mark",children:i.name}),i.running?null:M.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted ml-2",children:"· stopped"})]},i.name))})]}):M.jsx(qv,{})]})})}function w9(){return M.jsx(Ja,{children:M.jsxs("section",{className:"space-y-4",children:[M.jsx("h1",{className:"text-display font-semibold text-fg",children:"No cities are registered on this supervisor."}),M.jsx(qv,{})]})})}function qv(){return M.jsxs("div",{className:"space-y-3",children:[M.jsx("p",{className:"text-body text-fg-muted",children:"Create one from a terminal:"}),M.jsx("pre",{className:"text-body bg-surface-tint rounded-sm px-3 py-2 overflow-x-auto",children:M.jsx("code",{children:"gc init ~/my-city"})}),M.jsxs("p",{className:"text-body text-fg-muted",children:[M.jsx("code",{children:"gc init"})," bootstraps the city directory, registers it with the supervisor, and starts the orchestrator. Then refresh this page. See the"," ",M.jsx("a",{href:y9,target:"_blank",rel:"noreferrer",className:"text-accent hover:underline focus-mark",children:"getting-started guide"})," ","for the full walkthrough."]})]})}function S9({message:t,onRetry:r}){return M.jsx(Ja,{children:M.jsxs("section",{role:"alert",className:"space-y-4",children:[M.jsx("h1",{className:"text-display font-semibold text-fg",children:"Could not load cities."}),M.jsx("p",{className:"text-body text-fg-muted",children:t}),M.jsx(h9,{onClick:r,children:"Retry"})]})})}const Fv=document.getElementById("root");if(!Fv)throw new Error("missing #root");X2.createRoot(Fv).render(M.jsx(Dm.StrictMode,{children:M.jsx(ck,{children:M.jsx(kv,{children:M.jsx(I9,{})})})}));export{$9 as $,Yo as A,h9 as B,nr as C,R9 as D,b9 as E,wu as F,v3 as G,Tk as H,Pv as I,j9 as J,Lt as K,Q0 as L,jc as M,Cm as N,n9 as O,BS as P,Xa as Q,U9 as R,gk as S,k9 as T,Ek as U,Z9 as V,Pc as W,FS as X,D9 as Y,_3 as Z,y3 as _,Pw as a,O9 as a0,Bv as a1,zv as a2,lr as a3,av as a4,jw as a5,ww as a6,Yl as a7,A9 as a8,Sn as a9,G9 as aa,q9 as ab,V9 as ac,kk as ad,d3 as ae,lb as af,ub as ag,zS as ah,En as b,DS as c,RS as d,a3 as e,Vk as f,yk as g,N9 as h,Av as i,M as j,P9 as k,wk as l,ib as m,L9 as n,M9 as o,C9 as p,W9 as q,T as r,F9 as s,T9 as t,H9 as u,Qe as v,pn as w,JE as x,B9 as y,z9 as z}; diff --git a/internal/api/dashboardspa/dist/assets/projectOf-BjfQvzy4.js b/internal/api/dashboardspa/dist/assets/projectOf-mIrvrzQE.js similarity index 97% rename from internal/api/dashboardspa/dist/assets/projectOf-BjfQvzy4.js rename to internal/api/dashboardspa/dist/assets/projectOf-mIrvrzQE.js index 7856618984..3d11495046 100644 --- a/internal/api/dashboardspa/dist/assets/projectOf-BjfQvzy4.js +++ b/internal/api/dashboardspa/dist/assets/projectOf-mIrvrzQE.js @@ -1 +1 @@ -import{j as c,Q as R}from"./index-DDS7Ehww.js";function k({value:e,onChange:t,placeholder:n="Search",matchCount:r,totalCount:i,ariaLabel:a="Search list"}){const d=e.length>0&&typeof r=="number"&&typeof i=="number";return c.jsxs("div",{className:"flex items-baseline gap-3 border-b border-rule pb-1",children:[c.jsx("input",{type:"search",value:e,onChange:m=>t(m.target.value),placeholder:n,"aria-label":a,className:"flex-1 bg-transparent border-0 text-body text-fg placeholder:text-fg-faint focus:outline-none focus:ring-0 px-0 py-0.5"}),d&&c.jsxs("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:[r," / ",i]})]})}const b=/^(.+?)-[a-z0-9]+(?:\.\d+)?$/i;function C(e){return b.exec(e.id)?.[1]??e.id}const o="Orchestration";function u(){return R()??o}const s="(no rig)",l="Maintenance",E=new Set(["mayor","control-dispatcher","oversight-rig.chief-of-staff"]);function g(e){return e.rig&&e.rig.length>0?!1:!!e.template&&E.has(e.template)}const p=/\/control-dispatcher$/;function O(e){return!e.rig||e.rig.length===0?!1:p.test(e.alias??"")}const _=/(?:worker|polecat)(?:-\d+)?$/,f=/(?:\.project-lead|chief-of-staff)$/;function j(e){if(e.state!=="active"&&e.state!=="running"||g(e)||O(e))return!1;const t=e.template??"",n=e.alias??"";if(f.test(t)||f.test(n))return!1;const r=e.session_name;return[t,n,r].filter(a=>a.length>0).map(a=>I(a)).some(a=>_.test(a))}function h(e){return e.toLowerCase().replace(/_/g,"-")}function L(e){if(g(e))return{key:o,label:u()};const t=e.rig??e.pool??e.template;if(!t)return{key:s,label:s};const n=t.split(/[\\/]/).filter(Boolean),r=n[n.length-1]??t;return{key:h(r),label:r}}function w(e){return e.rig&&e.rig.length>0?e.rig:s}const S=new Set(["mayor","control-dispatcher","oversight-rig.chief-of-staff"]),N=new Set(["dog"]);function y(e){return e.rig&&e.rig.length>0?!1:S.has(e.name)}function v(e){return!e.rig||e.rig.length===0?!1:p.test(e.name)}function A(e){if(y(e))return{key:o,label:u()};const t=e.rig&&e.rig.length>0?e.rig:void 0;if(!t&&e.pool&&N.has(e.pool))return{key:l,label:l};const n=t??e.pool;if(!n)return{key:s,label:s};const r=n.split(/[\\/]/).filter(Boolean),i=T(r[r.length-1]??n);return{key:h(i),label:i}}function T(e){return e.endsWith("-main")?e.slice(0,-5):e}const x=/-(?:gc|td|th|[a-z]{4})-[a-z0-9]*[0-9][a-z0-9]*$/;function I(e){const t=e.trim(),n=t.split(/[\\/]/).filter(Boolean),r=n[n.length-1]??t,i=r.replace(x,"");return i.length>0?i:r}function X(e){const{key:t}=A(e);return t===o||t===l||t===s}export{k as L,T as a,X as b,I as c,A as d,v as e,C as f,j as i,w as m,L as s}; +import{j as c,Q as R}from"./index-BDHAaQRP.js";function k({value:e,onChange:t,placeholder:n="Search",matchCount:r,totalCount:i,ariaLabel:a="Search list"}){const d=e.length>0&&typeof r=="number"&&typeof i=="number";return c.jsxs("div",{className:"flex items-baseline gap-3 border-b border-rule pb-1",children:[c.jsx("input",{type:"search",value:e,onChange:m=>t(m.target.value),placeholder:n,"aria-label":a,className:"flex-1 bg-transparent border-0 text-body text-fg placeholder:text-fg-faint focus:outline-none focus:ring-0 px-0 py-0.5"}),d&&c.jsxs("span",{className:"text-label uppercase tracking-wider text-fg-faint tnum",children:[r," / ",i]})]})}const b=/^(.+?)-[a-z0-9]+(?:\.\d+)?$/i;function C(e){return b.exec(e.id)?.[1]??e.id}const o="Orchestration";function u(){return R()??o}const s="(no rig)",l="Maintenance",E=new Set(["mayor","control-dispatcher","oversight-rig.chief-of-staff"]);function g(e){return e.rig&&e.rig.length>0?!1:!!e.template&&E.has(e.template)}const p=/\/control-dispatcher$/;function O(e){return!e.rig||e.rig.length===0?!1:p.test(e.alias??"")}const _=/(?:worker|polecat)(?:-\d+)?$/,f=/(?:\.project-lead|chief-of-staff)$/;function j(e){if(e.state!=="active"&&e.state!=="running"||g(e)||O(e))return!1;const t=e.template??"",n=e.alias??"";if(f.test(t)||f.test(n))return!1;const r=e.session_name;return[t,n,r].filter(a=>a.length>0).map(a=>I(a)).some(a=>_.test(a))}function h(e){return e.toLowerCase().replace(/_/g,"-")}function L(e){if(g(e))return{key:o,label:u()};const t=e.rig??e.pool??e.template;if(!t)return{key:s,label:s};const n=t.split(/[\\/]/).filter(Boolean),r=n[n.length-1]??t;return{key:h(r),label:r}}function w(e){return e.rig&&e.rig.length>0?e.rig:s}const S=new Set(["mayor","control-dispatcher","oversight-rig.chief-of-staff"]),N=new Set(["dog"]);function y(e){return e.rig&&e.rig.length>0?!1:S.has(e.name)}function v(e){return!e.rig||e.rig.length===0?!1:p.test(e.name)}function A(e){if(y(e))return{key:o,label:u()};const t=e.rig&&e.rig.length>0?e.rig:void 0;if(!t&&e.pool&&N.has(e.pool))return{key:l,label:l};const n=t??e.pool;if(!n)return{key:s,label:s};const r=n.split(/[\\/]/).filter(Boolean),i=T(r[r.length-1]??n);return{key:h(i),label:i}}function T(e){return e.endsWith("-main")?e.slice(0,-5):e}const x=/-(?:gc|td|th|[a-z]{4})-[a-z0-9]*[0-9][a-z0-9]*$/;function I(e){const t=e.trim(),n=t.split(/[\\/]/).filter(Boolean),r=n[n.length-1]??t,i=r.replace(x,"");return i.length>0?i:r}function X(e){const{key:t}=A(e);return t===o||t===l||t===s}export{k as L,T as a,X as b,I as c,A as d,v as e,C as f,j as i,w as m,L as s}; diff --git a/internal/api/dashboardspa/dist/assets/useListFilters-HxlZke6_.js b/internal/api/dashboardspa/dist/assets/useListFilters-D3eLt7Cq.js similarity index 98% rename from internal/api/dashboardspa/dist/assets/useListFilters-HxlZke6_.js rename to internal/api/dashboardspa/dist/assets/useListFilters-D3eLt7Cq.js index fb28a3e25e..9148ae67ac 100644 --- a/internal/api/dashboardspa/dist/assets/useListFilters-HxlZke6_.js +++ b/internal/api/dashboardspa/dist/assets/useListFilters-D3eLt7Cq.js @@ -1 +1 @@ -import{j as y,r as g,a1 as Y,a2 as D,C as tt,A as et}from"./index-DDS7Ehww.js";function gt({chips:e,activeIds:n,onToggle:a,legend:p}){return e.length===0?null:y.jsxs("div",{className:"flex items-baseline gap-4 flex-wrap",children:[p&&y.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:p}),e.map(i=>{const d=n.has(i.id);return y.jsx("button",{type:"button",onClick:()=>a(i.id),"aria-pressed":d,className:`text-label uppercase tracking-wider transition-colors duration-150 ease-out-quart focus-mark rounded-sm ${d?"text-fg font-semibold underline decoration-fg underline-offset-4":"text-fg-muted hover:text-fg"}`,children:i.label},i.id)})]})}const st="gcd:listFilters:collapsed:",rt="gcd:listFilters:expanded:",X="gcd:listFilters:sortMode:",m="useListFilters";function B(e,n){return(n?rt:st)+e}function R(e,n){const a=B(e,n),p=Y("localStorage",a,m);if(p.status!=="found")return new Set;try{const i=JSON.parse(p.value);if(Array.isArray(i))return new Set(i.filter(d=>typeof d=="string"))}catch(i){at(a,i)}return new Set}function nt(e,n,a){D("localStorage",B(e,n),JSON.stringify(Array.from(a)),m)}function T(e,n){const a=Y("localStorage",X+e,m);return a.status==="found"&&(a.value==="alpha"||a.value==="activity")?a.value:n}function ot(e,n){D("localStorage",X+e,n,m)}function at(e,n){tt({component:m,operation:"localStorage.parse",message:`${e}: ${et(n)}`})}const ct=[],it=new Set,lt=[];function pt({viewKey:e,rows:n,projectOf:a,searchOf:p,chips:i,initialActiveChipIds:d=lt,defaultCollapsed:f=!1,activityOf:x,defaultSortMode:M="alpha",pinnedProjects:k=ct,nonCollapsibleProjects:I=it}){const $=d.join(","),[N,L]=g.useState(""),[P,_]=g.useState(()=>new Set(d)),[w,A]=g.useState(()=>R(e,f)),[C,v]=g.useState(()=>T(e,M));g.useEffect(()=>{A(R(e,f)),v(T(e,M)),L(""),_(new Set(d))},[e,f,M,$]);const H=g.useCallback(r=>{_(S=>{const l=new Set(S);return l.has(r)?l.delete(r):l.add(r),l})},[]),J=g.useCallback(r=>{A(S=>{const l=new Set(S);return l.has(r)?l.delete(r):l.add(r),nt(e,f,l),l})},[e,f]),U=g.useCallback(r=>w.has(r)?!f:f,[w,f]),q=g.useCallback(r=>{v(r),ot(e,r)},[e]),F=g.useMemo(()=>{const r=N.trim().toLowerCase(),S=i.filter(t=>P.has(t.id)),l=t=>{if(r.length===0)return!0;for(const s of p(t))if(s&&s.toLowerCase().includes(r))return!0;return!1},Z=t=>{if(S.length===0)return!0;for(const s of S)if(s.match(t))return!0;return!1},b=new Map;for(const t of n){if(!l(t)||!Z(t))continue;const s=a(t),o=typeof s=="string"?s:s.key,c=typeof s=="string"?s:s.label,u=b.get(o);u?(u.rows.push(t),u.labelCounts.set(c,(u.labelCounts.get(c)??0)+1)):b.set(o,{rows:[t],labelCounts:new Map([[c,1]])})}const z=t=>{let s="",o=-1,c=!1;for(const[u,h]of t){const j=/[A-Z]/.test(u);(h>o||h===o&&j&&!c)&&(s=u,o=h,c=j)}return s},G=Array.from(b.keys()),O=k.filter(t=>b.has(t)),Q=new Set(O),E=G.filter(t=>!Q.has(t));if(C==="activity"&&x){const t=new Map;for(const s of E){const o=b.get(s);let c=-1/0;if(o)for(const u of o.rows){const h=x(u);typeof h=="number"&&Number.isFinite(h)&&h>c&&(c=h)}t.set(s,c)}E.sort((s,o)=>{const c=t.get(s)??-1/0,u=t.get(o)??-1/0;return c!==u?u-c:s.localeCompare(o)})}else E.sort();const V=[...O,...E],W=t=>I.has(t)?!1:w.has(t)?!f:f;return V.map(t=>{const s=b.get(t),o=s?.rows??[];return{project:s?z(s.labelCounts):t,projectKey:t,rows:o,totalInProject:o.length,collapsed:W(t),collapsible:!I.has(t)}})},[n,N,P,i,a,p,w,f,C,x,k,I]),K=g.useMemo(()=>F.reduce((r,S)=>r+S.totalInProject,0),[F]);return{search:N,setSearch:L,activeChipIds:P,toggleChip:H,isCollapsed:U,toggleProject:J,sortMode:C,setSortMode:q,groups:F,totalMatches:K}}export{gt as F,pt as u}; +import{j as y,r as g,a1 as Y,a2 as D,C as tt,A as et}from"./index-BDHAaQRP.js";function gt({chips:e,activeIds:n,onToggle:a,legend:p}){return e.length===0?null:y.jsxs("div",{className:"flex items-baseline gap-4 flex-wrap",children:[p&&y.jsx("span",{className:"text-label uppercase tracking-wider text-fg-muted",children:p}),e.map(i=>{const d=n.has(i.id);return y.jsx("button",{type:"button",onClick:()=>a(i.id),"aria-pressed":d,className:`text-label uppercase tracking-wider transition-colors duration-150 ease-out-quart focus-mark rounded-sm ${d?"text-fg font-semibold underline decoration-fg underline-offset-4":"text-fg-muted hover:text-fg"}`,children:i.label},i.id)})]})}const st="gcd:listFilters:collapsed:",rt="gcd:listFilters:expanded:",X="gcd:listFilters:sortMode:",m="useListFilters";function B(e,n){return(n?rt:st)+e}function R(e,n){const a=B(e,n),p=Y("localStorage",a,m);if(p.status!=="found")return new Set;try{const i=JSON.parse(p.value);if(Array.isArray(i))return new Set(i.filter(d=>typeof d=="string"))}catch(i){at(a,i)}return new Set}function nt(e,n,a){D("localStorage",B(e,n),JSON.stringify(Array.from(a)),m)}function T(e,n){const a=Y("localStorage",X+e,m);return a.status==="found"&&(a.value==="alpha"||a.value==="activity")?a.value:n}function ot(e,n){D("localStorage",X+e,n,m)}function at(e,n){tt({component:m,operation:"localStorage.parse",message:`${e}: ${et(n)}`})}const ct=[],it=new Set,lt=[];function pt({viewKey:e,rows:n,projectOf:a,searchOf:p,chips:i,initialActiveChipIds:d=lt,defaultCollapsed:f=!1,activityOf:x,defaultSortMode:M="alpha",pinnedProjects:k=ct,nonCollapsibleProjects:I=it}){const $=d.join(","),[N,L]=g.useState(""),[P,_]=g.useState(()=>new Set(d)),[w,A]=g.useState(()=>R(e,f)),[C,v]=g.useState(()=>T(e,M));g.useEffect(()=>{A(R(e,f)),v(T(e,M)),L(""),_(new Set(d))},[e,f,M,$]);const H=g.useCallback(r=>{_(S=>{const l=new Set(S);return l.has(r)?l.delete(r):l.add(r),l})},[]),J=g.useCallback(r=>{A(S=>{const l=new Set(S);return l.has(r)?l.delete(r):l.add(r),nt(e,f,l),l})},[e,f]),U=g.useCallback(r=>w.has(r)?!f:f,[w,f]),q=g.useCallback(r=>{v(r),ot(e,r)},[e]),F=g.useMemo(()=>{const r=N.trim().toLowerCase(),S=i.filter(t=>P.has(t.id)),l=t=>{if(r.length===0)return!0;for(const s of p(t))if(s&&s.toLowerCase().includes(r))return!0;return!1},Z=t=>{if(S.length===0)return!0;for(const s of S)if(s.match(t))return!0;return!1},b=new Map;for(const t of n){if(!l(t)||!Z(t))continue;const s=a(t),o=typeof s=="string"?s:s.key,c=typeof s=="string"?s:s.label,u=b.get(o);u?(u.rows.push(t),u.labelCounts.set(c,(u.labelCounts.get(c)??0)+1)):b.set(o,{rows:[t],labelCounts:new Map([[c,1]])})}const z=t=>{let s="",o=-1,c=!1;for(const[u,h]of t){const j=/[A-Z]/.test(u);(h>o||h===o&&j&&!c)&&(s=u,o=h,c=j)}return s},G=Array.from(b.keys()),O=k.filter(t=>b.has(t)),Q=new Set(O),E=G.filter(t=>!Q.has(t));if(C==="activity"&&x){const t=new Map;for(const s of E){const o=b.get(s);let c=-1/0;if(o)for(const u of o.rows){const h=x(u);typeof h=="number"&&Number.isFinite(h)&&h>c&&(c=h)}t.set(s,c)}E.sort((s,o)=>{const c=t.get(s)??-1/0,u=t.get(o)??-1/0;return c!==u?u-c:s.localeCompare(o)})}else E.sort();const V=[...O,...E],W=t=>I.has(t)?!1:w.has(t)?!f:f;return V.map(t=>{const s=b.get(t),o=s?.rows??[];return{project:s?z(s.labelCounts):t,projectKey:t,rows:o,totalInProject:o.length,collapsed:W(t),collapsible:!I.has(t)}})},[n,N,P,i,a,p,w,f,C,x,k,I]),K=g.useMemo(()=>F.reduce((r,S)=>r+S.totalInProject,0),[F]);return{search:N,setSearch:L,activeChipIds:P,toggleChip:H,isCollapsed:U,toggleProject:J,sortMode:C,setSortMode:q,groups:F,totalMatches:K}}export{gt as F,pt as u}; diff --git a/internal/api/dashboardspa/dist/assets/useVisibleRefresh-C8_1beQq.js b/internal/api/dashboardspa/dist/assets/useVisibleRefresh-B7rFi4L5.js similarity index 92% rename from internal/api/dashboardspa/dist/assets/useVisibleRefresh-C8_1beQq.js rename to internal/api/dashboardspa/dist/assets/useVisibleRefresh-B7rFi4L5.js index 00d1d180b0..38d8933e7b 100644 --- a/internal/api/dashboardspa/dist/assets/useVisibleRefresh-C8_1beQq.js +++ b/internal/api/dashboardspa/dist/assets/useVisibleRefresh-B7rFi4L5.js @@ -1 +1 @@ -import{r}from"./index-DDS7Ehww.js";const F=2e3,w=6e4;function h(e,u,s={}){const a=r.useRef(e);a.current=e;const n=r.useRef(l(s));n.current=l(s);const t=r.useRef(0),c=r.useRef(0),o=r.useRef(!1),{enabled:i,initialBackoffMs:d,maxBackoffMs:B}=n.current;r.useEffect(()=>{if(!i)return;const M=()=>{t.current=0,c.current=0},R=A=>{const f=n.current;f.onError?.(A);const E=Math.min(f.initialBackoffMs*2**t.current,f.maxBackoffMs);t.current+=1,c.current=Date.now()+E},k=()=>{document.hidden||o.current||Date.now(){o.current=!1}))},m=window.setInterval(k,u);return()=>window.clearInterval(m)},[i,u,d,B])}function l(e){return{enabled:e.enabled??!0,initialBackoffMs:e.initialBackoffMs??F,maxBackoffMs:e.maxBackoffMs??w,onError:e.onError??x}}function x(){}export{h as u}; +import{r}from"./index-BDHAaQRP.js";const F=2e3,w=6e4;function h(e,u,s={}){const a=r.useRef(e);a.current=e;const n=r.useRef(l(s));n.current=l(s);const t=r.useRef(0),c=r.useRef(0),o=r.useRef(!1),{enabled:i,initialBackoffMs:d,maxBackoffMs:B}=n.current;r.useEffect(()=>{if(!i)return;const M=()=>{t.current=0,c.current=0},R=A=>{const f=n.current;f.onError?.(A);const E=Math.min(f.initialBackoffMs*2**t.current,f.maxBackoffMs);t.current+=1,c.current=Date.now()+E},k=()=>{document.hidden||o.current||Date.now(){o.current=!1}))},m=window.setInterval(k,u);return()=>window.clearInterval(m)},[i,u,d,B])}function l(e){return{enabled:e.enabled??!0,initialBackoffMs:e.initialBackoffMs??F,maxBackoffMs:e.maxBackoffMs??w,onError:e.onError??x}}function x(){}export{h as u}; diff --git a/internal/api/dashboardspa/dist/index.html b/internal/api/dashboardspa/dist/index.html index 4767cbe82b..2d4886cc9c 100644 --- a/internal/api/dashboardspa/dist/index.html +++ b/internal/api/dashboardspa/dist/index.html @@ -20,7 +20,7 @@ } catch (_) {} })(); - + diff --git a/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/index.ts b/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/index.ts index 44421303fd..37ff4cc0d9 100644 --- a/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/index.ts +++ b/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts export { addPack, createAgent, createBead, createConvoy, createProvider, createRig, createSession, deleteV0CityByCityNameAgentByBase, deleteV0CityByCityNameAgentByDirByBase, deleteV0CityByCityNameBeadById, deleteV0CityByCityNameConvoyById, deleteV0CityByCityNameExtmsgAdapters, deleteV0CityByCityNameExtmsgParticipants, deleteV0CityByCityNameFormulasByName, deleteV0CityByCityNameMailById, deleteV0CityByCityNamePacksByName, deleteV0CityByCityNamePatchesAgentByBase, deleteV0CityByCityNamePatchesAgentByDirByBase, deleteV0CityByCityNamePatchesProviderByName, deleteV0CityByCityNamePatchesRigByName, deleteV0CityByCityNameProviderByName, deleteV0CityByCityNameRigByName, deleteV0CityByCityNameWorkflowByWorkflowId, emitEvent, ensureExtmsgGroup, getHealth, getV0Cities, getV0CityByCityName, getV0CityByCityNameAgentByBase, getV0CityByCityNameAgentByBaseOutput, getV0CityByCityNameAgentByDirByBase, getV0CityByCityNameAgentByDirByBaseOutput, getV0CityByCityNameAgents, getV0CityByCityNameBeadById, getV0CityByCityNameBeadByIdDeps, getV0CityByCityNameBeads, getV0CityByCityNameBeadsGraphByRootId, getV0CityByCityNameBeadsReady, getV0CityByCityNameConfig, getV0CityByCityNameConfigDefaults, getV0CityByCityNameConfigExplain, getV0CityByCityNameConfigValidate, getV0CityByCityNameConvoyById, getV0CityByCityNameConvoyByIdCheck, getV0CityByCityNameConvoys, getV0CityByCityNameEvents, getV0CityByCityNameExtmsgAdapters, getV0CityByCityNameExtmsgBindings, getV0CityByCityNameExtmsgGroups, getV0CityByCityNameExtmsgTranscript, getV0CityByCityNameFormulaByName, getV0CityByCityNameFormulas, getV0CityByCityNameFormulasByName, getV0CityByCityNameFormulasByNameRuns, getV0CityByCityNameFormulasByNameSource, getV0CityByCityNameFormulasFeed, getV0CityByCityNameHealth, getV0CityByCityNameMail, getV0CityByCityNameMailById, getV0CityByCityNameMailCount, getV0CityByCityNameMailThreadById, getV0CityByCityNameMaintenanceStatus, getV0CityByCityNameOrderByName, getV0CityByCityNameOrderHistoryByBeadId, getV0CityByCityNameOrders, getV0CityByCityNameOrdersCheck, getV0CityByCityNameOrdersFeed, getV0CityByCityNameOrdersHistory, getV0CityByCityNamePacks, getV0CityByCityNamePatchesAgentByBase, getV0CityByCityNamePatchesAgentByDirByBase, getV0CityByCityNamePatchesAgents, getV0CityByCityNamePatchesProviderByName, getV0CityByCityNamePatchesProviders, getV0CityByCityNamePatchesRigByName, getV0CityByCityNamePatchesRigs, getV0CityByCityNamePending, getV0CityByCityNameProviderByName, getV0CityByCityNameProviderReadiness, getV0CityByCityNameProviders, getV0CityByCityNameProvidersPublic, getV0CityByCityNameReadiness, getV0CityByCityNameRigByName, getV0CityByCityNameRigs, getV0CityByCityNameRuns, getV0CityByCityNameRunsByRunId, getV0CityByCityNameRunsByRunIdSteps, getV0CityByCityNameRunsCensus, getV0CityByCityNameServiceByName, getV0CityByCityNameServices, getV0CityByCityNameSessionById, getV0CityByCityNameSessionByIdAgents, getV0CityByCityNameSessionByIdAgentsByAgentId, getV0CityByCityNameSessionByIdPending, getV0CityByCityNameSessionByIdTranscript, getV0CityByCityNameSessions, getV0CityByCityNameStatus, getV0CityByCityNameUsage, getV0CityByCityNameWaitById, getV0CityByCityNameWaits, getV0CityByCityNameWorkflowByWorkflowId, getV0Events, getV0ProviderReadiness, getV0Readiness, type Options, patchV0CityByCityName, patchV0CityByCityNameAgentByBase, patchV0CityByCityNameAgentByDirByBase, patchV0CityByCityNameBeadById, patchV0CityByCityNameProviderByName, patchV0CityByCityNameRigByName, patchV0CityByCityNameSessionById, postV0City, postV0CityByCityNameAgentByBaseByAction, postV0CityByCityNameAgentByDirByBaseByAction, postV0CityByCityNameBeadByIdAssign, postV0CityByCityNameBeadByIdClose, postV0CityByCityNameBeadByIdReopen, postV0CityByCityNameBeadByIdUpdate, postV0CityByCityNameConvoyByIdAdd, postV0CityByCityNameConvoyByIdClose, postV0CityByCityNameConvoyByIdRemove, postV0CityByCityNameExtmsgBind, postV0CityByCityNameExtmsgInbound, postV0CityByCityNameExtmsgOutbound, postV0CityByCityNameExtmsgParticipants, postV0CityByCityNameExtmsgTranscriptAck, postV0CityByCityNameExtmsgUnbind, postV0CityByCityNameFormulasByNamePreview, postV0CityByCityNameFormulasByNameValidate, postV0CityByCityNameMailByIdArchive, postV0CityByCityNameMailByIdMarkUnread, postV0CityByCityNameMailByIdRead, postV0CityByCityNameOrderByNameDisable, postV0CityByCityNameOrderByNameEnable, postV0CityByCityNameOrderByNameRun, postV0CityByCityNameRigByNameByAction, postV0CityByCityNameRunsByRunIdCancel, postV0CityByCityNameServiceByNameRestart, postV0CityByCityNameSessionByIdClose, postV0CityByCityNameSessionByIdKill, postV0CityByCityNameSessionByIdPermissionMode, postV0CityByCityNameSessionByIdRename, postV0CityByCityNameSessionByIdStop, postV0CityByCityNameSessionByIdSuspend, postV0CityByCityNameSessionByIdWake, postV0CityByCityNameSling, postV0CityByCityNameUnregister, putV0CityByCityNameFormulasByName, putV0CityByCityNamePatchesAgents, putV0CityByCityNamePatchesProviders, putV0CityByCityNamePatchesRigs, registerExtmsgAdapter, replyMail, respondSession, rotateEvents, sendMail, sendSessionMessage, streamAgentOutput, streamAgentOutputQualified, streamEvents, streamSession, streamSupervisorEvents, submitSession, triggerMaintenanceDoltGc } from './sdk.gen.js'; -export type { AdapterCapabilities, AdapterEventPayload, AddPackData, AddPackError, AddPackErrors, AddPackResponse, AddPackResponses, AgentCreatedOutputBody, AgentCreateInputBody, AgentMapping, AgentOutputResponse, AgentPatch, AgentPatchSetInputBody, AgentResponse, AgentUpdateInputBody, AgentUpdateQualifiedInputBody, AnnotatedAgentResponse, AnnotatedProviderResponse, AsyncAcceptedBody, AsyncAcceptedResponse, Bead, BeadAssignInputBody, BeadClaimRejectedPayload, BeadCreateInputBody, BeadDeadAssigneeReopenedPayload, BeadDepsResponse, BeadEventPayload, BeadGraphResponse, BeadsDiagnostic, BeadUpdateBody, BeadWorktreeReapedPayload, BeadWorktreeReapSkippedPayload, BindingStatus, BoundEventPayload, BreakerStateChangedPayload, CityCreateRequest, CityCreateSucceededPayload, CityGetResponse, CityInfo, CityLifecyclePayload, CityPatchInputBody, CityPendingEntry, CityUnregisterSucceededPayload, ClientOptions, ConditionalWritesDegradedPayload, ConfigAgentResponse, ConfigExplainPatches, ConfigExplainResponse, ConfigPatchesResponse, ConfigResponse, ConfigRigResponse, ConfigValidateOutputBody, ControllerTickCompletedPayload, ConversationGroupParticipant, ConversationGroupRecord, ConversationKind, ConversationRef, ConversationTranscriptRecord, ConvoyAddInputBody, ConvoyCheckResponse, ConvoyCreateInputBody, ConvoyGetResponse, ConvoyProgress, ConvoyRemoveInputBody, CreateAgentData, CreateAgentError, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateBeadData, CreateBeadError, CreateBeadErrors, CreateBeadResponse, CreateBeadResponses, CreateConvoyData, CreateConvoyError, CreateConvoyErrors, CreateConvoyResponse, CreateConvoyResponses, CreateProviderData, CreateProviderError, CreateProviderErrors, CreateProviderResponse, CreateProviderResponses, CreateRigData, CreateRigError, CreateRigErrors, CreateRigResponse, CreateRigResponses, CreateSessionData, CreateSessionError, CreateSessionErrors, CreateSessionResponse, CreateSessionResponses, DeleteV0CityByCityNameAgentByBaseData, DeleteV0CityByCityNameAgentByBaseError, DeleteV0CityByCityNameAgentByBaseErrors, DeleteV0CityByCityNameAgentByBaseResponse, DeleteV0CityByCityNameAgentByBaseResponses, DeleteV0CityByCityNameAgentByDirByBaseData, DeleteV0CityByCityNameAgentByDirByBaseError, DeleteV0CityByCityNameAgentByDirByBaseErrors, DeleteV0CityByCityNameAgentByDirByBaseResponse, DeleteV0CityByCityNameAgentByDirByBaseResponses, DeleteV0CityByCityNameBeadByIdData, DeleteV0CityByCityNameBeadByIdError, DeleteV0CityByCityNameBeadByIdErrors, DeleteV0CityByCityNameBeadByIdResponse, DeleteV0CityByCityNameBeadByIdResponses, DeleteV0CityByCityNameConvoyByIdData, DeleteV0CityByCityNameConvoyByIdError, DeleteV0CityByCityNameConvoyByIdErrors, DeleteV0CityByCityNameConvoyByIdResponse, DeleteV0CityByCityNameConvoyByIdResponses, DeleteV0CityByCityNameExtmsgAdaptersData, DeleteV0CityByCityNameExtmsgAdaptersError, DeleteV0CityByCityNameExtmsgAdaptersErrors, DeleteV0CityByCityNameExtmsgAdaptersResponse, DeleteV0CityByCityNameExtmsgAdaptersResponses, DeleteV0CityByCityNameExtmsgParticipantsData, DeleteV0CityByCityNameExtmsgParticipantsError, DeleteV0CityByCityNameExtmsgParticipantsErrors, DeleteV0CityByCityNameExtmsgParticipantsResponse, DeleteV0CityByCityNameExtmsgParticipantsResponses, DeleteV0CityByCityNameFormulasByNameData, DeleteV0CityByCityNameFormulasByNameError, DeleteV0CityByCityNameFormulasByNameErrors, DeleteV0CityByCityNameFormulasByNameResponse, DeleteV0CityByCityNameFormulasByNameResponses, DeleteV0CityByCityNameMailByIdData, DeleteV0CityByCityNameMailByIdError, DeleteV0CityByCityNameMailByIdErrors, DeleteV0CityByCityNameMailByIdResponse, DeleteV0CityByCityNameMailByIdResponses, DeleteV0CityByCityNamePacksByNameData, DeleteV0CityByCityNamePacksByNameError, DeleteV0CityByCityNamePacksByNameErrors, DeleteV0CityByCityNamePacksByNameResponse, DeleteV0CityByCityNamePacksByNameResponses, DeleteV0CityByCityNamePatchesAgentByBaseData, DeleteV0CityByCityNamePatchesAgentByBaseError, DeleteV0CityByCityNamePatchesAgentByBaseErrors, DeleteV0CityByCityNamePatchesAgentByBaseResponse, DeleteV0CityByCityNamePatchesAgentByBaseResponses, DeleteV0CityByCityNamePatchesAgentByDirByBaseData, DeleteV0CityByCityNamePatchesAgentByDirByBaseError, DeleteV0CityByCityNamePatchesAgentByDirByBaseErrors, DeleteV0CityByCityNamePatchesAgentByDirByBaseResponse, DeleteV0CityByCityNamePatchesAgentByDirByBaseResponses, DeleteV0CityByCityNamePatchesProviderByNameData, DeleteV0CityByCityNamePatchesProviderByNameError, DeleteV0CityByCityNamePatchesProviderByNameErrors, DeleteV0CityByCityNamePatchesProviderByNameResponse, DeleteV0CityByCityNamePatchesProviderByNameResponses, DeleteV0CityByCityNamePatchesRigByNameData, DeleteV0CityByCityNamePatchesRigByNameError, DeleteV0CityByCityNamePatchesRigByNameErrors, DeleteV0CityByCityNamePatchesRigByNameResponse, DeleteV0CityByCityNamePatchesRigByNameResponses, DeleteV0CityByCityNameProviderByNameData, DeleteV0CityByCityNameProviderByNameError, DeleteV0CityByCityNameProviderByNameErrors, DeleteV0CityByCityNameProviderByNameResponse, DeleteV0CityByCityNameProviderByNameResponses, DeleteV0CityByCityNameRigByNameData, DeleteV0CityByCityNameRigByNameError, DeleteV0CityByCityNameRigByNameErrors, DeleteV0CityByCityNameRigByNameResponse, DeleteV0CityByCityNameRigByNameResponses, DeleteV0CityByCityNameWorkflowByWorkflowIdData, DeleteV0CityByCityNameWorkflowByWorkflowIdError, DeleteV0CityByCityNameWorkflowByWorkflowIdErrors, DeleteV0CityByCityNameWorkflowByWorkflowIdResponse, DeleteV0CityByCityNameWorkflowByWorkflowIdResponses, DeliveryContextRecord, Dep, DoctorAlertPayload, EmitEventData, EmitEventError, EmitEventErrors, EmitEventResponse, EmitEventResponses, EnsureExtmsgGroupData, EnsureExtmsgGroupError, EnsureExtmsgGroupErrors, EnsureExtmsgGroupResponse, EnsureExtmsgGroupResponses, ErrorDetail, ErrorModel, EventEmitOutputBody, EventEmitRequest, EventPayload, EventRotateAnchor, EventRotateArchive, EventRotateResponse, EventStreamEnvelope, ExternalActor, ExternalAttachment, ExternalInboundMessage, ExtmsgAdapterInfo, ExtMsgAdapterRegisterInputBody, ExtMsgAdapterRegisterOutputBody, ExtMsgAdapterUnregisterInputBody, ExtMsgBindInputBody, ExtMsgGroupEnsureInputBody, ExtMsgInboundInputBody, ExtMsgOutboundInputBody, ExtMsgParticipantRemoveInputBody, ExtMsgParticipantUpsertInputBody, ExtMsgTranscriptAckInputBody, ExtMsgUnbindBody, ExtMsgUnbindInputBody, FanoutPolicy, FormulaDetailResponse, FormulaFeedBody, FormulaListBody, FormulaPreviewBody, FormulaPreviewEdgeResponse, FormulaPreviewNodeResponse, FormulaPreviewResponse, FormulaRecentRunResponse, FormulaRunsResponse, FormulaSourceOutputBody, FormulaStepResponse, FormulaSummaryResponse, FormulaValidateOutputBody, FormulaVarDefResponse, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetV0CitiesData, GetV0CitiesError, GetV0CitiesErrors, GetV0CitiesResponse, GetV0CitiesResponses, GetV0CityByCityNameAgentByBaseData, GetV0CityByCityNameAgentByBaseError, GetV0CityByCityNameAgentByBaseErrors, GetV0CityByCityNameAgentByBaseOutputData, GetV0CityByCityNameAgentByBaseOutputError, GetV0CityByCityNameAgentByBaseOutputErrors, GetV0CityByCityNameAgentByBaseOutputResponse, GetV0CityByCityNameAgentByBaseOutputResponses, GetV0CityByCityNameAgentByBaseResponse, GetV0CityByCityNameAgentByBaseResponses, GetV0CityByCityNameAgentByDirByBaseData, GetV0CityByCityNameAgentByDirByBaseError, GetV0CityByCityNameAgentByDirByBaseErrors, GetV0CityByCityNameAgentByDirByBaseOutputData, GetV0CityByCityNameAgentByDirByBaseOutputError, GetV0CityByCityNameAgentByDirByBaseOutputErrors, GetV0CityByCityNameAgentByDirByBaseOutputResponse, GetV0CityByCityNameAgentByDirByBaseOutputResponses, GetV0CityByCityNameAgentByDirByBaseResponse, GetV0CityByCityNameAgentByDirByBaseResponses, GetV0CityByCityNameAgentsData, GetV0CityByCityNameAgentsError, GetV0CityByCityNameAgentsErrors, GetV0CityByCityNameAgentsResponse, GetV0CityByCityNameAgentsResponses, GetV0CityByCityNameBeadByIdData, GetV0CityByCityNameBeadByIdDepsData, GetV0CityByCityNameBeadByIdDepsError, GetV0CityByCityNameBeadByIdDepsErrors, GetV0CityByCityNameBeadByIdDepsResponse, GetV0CityByCityNameBeadByIdDepsResponses, GetV0CityByCityNameBeadByIdError, GetV0CityByCityNameBeadByIdErrors, GetV0CityByCityNameBeadByIdResponse, GetV0CityByCityNameBeadByIdResponses, GetV0CityByCityNameBeadsData, GetV0CityByCityNameBeadsError, GetV0CityByCityNameBeadsErrors, GetV0CityByCityNameBeadsGraphByRootIdData, GetV0CityByCityNameBeadsGraphByRootIdError, GetV0CityByCityNameBeadsGraphByRootIdErrors, GetV0CityByCityNameBeadsGraphByRootIdResponse, GetV0CityByCityNameBeadsGraphByRootIdResponses, GetV0CityByCityNameBeadsReadyData, GetV0CityByCityNameBeadsReadyError, GetV0CityByCityNameBeadsReadyErrors, GetV0CityByCityNameBeadsReadyResponse, GetV0CityByCityNameBeadsReadyResponses, GetV0CityByCityNameBeadsResponse, GetV0CityByCityNameBeadsResponses, GetV0CityByCityNameConfigData, GetV0CityByCityNameConfigDefaultsData, GetV0CityByCityNameConfigDefaultsError, GetV0CityByCityNameConfigDefaultsErrors, GetV0CityByCityNameConfigDefaultsResponse, GetV0CityByCityNameConfigDefaultsResponses, GetV0CityByCityNameConfigError, GetV0CityByCityNameConfigErrors, GetV0CityByCityNameConfigExplainData, GetV0CityByCityNameConfigExplainError, GetV0CityByCityNameConfigExplainErrors, GetV0CityByCityNameConfigExplainResponse, GetV0CityByCityNameConfigExplainResponses, GetV0CityByCityNameConfigResponse, GetV0CityByCityNameConfigResponses, GetV0CityByCityNameConfigValidateData, GetV0CityByCityNameConfigValidateError, GetV0CityByCityNameConfigValidateErrors, GetV0CityByCityNameConfigValidateResponse, GetV0CityByCityNameConfigValidateResponses, GetV0CityByCityNameConvoyByIdCheckData, GetV0CityByCityNameConvoyByIdCheckError, GetV0CityByCityNameConvoyByIdCheckErrors, GetV0CityByCityNameConvoyByIdCheckResponse, GetV0CityByCityNameConvoyByIdCheckResponses, GetV0CityByCityNameConvoyByIdData, GetV0CityByCityNameConvoyByIdError, GetV0CityByCityNameConvoyByIdErrors, GetV0CityByCityNameConvoyByIdResponse, GetV0CityByCityNameConvoyByIdResponses, GetV0CityByCityNameConvoysData, GetV0CityByCityNameConvoysError, GetV0CityByCityNameConvoysErrors, GetV0CityByCityNameConvoysResponse, GetV0CityByCityNameConvoysResponses, GetV0CityByCityNameData, GetV0CityByCityNameError, GetV0CityByCityNameErrors, GetV0CityByCityNameEventsData, GetV0CityByCityNameEventsError, GetV0CityByCityNameEventsErrors, GetV0CityByCityNameEventsResponse, GetV0CityByCityNameEventsResponses, GetV0CityByCityNameExtmsgAdaptersData, GetV0CityByCityNameExtmsgAdaptersError, GetV0CityByCityNameExtmsgAdaptersErrors, GetV0CityByCityNameExtmsgAdaptersResponse, GetV0CityByCityNameExtmsgAdaptersResponses, GetV0CityByCityNameExtmsgBindingsData, GetV0CityByCityNameExtmsgBindingsError, GetV0CityByCityNameExtmsgBindingsErrors, GetV0CityByCityNameExtmsgBindingsResponse, GetV0CityByCityNameExtmsgBindingsResponses, GetV0CityByCityNameExtmsgGroupsData, GetV0CityByCityNameExtmsgGroupsError, GetV0CityByCityNameExtmsgGroupsErrors, GetV0CityByCityNameExtmsgGroupsResponse, GetV0CityByCityNameExtmsgGroupsResponses, GetV0CityByCityNameExtmsgTranscriptData, GetV0CityByCityNameExtmsgTranscriptError, GetV0CityByCityNameExtmsgTranscriptErrors, GetV0CityByCityNameExtmsgTranscriptResponse, GetV0CityByCityNameExtmsgTranscriptResponses, GetV0CityByCityNameFormulaByNameData, GetV0CityByCityNameFormulaByNameError, GetV0CityByCityNameFormulaByNameErrors, GetV0CityByCityNameFormulaByNameResponse, GetV0CityByCityNameFormulaByNameResponses, GetV0CityByCityNameFormulasByNameData, GetV0CityByCityNameFormulasByNameError, GetV0CityByCityNameFormulasByNameErrors, GetV0CityByCityNameFormulasByNameResponse, GetV0CityByCityNameFormulasByNameResponses, GetV0CityByCityNameFormulasByNameRunsData, GetV0CityByCityNameFormulasByNameRunsError, GetV0CityByCityNameFormulasByNameRunsErrors, GetV0CityByCityNameFormulasByNameRunsResponse, GetV0CityByCityNameFormulasByNameRunsResponses, GetV0CityByCityNameFormulasByNameSourceData, GetV0CityByCityNameFormulasByNameSourceError, GetV0CityByCityNameFormulasByNameSourceErrors, GetV0CityByCityNameFormulasByNameSourceResponse, GetV0CityByCityNameFormulasByNameSourceResponses, GetV0CityByCityNameFormulasData, GetV0CityByCityNameFormulasError, GetV0CityByCityNameFormulasErrors, GetV0CityByCityNameFormulasFeedData, GetV0CityByCityNameFormulasFeedError, GetV0CityByCityNameFormulasFeedErrors, GetV0CityByCityNameFormulasFeedResponse, GetV0CityByCityNameFormulasFeedResponses, GetV0CityByCityNameFormulasResponse, GetV0CityByCityNameFormulasResponses, GetV0CityByCityNameHealthData, GetV0CityByCityNameHealthError, GetV0CityByCityNameHealthErrors, GetV0CityByCityNameHealthResponse, GetV0CityByCityNameHealthResponses, GetV0CityByCityNameMailByIdData, GetV0CityByCityNameMailByIdError, GetV0CityByCityNameMailByIdErrors, GetV0CityByCityNameMailByIdResponse, GetV0CityByCityNameMailByIdResponses, GetV0CityByCityNameMailCountData, GetV0CityByCityNameMailCountError, GetV0CityByCityNameMailCountErrors, GetV0CityByCityNameMailCountResponse, GetV0CityByCityNameMailCountResponses, GetV0CityByCityNameMailData, GetV0CityByCityNameMailError, GetV0CityByCityNameMailErrors, GetV0CityByCityNameMailResponse, GetV0CityByCityNameMailResponses, GetV0CityByCityNameMailThreadByIdData, GetV0CityByCityNameMailThreadByIdError, GetV0CityByCityNameMailThreadByIdErrors, GetV0CityByCityNameMailThreadByIdResponse, GetV0CityByCityNameMailThreadByIdResponses, GetV0CityByCityNameMaintenanceStatusData, GetV0CityByCityNameMaintenanceStatusError, GetV0CityByCityNameMaintenanceStatusErrors, GetV0CityByCityNameMaintenanceStatusResponse, GetV0CityByCityNameMaintenanceStatusResponses, GetV0CityByCityNameOrderByNameData, GetV0CityByCityNameOrderByNameError, GetV0CityByCityNameOrderByNameErrors, GetV0CityByCityNameOrderByNameResponse, GetV0CityByCityNameOrderByNameResponses, GetV0CityByCityNameOrderHistoryByBeadIdData, GetV0CityByCityNameOrderHistoryByBeadIdError, GetV0CityByCityNameOrderHistoryByBeadIdErrors, GetV0CityByCityNameOrderHistoryByBeadIdResponse, GetV0CityByCityNameOrderHistoryByBeadIdResponses, GetV0CityByCityNameOrdersCheckData, GetV0CityByCityNameOrdersCheckError, GetV0CityByCityNameOrdersCheckErrors, GetV0CityByCityNameOrdersCheckResponse, GetV0CityByCityNameOrdersCheckResponses, GetV0CityByCityNameOrdersData, GetV0CityByCityNameOrdersError, GetV0CityByCityNameOrdersErrors, GetV0CityByCityNameOrdersFeedData, GetV0CityByCityNameOrdersFeedError, GetV0CityByCityNameOrdersFeedErrors, GetV0CityByCityNameOrdersFeedResponse, GetV0CityByCityNameOrdersFeedResponses, GetV0CityByCityNameOrdersHistoryData, GetV0CityByCityNameOrdersHistoryError, GetV0CityByCityNameOrdersHistoryErrors, GetV0CityByCityNameOrdersHistoryResponse, GetV0CityByCityNameOrdersHistoryResponses, GetV0CityByCityNameOrdersResponse, GetV0CityByCityNameOrdersResponses, GetV0CityByCityNamePacksData, GetV0CityByCityNamePacksError, GetV0CityByCityNamePacksErrors, GetV0CityByCityNamePacksResponse, GetV0CityByCityNamePacksResponses, GetV0CityByCityNamePatchesAgentByBaseData, GetV0CityByCityNamePatchesAgentByBaseError, GetV0CityByCityNamePatchesAgentByBaseErrors, GetV0CityByCityNamePatchesAgentByBaseResponse, GetV0CityByCityNamePatchesAgentByBaseResponses, GetV0CityByCityNamePatchesAgentByDirByBaseData, GetV0CityByCityNamePatchesAgentByDirByBaseError, GetV0CityByCityNamePatchesAgentByDirByBaseErrors, GetV0CityByCityNamePatchesAgentByDirByBaseResponse, GetV0CityByCityNamePatchesAgentByDirByBaseResponses, GetV0CityByCityNamePatchesAgentsData, GetV0CityByCityNamePatchesAgentsError, GetV0CityByCityNamePatchesAgentsErrors, GetV0CityByCityNamePatchesAgentsResponse, GetV0CityByCityNamePatchesAgentsResponses, GetV0CityByCityNamePatchesProviderByNameData, GetV0CityByCityNamePatchesProviderByNameError, GetV0CityByCityNamePatchesProviderByNameErrors, GetV0CityByCityNamePatchesProviderByNameResponse, GetV0CityByCityNamePatchesProviderByNameResponses, GetV0CityByCityNamePatchesProvidersData, GetV0CityByCityNamePatchesProvidersError, GetV0CityByCityNamePatchesProvidersErrors, GetV0CityByCityNamePatchesProvidersResponse, GetV0CityByCityNamePatchesProvidersResponses, GetV0CityByCityNamePatchesRigByNameData, GetV0CityByCityNamePatchesRigByNameError, GetV0CityByCityNamePatchesRigByNameErrors, GetV0CityByCityNamePatchesRigByNameResponse, GetV0CityByCityNamePatchesRigByNameResponses, GetV0CityByCityNamePatchesRigsData, GetV0CityByCityNamePatchesRigsError, GetV0CityByCityNamePatchesRigsErrors, GetV0CityByCityNamePatchesRigsResponse, GetV0CityByCityNamePatchesRigsResponses, GetV0CityByCityNamePendingData, GetV0CityByCityNamePendingError, GetV0CityByCityNamePendingErrors, GetV0CityByCityNamePendingResponse, GetV0CityByCityNamePendingResponses, GetV0CityByCityNameProviderByNameData, GetV0CityByCityNameProviderByNameError, GetV0CityByCityNameProviderByNameErrors, GetV0CityByCityNameProviderByNameResponse, GetV0CityByCityNameProviderByNameResponses, GetV0CityByCityNameProviderReadinessData, GetV0CityByCityNameProviderReadinessError, GetV0CityByCityNameProviderReadinessErrors, GetV0CityByCityNameProviderReadinessResponse, GetV0CityByCityNameProviderReadinessResponses, GetV0CityByCityNameProvidersData, GetV0CityByCityNameProvidersError, GetV0CityByCityNameProvidersErrors, GetV0CityByCityNameProvidersPublicData, GetV0CityByCityNameProvidersPublicError, GetV0CityByCityNameProvidersPublicErrors, GetV0CityByCityNameProvidersPublicResponse, GetV0CityByCityNameProvidersPublicResponses, GetV0CityByCityNameProvidersResponse, GetV0CityByCityNameProvidersResponses, GetV0CityByCityNameReadinessData, GetV0CityByCityNameReadinessError, GetV0CityByCityNameReadinessErrors, GetV0CityByCityNameReadinessResponse, GetV0CityByCityNameReadinessResponses, GetV0CityByCityNameResponse, GetV0CityByCityNameResponses, GetV0CityByCityNameRigByNameData, GetV0CityByCityNameRigByNameError, GetV0CityByCityNameRigByNameErrors, GetV0CityByCityNameRigByNameResponse, GetV0CityByCityNameRigByNameResponses, GetV0CityByCityNameRigsData, GetV0CityByCityNameRigsError, GetV0CityByCityNameRigsErrors, GetV0CityByCityNameRigsResponse, GetV0CityByCityNameRigsResponses, GetV0CityByCityNameRunsByRunIdData, GetV0CityByCityNameRunsByRunIdError, GetV0CityByCityNameRunsByRunIdErrors, GetV0CityByCityNameRunsByRunIdResponse, GetV0CityByCityNameRunsByRunIdResponses, GetV0CityByCityNameRunsByRunIdStepsData, GetV0CityByCityNameRunsByRunIdStepsError, GetV0CityByCityNameRunsByRunIdStepsErrors, GetV0CityByCityNameRunsByRunIdStepsResponse, GetV0CityByCityNameRunsByRunIdStepsResponses, GetV0CityByCityNameRunsCensusData, GetV0CityByCityNameRunsCensusError, GetV0CityByCityNameRunsCensusErrors, GetV0CityByCityNameRunsCensusResponse, GetV0CityByCityNameRunsCensusResponses, GetV0CityByCityNameRunsData, GetV0CityByCityNameRunsError, GetV0CityByCityNameRunsErrors, GetV0CityByCityNameRunsResponse, GetV0CityByCityNameRunsResponses, GetV0CityByCityNameServiceByNameData, GetV0CityByCityNameServiceByNameError, GetV0CityByCityNameServiceByNameErrors, GetV0CityByCityNameServiceByNameResponse, GetV0CityByCityNameServiceByNameResponses, GetV0CityByCityNameServicesData, GetV0CityByCityNameServicesError, GetV0CityByCityNameServicesErrors, GetV0CityByCityNameServicesResponse, GetV0CityByCityNameServicesResponses, GetV0CityByCityNameSessionByIdAgentsByAgentIdData, GetV0CityByCityNameSessionByIdAgentsByAgentIdError, GetV0CityByCityNameSessionByIdAgentsByAgentIdErrors, GetV0CityByCityNameSessionByIdAgentsByAgentIdResponse, GetV0CityByCityNameSessionByIdAgentsByAgentIdResponses, GetV0CityByCityNameSessionByIdAgentsData, GetV0CityByCityNameSessionByIdAgentsError, GetV0CityByCityNameSessionByIdAgentsErrors, GetV0CityByCityNameSessionByIdAgentsResponse, GetV0CityByCityNameSessionByIdAgentsResponses, GetV0CityByCityNameSessionByIdData, GetV0CityByCityNameSessionByIdError, GetV0CityByCityNameSessionByIdErrors, GetV0CityByCityNameSessionByIdPendingData, GetV0CityByCityNameSessionByIdPendingError, GetV0CityByCityNameSessionByIdPendingErrors, GetV0CityByCityNameSessionByIdPendingResponse, GetV0CityByCityNameSessionByIdPendingResponses, GetV0CityByCityNameSessionByIdResponse, GetV0CityByCityNameSessionByIdResponses, GetV0CityByCityNameSessionByIdTranscriptData, GetV0CityByCityNameSessionByIdTranscriptError, GetV0CityByCityNameSessionByIdTranscriptErrors, GetV0CityByCityNameSessionByIdTranscriptResponse, GetV0CityByCityNameSessionByIdTranscriptResponses, GetV0CityByCityNameSessionsData, GetV0CityByCityNameSessionsError, GetV0CityByCityNameSessionsErrors, GetV0CityByCityNameSessionsResponse, GetV0CityByCityNameSessionsResponses, GetV0CityByCityNameStatusData, GetV0CityByCityNameStatusError, GetV0CityByCityNameStatusErrors, GetV0CityByCityNameStatusResponse, GetV0CityByCityNameStatusResponses, GetV0CityByCityNameUsageData, GetV0CityByCityNameUsageError, GetV0CityByCityNameUsageErrors, GetV0CityByCityNameUsageResponse, GetV0CityByCityNameUsageResponses, GetV0CityByCityNameWaitByIdData, GetV0CityByCityNameWaitByIdError, GetV0CityByCityNameWaitByIdErrors, GetV0CityByCityNameWaitByIdResponse, GetV0CityByCityNameWaitByIdResponses, GetV0CityByCityNameWaitsData, GetV0CityByCityNameWaitsError, GetV0CityByCityNameWaitsErrors, GetV0CityByCityNameWaitsResponse, GetV0CityByCityNameWaitsResponses, GetV0CityByCityNameWorkflowByWorkflowIdData, GetV0CityByCityNameWorkflowByWorkflowIdError, GetV0CityByCityNameWorkflowByWorkflowIdErrors, GetV0CityByCityNameWorkflowByWorkflowIdResponse, GetV0CityByCityNameWorkflowByWorkflowIdResponses, GetV0EventsData, GetV0EventsError, GetV0EventsErrors, GetV0EventsResponse, GetV0EventsResponses, GetV0ProviderReadinessData, GetV0ProviderReadinessError, GetV0ProviderReadinessErrors, GetV0ProviderReadinessResponse, GetV0ProviderReadinessResponses, GetV0ReadinessData, GetV0ReadinessError, GetV0ReadinessErrors, GetV0ReadinessResponse, GetV0ReadinessResponses, GitStatus, GroupCreatedEventPayload, GroupRouteDecision, HealthOutputBody, HeartbeatEvent, InboundEventPayload, InboundResult, ListBodyAgentPatch, ListBodyAgentResponse, ListBodyBead, ListBodyCityPendingEntry, ListBodyConversationTranscriptRecord, ListBodyExtmsgAdapterInfo, ListBodyProviderPatch, ListBodyProviderResponse, ListBodyRigPatch, ListBodyRigResponse, ListBodySessionBindingRecord, ListBodySessionResponse, ListBodyStatus, ListBodyWireEvent, LogicalNode, MailCountOutputBody, MailEventPayload, MailListBody, MailReplyInputBody, MailSendInputBody, MaintenanceRunBody, MaintenanceStatusBody, MaintenanceTriggerBody, Message, MoleculeResolvedPayload, MonitorFeedItemResponse, NoPayload, OkResponseBody, OkWithIdResponseBody, OptionChoiceDto, OrderCheckListBody, OrderCheckResponse, OrderGateTimeoutFailOpenPayload, OrderHistoryDetailResponse, OrderHistoryEntry, OrderHistoryListBody, OrderListBody, OrderResponse, OrderRunInputBody, OrderRunOutputBody, OrdersFeedBody, OutboundChannelMismatchPayload, OutboundEventPayload, OutboundResult, OutputTurn, PackAddedOutputBody, PackAddInputBody, PackListBody, PackRemovedOutputBody, PackResponse, PaginationInfo, PatchDeletedResponseBody, PatchOkResponseBody, PatchV0CityByCityNameAgentByBaseData, PatchV0CityByCityNameAgentByBaseError, PatchV0CityByCityNameAgentByBaseErrors, PatchV0CityByCityNameAgentByBaseResponse, PatchV0CityByCityNameAgentByBaseResponses, PatchV0CityByCityNameAgentByDirByBaseData, PatchV0CityByCityNameAgentByDirByBaseError, PatchV0CityByCityNameAgentByDirByBaseErrors, PatchV0CityByCityNameAgentByDirByBaseResponse, PatchV0CityByCityNameAgentByDirByBaseResponses, PatchV0CityByCityNameBeadByIdData, PatchV0CityByCityNameBeadByIdError, PatchV0CityByCityNameBeadByIdErrors, PatchV0CityByCityNameBeadByIdResponse, PatchV0CityByCityNameBeadByIdResponses, PatchV0CityByCityNameData, PatchV0CityByCityNameError, PatchV0CityByCityNameErrors, PatchV0CityByCityNameProviderByNameData, PatchV0CityByCityNameProviderByNameError, PatchV0CityByCityNameProviderByNameErrors, PatchV0CityByCityNameProviderByNameResponse, PatchV0CityByCityNameProviderByNameResponses, PatchV0CityByCityNameResponse, PatchV0CityByCityNameResponses, PatchV0CityByCityNameRigByNameData, PatchV0CityByCityNameRigByNameError, PatchV0CityByCityNameRigByNameErrors, PatchV0CityByCityNameRigByNameResponse, PatchV0CityByCityNameRigByNameResponses, PatchV0CityByCityNameSessionByIdData, PatchV0CityByCityNameSessionByIdError, PatchV0CityByCityNameSessionByIdErrors, PatchV0CityByCityNameSessionByIdResponse, PatchV0CityByCityNameSessionByIdResponses, PendingInteraction, PoolOverride, PostgresCredentialResolvedPayload, PostV0CityByCityNameAgentByBaseByActionData, PostV0CityByCityNameAgentByBaseByActionError, PostV0CityByCityNameAgentByBaseByActionErrors, PostV0CityByCityNameAgentByBaseByActionResponse, PostV0CityByCityNameAgentByBaseByActionResponses, PostV0CityByCityNameAgentByDirByBaseByActionData, PostV0CityByCityNameAgentByDirByBaseByActionError, PostV0CityByCityNameAgentByDirByBaseByActionErrors, PostV0CityByCityNameAgentByDirByBaseByActionResponse, PostV0CityByCityNameAgentByDirByBaseByActionResponses, PostV0CityByCityNameBeadByIdAssignData, PostV0CityByCityNameBeadByIdAssignError, PostV0CityByCityNameBeadByIdAssignErrors, PostV0CityByCityNameBeadByIdAssignResponse, PostV0CityByCityNameBeadByIdAssignResponses, PostV0CityByCityNameBeadByIdCloseData, PostV0CityByCityNameBeadByIdCloseError, PostV0CityByCityNameBeadByIdCloseErrors, PostV0CityByCityNameBeadByIdCloseResponse, PostV0CityByCityNameBeadByIdCloseResponses, PostV0CityByCityNameBeadByIdReopenData, PostV0CityByCityNameBeadByIdReopenError, PostV0CityByCityNameBeadByIdReopenErrors, PostV0CityByCityNameBeadByIdReopenResponse, PostV0CityByCityNameBeadByIdReopenResponses, PostV0CityByCityNameBeadByIdUpdateData, PostV0CityByCityNameBeadByIdUpdateError, PostV0CityByCityNameBeadByIdUpdateErrors, PostV0CityByCityNameBeadByIdUpdateResponse, PostV0CityByCityNameBeadByIdUpdateResponses, PostV0CityByCityNameConvoyByIdAddData, PostV0CityByCityNameConvoyByIdAddError, PostV0CityByCityNameConvoyByIdAddErrors, PostV0CityByCityNameConvoyByIdAddResponse, PostV0CityByCityNameConvoyByIdAddResponses, PostV0CityByCityNameConvoyByIdCloseData, PostV0CityByCityNameConvoyByIdCloseError, PostV0CityByCityNameConvoyByIdCloseErrors, PostV0CityByCityNameConvoyByIdCloseResponse, PostV0CityByCityNameConvoyByIdCloseResponses, PostV0CityByCityNameConvoyByIdRemoveData, PostV0CityByCityNameConvoyByIdRemoveError, PostV0CityByCityNameConvoyByIdRemoveErrors, PostV0CityByCityNameConvoyByIdRemoveResponse, PostV0CityByCityNameConvoyByIdRemoveResponses, PostV0CityByCityNameExtmsgBindData, PostV0CityByCityNameExtmsgBindError, PostV0CityByCityNameExtmsgBindErrors, PostV0CityByCityNameExtmsgBindResponse, PostV0CityByCityNameExtmsgBindResponses, PostV0CityByCityNameExtmsgInboundData, PostV0CityByCityNameExtmsgInboundError, PostV0CityByCityNameExtmsgInboundErrors, PostV0CityByCityNameExtmsgInboundResponse, PostV0CityByCityNameExtmsgInboundResponses, PostV0CityByCityNameExtmsgOutboundData, PostV0CityByCityNameExtmsgOutboundError, PostV0CityByCityNameExtmsgOutboundErrors, PostV0CityByCityNameExtmsgOutboundResponse, PostV0CityByCityNameExtmsgOutboundResponses, PostV0CityByCityNameExtmsgParticipantsData, PostV0CityByCityNameExtmsgParticipantsError, PostV0CityByCityNameExtmsgParticipantsErrors, PostV0CityByCityNameExtmsgParticipantsResponse, PostV0CityByCityNameExtmsgParticipantsResponses, PostV0CityByCityNameExtmsgTranscriptAckData, PostV0CityByCityNameExtmsgTranscriptAckError, PostV0CityByCityNameExtmsgTranscriptAckErrors, PostV0CityByCityNameExtmsgTranscriptAckResponse, PostV0CityByCityNameExtmsgTranscriptAckResponses, PostV0CityByCityNameExtmsgUnbindData, PostV0CityByCityNameExtmsgUnbindError, PostV0CityByCityNameExtmsgUnbindErrors, PostV0CityByCityNameExtmsgUnbindResponse, PostV0CityByCityNameExtmsgUnbindResponses, PostV0CityByCityNameFormulasByNamePreviewData, PostV0CityByCityNameFormulasByNamePreviewError, PostV0CityByCityNameFormulasByNamePreviewErrors, PostV0CityByCityNameFormulasByNamePreviewResponse, PostV0CityByCityNameFormulasByNamePreviewResponses, PostV0CityByCityNameFormulasByNameValidateData, PostV0CityByCityNameFormulasByNameValidateError, PostV0CityByCityNameFormulasByNameValidateErrors, PostV0CityByCityNameFormulasByNameValidateResponse, PostV0CityByCityNameFormulasByNameValidateResponses, PostV0CityByCityNameMailByIdArchiveData, PostV0CityByCityNameMailByIdArchiveError, PostV0CityByCityNameMailByIdArchiveErrors, PostV0CityByCityNameMailByIdArchiveResponse, PostV0CityByCityNameMailByIdArchiveResponses, PostV0CityByCityNameMailByIdMarkUnreadData, PostV0CityByCityNameMailByIdMarkUnreadError, PostV0CityByCityNameMailByIdMarkUnreadErrors, PostV0CityByCityNameMailByIdMarkUnreadResponse, PostV0CityByCityNameMailByIdMarkUnreadResponses, PostV0CityByCityNameMailByIdReadData, PostV0CityByCityNameMailByIdReadError, PostV0CityByCityNameMailByIdReadErrors, PostV0CityByCityNameMailByIdReadResponse, PostV0CityByCityNameMailByIdReadResponses, PostV0CityByCityNameOrderByNameDisableData, PostV0CityByCityNameOrderByNameDisableError, PostV0CityByCityNameOrderByNameDisableErrors, PostV0CityByCityNameOrderByNameDisableResponse, PostV0CityByCityNameOrderByNameDisableResponses, PostV0CityByCityNameOrderByNameEnableData, PostV0CityByCityNameOrderByNameEnableError, PostV0CityByCityNameOrderByNameEnableErrors, PostV0CityByCityNameOrderByNameEnableResponse, PostV0CityByCityNameOrderByNameEnableResponses, PostV0CityByCityNameOrderByNameRunData, PostV0CityByCityNameOrderByNameRunError, PostV0CityByCityNameOrderByNameRunErrors, PostV0CityByCityNameOrderByNameRunResponse, PostV0CityByCityNameOrderByNameRunResponses, PostV0CityByCityNameRigByNameByActionData, PostV0CityByCityNameRigByNameByActionError, PostV0CityByCityNameRigByNameByActionErrors, PostV0CityByCityNameRigByNameByActionResponse, PostV0CityByCityNameRigByNameByActionResponses, PostV0CityByCityNameRunsByRunIdCancelData, PostV0CityByCityNameRunsByRunIdCancelError, PostV0CityByCityNameRunsByRunIdCancelErrors, PostV0CityByCityNameRunsByRunIdCancelResponse, PostV0CityByCityNameRunsByRunIdCancelResponses, PostV0CityByCityNameServiceByNameRestartData, PostV0CityByCityNameServiceByNameRestartError, PostV0CityByCityNameServiceByNameRestartErrors, PostV0CityByCityNameServiceByNameRestartResponse, PostV0CityByCityNameServiceByNameRestartResponses, PostV0CityByCityNameSessionByIdCloseData, PostV0CityByCityNameSessionByIdCloseError, PostV0CityByCityNameSessionByIdCloseErrors, PostV0CityByCityNameSessionByIdCloseResponse, PostV0CityByCityNameSessionByIdCloseResponses, PostV0CityByCityNameSessionByIdKillData, PostV0CityByCityNameSessionByIdKillError, PostV0CityByCityNameSessionByIdKillErrors, PostV0CityByCityNameSessionByIdKillResponse, PostV0CityByCityNameSessionByIdKillResponses, PostV0CityByCityNameSessionByIdPermissionModeData, PostV0CityByCityNameSessionByIdPermissionModeError, PostV0CityByCityNameSessionByIdPermissionModeErrors, PostV0CityByCityNameSessionByIdPermissionModeResponse, PostV0CityByCityNameSessionByIdPermissionModeResponses, PostV0CityByCityNameSessionByIdRenameData, PostV0CityByCityNameSessionByIdRenameError, PostV0CityByCityNameSessionByIdRenameErrors, PostV0CityByCityNameSessionByIdRenameResponse, PostV0CityByCityNameSessionByIdRenameResponses, PostV0CityByCityNameSessionByIdStopData, PostV0CityByCityNameSessionByIdStopError, PostV0CityByCityNameSessionByIdStopErrors, PostV0CityByCityNameSessionByIdStopResponse, PostV0CityByCityNameSessionByIdStopResponses, PostV0CityByCityNameSessionByIdSuspendData, PostV0CityByCityNameSessionByIdSuspendError, PostV0CityByCityNameSessionByIdSuspendErrors, PostV0CityByCityNameSessionByIdSuspendResponse, PostV0CityByCityNameSessionByIdSuspendResponses, PostV0CityByCityNameSessionByIdWakeData, PostV0CityByCityNameSessionByIdWakeError, PostV0CityByCityNameSessionByIdWakeErrors, PostV0CityByCityNameSessionByIdWakeResponse, PostV0CityByCityNameSessionByIdWakeResponses, PostV0CityByCityNameSlingData, PostV0CityByCityNameSlingError, PostV0CityByCityNameSlingErrors, PostV0CityByCityNameSlingResponse, PostV0CityByCityNameSlingResponses, PostV0CityByCityNameUnregisterData, PostV0CityByCityNameUnregisterError, PostV0CityByCityNameUnregisterErrors, PostV0CityByCityNameUnregisterResponse, PostV0CityByCityNameUnregisterResponses, PostV0CityData, PostV0CityError, PostV0CityErrors, PostV0CityResponse, PostV0CityResponses, ProjectIdentityStampedPayload, ProviderCreatedOutputBody, ProviderCreateInputBody, ProviderOptionDto, ProviderPatch, ProviderPatchSetInputBody, ProviderPublicListBody, ProviderPublicResponse, ProviderReadiness, ProviderReadinessResponse, ProviderResponse, ProviderSpecJson, ProviderUpdateInputBody, ProxyReapedPayload, PublishReceipt, PutV0CityByCityNameFormulasByNameData, PutV0CityByCityNameFormulasByNameError, PutV0CityByCityNameFormulasByNameErrors, PutV0CityByCityNameFormulasByNameResponse, PutV0CityByCityNameFormulasByNameResponses, PutV0CityByCityNamePatchesAgentsData, PutV0CityByCityNamePatchesAgentsError, PutV0CityByCityNamePatchesAgentsErrors, PutV0CityByCityNamePatchesAgentsResponse, PutV0CityByCityNamePatchesAgentsResponses, PutV0CityByCityNamePatchesProvidersData, PutV0CityByCityNamePatchesProvidersError, PutV0CityByCityNamePatchesProvidersErrors, PutV0CityByCityNamePatchesProvidersResponse, PutV0CityByCityNamePatchesProvidersResponses, PutV0CityByCityNamePatchesRigsData, PutV0CityByCityNamePatchesRigsError, PutV0CityByCityNamePatchesRigsErrors, PutV0CityByCityNamePatchesRigsResponse, PutV0CityByCityNamePatchesRigsResponses, QuotaObservedPayload, QuotaPollFailedPayload, ReadinessItem, ReadinessResponse, Record, RegisterExtmsgAdapterData, RegisterExtmsgAdapterError, RegisterExtmsgAdapterErrors, RegisterExtmsgAdapterResponse, RegisterExtmsgAdapterResponses, ReplyMailData, ReplyMailError, ReplyMailErrors, ReplyMailResponse, ReplyMailResponses, RequestFailedPayload, RespondSessionData, RespondSessionError, RespondSessionErrors, RespondSessionResponse, RespondSessionResponses, RigActionBody, RigCreateBody, RigCreateResponseBody, RigCreateSucceededPayload, RigPatch, RigPatchSetInputBody, RigProvisionProgressPayload, RigResponse, RigUpdateInputBody, RotatedPayload, RotateEventsData, RotateEventsError, RotateEventsErrors, RotateEventsResponse, RotateEventsResponses, Run, RunCancelOutputBody, RunLastError, RunRef, RunsCensusOutputBody, RunScope, RunsListOutputBody, RunStatus, RunStatusCounts, RunStep, RunStepsOutputBody, RunStepStatus, ScopeGroup, SendMailData, SendMailError, SendMailErrors, SendMailResponse, SendMailResponses, SendSessionMessageData, SendSessionMessageError, SendSessionMessageErrors, SendSessionMessageResponse, SendSessionMessageResponses, ServiceRestartOutputBody, SessionActivityEvent, SessionAgentGetResponse, SessionAgentListResponse, SessionBindingRecord, SessionCreateBody, SessionCreateSucceededPayload, SessionDrainAckedWithAssignedWorkPayload, SessionInfo, SessionLifecyclePayload, SessionMessageInputBody, SessionMessageSucceededPayload, SessionPatchBody, SessionPendingClearedEvent, SessionPendingResponse, SessionPermissionModeBody, SessionRawMessageFrame, SessionRenameInputBody, SessionResetStalledPayload, SessionRespondInputBody, SessionRespondOutputBody, SessionResponse, SessionStrandedPayload, SessionStreamCommonEvent, SessionStreamMessageEvent, SessionStreamRawMessageEvent, SessionStreamStructuredMessageEvent, SessionStructuredArgument, SessionStructuredBlock, SessionStructuredBlockImage, SessionStructuredBlockInteraction, SessionStructuredBlockText, SessionStructuredBlockThinking, SessionStructuredBlockToolResult, SessionStructuredBlockToolUse, SessionStructuredBlockUnknown, SessionStructuredContinuity, SessionStructuredCursor, SessionStructuredDiagnostic, SessionStructuredGeneration, SessionStructuredHistory, SessionStructuredIdeSelection, SessionStructuredInteraction, SessionStructuredMessage, SessionStructuredMessageAssistant, SessionStructuredMessageSystem, SessionStructuredMessageTool, SessionStructuredMessageUnknown, SessionStructuredMessageUser, SessionStructuredPatchHunk, SessionStructuredPlanStep, SessionStructuredQuestion, SessionStructuredQuestionOption, SessionStructuredSearchResultItem, SessionStructuredSystemEvent, SessionStructuredTailState, SessionStructuredTodoItem, SessionStructuredToolError, SessionStructuredToolInput, SessionStructuredToolInputArguments, SessionStructuredToolInputCode, SessionStructuredToolInputCommand, SessionStructuredToolInputFetch, SessionStructuredToolInputFile, SessionStructuredToolInputGlob, SessionStructuredToolInputPatch, SessionStructuredToolInputPlan, SessionStructuredToolInputQuestion, SessionStructuredToolInputSearch, SessionStructuredToolInputStdin, SessionStructuredToolInputTask, SessionStructuredToolInputText, SessionStructuredToolInputTodo, SessionStructuredToolInputUnknown, SessionStructuredToolInputWrite, SessionStructuredToolResult, SessionStructuredToolResultBash, SessionStructuredToolResultEdit, SessionStructuredToolResultFetch, SessionStructuredToolResultGlob, SessionStructuredToolResultGrep, SessionStructuredToolResultPlan, SessionStructuredToolResultPython, SessionStructuredToolResultQuestion, SessionStructuredToolResultRead, SessionStructuredToolResultSearch, SessionStructuredToolResultStdin, SessionStructuredToolResultTask, SessionStructuredToolResultText, SessionStructuredToolResultTodo, SessionStructuredToolResultUnknown, SessionStructuredToolResultWrite, SessionStructuredUploadedFile, SessionStructuredUsage, SessionStructuredUserPrompt, SessionSubmitInputBody, SessionSubmitSucceededPayload, SessionTranscriptConversationResponse, SessionTranscriptGetResponse, SessionTranscriptRawResponse, SessionTranscriptStructuredResponse, SessionUnknownStatePayload, SlingInputBody, SlingResponse, Status, StatusAgentCounts, StatusAgentDetail, StatusBody, StatusConditionalWrites, StatusConditionalWriteStoreVerdict, StatusMailCounts, StatusNamedSessionDetail, StatusRigCounts, StatusRigDetail, StatusRolloutNotice, StatusSessionCountsDetail, StatusStoreHealth, StatusWorkCounts, StoreDegradedPayload, StoreDiskCriticalPayload, StoreDiskWarnPayload, StoreMaintenanceDonePayload, StoreMaintenanceFailedPayload, StoreProbeFailedPayload, StoreRecoveredPayload, StreamAgentOutputData, StreamAgentOutputError, StreamAgentOutputErrors, StreamAgentOutputQualifiedData, StreamAgentOutputQualifiedError, StreamAgentOutputQualifiedErrors, StreamAgentOutputQualifiedResponse, StreamAgentOutputQualifiedResponses, StreamAgentOutputResponse, StreamAgentOutputResponses, StreamEventsData, StreamEventsError, StreamEventsErrors, StreamEventsResponse, StreamEventsResponses, StreamSessionData, StreamSessionError, StreamSessionErrors, StreamSessionResponse, StreamSessionResponses, StreamSupervisorEventsData, StreamSupervisorEventsError, StreamSupervisorEventsErrors, StreamSupervisorEventsResponse, StreamSupervisorEventsResponses, SubmissionCapabilities, SubmitIntent, SubmitSessionData, SubmitSessionError, SubmitSessionErrors, SubmitSessionResponse, SubmitSessionResponses, SupervisorCitiesOutputBody, SupervisorEventListOutputBody, SupervisorFsPressureSkippedTickPayload, SupervisorHealthOutputBody, SupervisorRequestPayload, SupervisorShutdownPayload, SupervisorStartedPayload, SupervisorStartup, TaggedEventStreamEnvelope, TranscriptMessageKind, TranscriptProvenance, TriggerMaintenanceDoltGcData, TriggerMaintenanceDoltGcError, TriggerMaintenanceDoltGcErrors, TriggerMaintenanceDoltGcResponse, TriggerMaintenanceDoltGcResponses, TypedEventStreamEnvelope, TypedEventStreamEnvelopeBeadClaimRejected, TypedEventStreamEnvelopeBeadClosed, TypedEventStreamEnvelopeBeadCreated, TypedEventStreamEnvelopeBeadDeadAssigneeReopened, TypedEventStreamEnvelopeBeadDeleted, TypedEventStreamEnvelopeBeadsConditionalWritesDegraded, TypedEventStreamEnvelopeBeadUpdated, TypedEventStreamEnvelopeBeadWorktreeReaped, TypedEventStreamEnvelopeBeadWorktreeReapSkipped, TypedEventStreamEnvelopeBreakerStateChanged, TypedEventStreamEnvelopeCityCreated, TypedEventStreamEnvelopeCityResumed, TypedEventStreamEnvelopeCitySuspended, TypedEventStreamEnvelopeCityUnregisterRequested, TypedEventStreamEnvelopeControllerStarted, TypedEventStreamEnvelopeControllerStopped, TypedEventStreamEnvelopeControllerTickCompleted, TypedEventStreamEnvelopeConvoyClosed, TypedEventStreamEnvelopeConvoyCreated, TypedEventStreamEnvelopeCustom, TypedEventStreamEnvelopeDoctorAlert, TypedEventStreamEnvelopeEmergencyAcked, TypedEventStreamEnvelopeEmergencySignaled, TypedEventStreamEnvelopeEventsRotated, TypedEventStreamEnvelopeExecutionStepDefined, TypedEventStreamEnvelopeExecutionWorkAssociated, TypedEventStreamEnvelopeExtmsgAdapterAdded, TypedEventStreamEnvelopeExtmsgAdapterRemoved, TypedEventStreamEnvelopeExtmsgBound, TypedEventStreamEnvelopeExtmsgGroupCreated, TypedEventStreamEnvelopeExtmsgInbound, TypedEventStreamEnvelopeExtmsgOutbound, TypedEventStreamEnvelopeExtmsgOutboundChannelMismatch, TypedEventStreamEnvelopeExtmsgUnbound, TypedEventStreamEnvelopeGcStoreDiskCritical, TypedEventStreamEnvelopeGcStoreDiskWarn, TypedEventStreamEnvelopeGcStoreMaintenanceDone, TypedEventStreamEnvelopeGcStoreMaintenanceFailed, TypedEventStreamEnvelopeMailArchived, TypedEventStreamEnvelopeMailDeleted, TypedEventStreamEnvelopeMailMarkedRead, TypedEventStreamEnvelopeMailMarkedUnread, TypedEventStreamEnvelopeMailRead, TypedEventStreamEnvelopeMailReplied, TypedEventStreamEnvelopeMailSent, TypedEventStreamEnvelopeMoleculeResolved, TypedEventStreamEnvelopeOrderCompleted, TypedEventStreamEnvelopeOrderFailed, TypedEventStreamEnvelopeOrderFired, TypedEventStreamEnvelopeOrderGateTimeoutFailOpen, TypedEventStreamEnvelopePgCredentialResolved, TypedEventStreamEnvelopeProjectIdentityStamped, TypedEventStreamEnvelopeProviderQuotaObserved, TypedEventStreamEnvelopeProviderQuotaPollFailed, TypedEventStreamEnvelopeProviderSwapped, TypedEventStreamEnvelopeProxyReaped, TypedEventStreamEnvelopeRequestFailed, TypedEventStreamEnvelopeRequestResultCityCreate, TypedEventStreamEnvelopeRequestResultCityUnregister, TypedEventStreamEnvelopeRequestResultRigCreate, TypedEventStreamEnvelopeRequestResultSessionCreate, TypedEventStreamEnvelopeRequestResultSessionMessage, TypedEventStreamEnvelopeRequestResultSessionSubmit, TypedEventStreamEnvelopeRigProvisionProgress, TypedEventStreamEnvelopeSessionColdStartTimeout, TypedEventStreamEnvelopeSessionCrashed, TypedEventStreamEnvelopeSessionDrainAckedWithAssignedWork, TypedEventStreamEnvelopeSessionDraining, TypedEventStreamEnvelopeSessionIdleKilled, TypedEventStreamEnvelopeSessionMaxAgeKilled, TypedEventStreamEnvelopeSessionQuarantined, TypedEventStreamEnvelopeSessionResetStalled, TypedEventStreamEnvelopeSessionStopped, TypedEventStreamEnvelopeSessionStranded, TypedEventStreamEnvelopeSessionSuspended, TypedEventStreamEnvelopeSessionUndrained, TypedEventStreamEnvelopeSessionUnknownState, TypedEventStreamEnvelopeSessionUpdated, TypedEventStreamEnvelopeSessionWoke, TypedEventStreamEnvelopeSessionWorkQueryFailed, TypedEventStreamEnvelopeStoreDegraded, TypedEventStreamEnvelopeStoreProbeFailed, TypedEventStreamEnvelopeStoreRecovered, TypedEventStreamEnvelopeSupervisorFsPressureSkippedTick, TypedEventStreamEnvelopeSupervisorRequest, TypedEventStreamEnvelopeSupervisorShutdownRequested, TypedEventStreamEnvelopeSupervisorStarted, TypedEventStreamEnvelopeWebhookReceived, TypedEventStreamEnvelopeWebhookRejected, TypedEventStreamEnvelopeWorkerOperation, TypedTaggedEventStreamEnvelope, TypedTaggedEventStreamEnvelopeBeadClaimRejected, TypedTaggedEventStreamEnvelopeBeadClosed, TypedTaggedEventStreamEnvelopeBeadCreated, TypedTaggedEventStreamEnvelopeBeadDeadAssigneeReopened, TypedTaggedEventStreamEnvelopeBeadDeleted, TypedTaggedEventStreamEnvelopeBeadsConditionalWritesDegraded, TypedTaggedEventStreamEnvelopeBeadUpdated, TypedTaggedEventStreamEnvelopeBeadWorktreeReaped, TypedTaggedEventStreamEnvelopeBeadWorktreeReapSkipped, TypedTaggedEventStreamEnvelopeBreakerStateChanged, TypedTaggedEventStreamEnvelopeCityCreated, TypedTaggedEventStreamEnvelopeCityResumed, TypedTaggedEventStreamEnvelopeCitySuspended, TypedTaggedEventStreamEnvelopeCityUnregisterRequested, TypedTaggedEventStreamEnvelopeControllerStarted, TypedTaggedEventStreamEnvelopeControllerStopped, TypedTaggedEventStreamEnvelopeControllerTickCompleted, TypedTaggedEventStreamEnvelopeConvoyClosed, TypedTaggedEventStreamEnvelopeConvoyCreated, TypedTaggedEventStreamEnvelopeCustom, TypedTaggedEventStreamEnvelopeDoctorAlert, TypedTaggedEventStreamEnvelopeEmergencyAcked, TypedTaggedEventStreamEnvelopeEmergencySignaled, TypedTaggedEventStreamEnvelopeEventsRotated, TypedTaggedEventStreamEnvelopeExecutionStepDefined, TypedTaggedEventStreamEnvelopeExecutionWorkAssociated, TypedTaggedEventStreamEnvelopeExtmsgAdapterAdded, TypedTaggedEventStreamEnvelopeExtmsgAdapterRemoved, TypedTaggedEventStreamEnvelopeExtmsgBound, TypedTaggedEventStreamEnvelopeExtmsgGroupCreated, TypedTaggedEventStreamEnvelopeExtmsgInbound, TypedTaggedEventStreamEnvelopeExtmsgOutbound, TypedTaggedEventStreamEnvelopeExtmsgOutboundChannelMismatch, TypedTaggedEventStreamEnvelopeExtmsgUnbound, TypedTaggedEventStreamEnvelopeGcStoreDiskCritical, TypedTaggedEventStreamEnvelopeGcStoreDiskWarn, TypedTaggedEventStreamEnvelopeGcStoreMaintenanceDone, TypedTaggedEventStreamEnvelopeGcStoreMaintenanceFailed, TypedTaggedEventStreamEnvelopeMailArchived, TypedTaggedEventStreamEnvelopeMailDeleted, TypedTaggedEventStreamEnvelopeMailMarkedRead, TypedTaggedEventStreamEnvelopeMailMarkedUnread, TypedTaggedEventStreamEnvelopeMailRead, TypedTaggedEventStreamEnvelopeMailReplied, TypedTaggedEventStreamEnvelopeMailSent, TypedTaggedEventStreamEnvelopeMoleculeResolved, TypedTaggedEventStreamEnvelopeOrderCompleted, TypedTaggedEventStreamEnvelopeOrderFailed, TypedTaggedEventStreamEnvelopeOrderFired, TypedTaggedEventStreamEnvelopeOrderGateTimeoutFailOpen, TypedTaggedEventStreamEnvelopePgCredentialResolved, TypedTaggedEventStreamEnvelopeProjectIdentityStamped, TypedTaggedEventStreamEnvelopeProviderQuotaObserved, TypedTaggedEventStreamEnvelopeProviderQuotaPollFailed, TypedTaggedEventStreamEnvelopeProviderSwapped, TypedTaggedEventStreamEnvelopeProxyReaped, TypedTaggedEventStreamEnvelopeRequestFailed, TypedTaggedEventStreamEnvelopeRequestResultCityCreate, TypedTaggedEventStreamEnvelopeRequestResultCityUnregister, TypedTaggedEventStreamEnvelopeRequestResultRigCreate, TypedTaggedEventStreamEnvelopeRequestResultSessionCreate, TypedTaggedEventStreamEnvelopeRequestResultSessionMessage, TypedTaggedEventStreamEnvelopeRequestResultSessionSubmit, TypedTaggedEventStreamEnvelopeRigProvisionProgress, TypedTaggedEventStreamEnvelopeSessionColdStartTimeout, TypedTaggedEventStreamEnvelopeSessionCrashed, TypedTaggedEventStreamEnvelopeSessionDrainAckedWithAssignedWork, TypedTaggedEventStreamEnvelopeSessionDraining, TypedTaggedEventStreamEnvelopeSessionIdleKilled, TypedTaggedEventStreamEnvelopeSessionMaxAgeKilled, TypedTaggedEventStreamEnvelopeSessionQuarantined, TypedTaggedEventStreamEnvelopeSessionResetStalled, TypedTaggedEventStreamEnvelopeSessionStopped, TypedTaggedEventStreamEnvelopeSessionStranded, TypedTaggedEventStreamEnvelopeSessionSuspended, TypedTaggedEventStreamEnvelopeSessionUndrained, TypedTaggedEventStreamEnvelopeSessionUnknownState, TypedTaggedEventStreamEnvelopeSessionUpdated, TypedTaggedEventStreamEnvelopeSessionWoke, TypedTaggedEventStreamEnvelopeSessionWorkQueryFailed, TypedTaggedEventStreamEnvelopeStoreDegraded, TypedTaggedEventStreamEnvelopeStoreProbeFailed, TypedTaggedEventStreamEnvelopeStoreRecovered, TypedTaggedEventStreamEnvelopeSupervisorFsPressureSkippedTick, TypedTaggedEventStreamEnvelopeSupervisorRequest, TypedTaggedEventStreamEnvelopeSupervisorShutdownRequested, TypedTaggedEventStreamEnvelopeSupervisorStarted, TypedTaggedEventStreamEnvelopeWebhookReceived, TypedTaggedEventStreamEnvelopeWebhookRejected, TypedTaggedEventStreamEnvelopeWorkerOperation, UnboundEventPayload, UsageBody, UsageSessionRecent, UsageTotals, WaitListBody, WaitView, WebhookReceivedPayload, WebhookRejectedPayload, WorkerOperationEventPayload, WorkflowAttemptSummary, WorkflowBeadResponse, WorkflowDeleteResponse, WorkflowDepResponse, WorkflowEventProjection, WorkflowSnapshotResponse, WorkspaceResponse } from './types.gen.js'; +export type { AdapterCapabilities, AdapterEventPayload, AddPackData, AddPackError, AddPackErrors, AddPackResponse, AddPackResponses, AgentCreatedOutputBody, AgentCreateInputBody, AgentMapping, AgentOutputResponse, AgentPatch, AgentPatchSetInputBody, AgentResponse, AgentUpdateInputBody, AgentUpdateQualifiedInputBody, AnnotatedAgentResponse, AnnotatedProviderResponse, AsyncAcceptedBody, AsyncAcceptedResponse, Bead, BeadAssignInputBody, BeadClaimRejectedPayload, BeadCreateInputBody, BeadDeadAssigneeReopenedPayload, BeadDepsResponse, BeadEventPayload, BeadGraphResponse, BeadsDiagnostic, BeadUpdateBody, BeadWorktreeReapedPayload, BeadWorktreeReapSkippedPayload, BindingStatus, BoundEventPayload, BreakerStateChangedPayload, CityCreateRequest, CityCreateSucceededPayload, CityGetResponse, CityInfo, CityLifecyclePayload, CityPatchInputBody, CityPendingEntry, CityUnregisterSucceededPayload, ClientOptions, ConditionalWritesDegradedPayload, ConfigAgentResponse, ConfigExplainPatches, ConfigExplainResponse, ConfigPatchesResponse, ConfigResponse, ConfigRigResponse, ConfigValidateOutputBody, ControllerTickCompletedPayload, ConversationGroupParticipant, ConversationGroupRecord, ConversationKind, ConversationRef, ConversationTranscriptRecord, ConvoyAddInputBody, ConvoyCheckResponse, ConvoyCreateInputBody, ConvoyGetResponse, ConvoyProgress, ConvoyRemoveInputBody, CreateAgentData, CreateAgentError, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateBeadData, CreateBeadError, CreateBeadErrors, CreateBeadResponse, CreateBeadResponses, CreateConvoyData, CreateConvoyError, CreateConvoyErrors, CreateConvoyResponse, CreateConvoyResponses, CreateProviderData, CreateProviderError, CreateProviderErrors, CreateProviderResponse, CreateProviderResponses, CreateRigData, CreateRigError, CreateRigErrors, CreateRigResponse, CreateRigResponses, CreateSessionData, CreateSessionError, CreateSessionErrors, CreateSessionResponse, CreateSessionResponses, DeleteV0CityByCityNameAgentByBaseData, DeleteV0CityByCityNameAgentByBaseError, DeleteV0CityByCityNameAgentByBaseErrors, DeleteV0CityByCityNameAgentByBaseResponse, DeleteV0CityByCityNameAgentByBaseResponses, DeleteV0CityByCityNameAgentByDirByBaseData, DeleteV0CityByCityNameAgentByDirByBaseError, DeleteV0CityByCityNameAgentByDirByBaseErrors, DeleteV0CityByCityNameAgentByDirByBaseResponse, DeleteV0CityByCityNameAgentByDirByBaseResponses, DeleteV0CityByCityNameBeadByIdData, DeleteV0CityByCityNameBeadByIdError, DeleteV0CityByCityNameBeadByIdErrors, DeleteV0CityByCityNameBeadByIdResponse, DeleteV0CityByCityNameBeadByIdResponses, DeleteV0CityByCityNameConvoyByIdData, DeleteV0CityByCityNameConvoyByIdError, DeleteV0CityByCityNameConvoyByIdErrors, DeleteV0CityByCityNameConvoyByIdResponse, DeleteV0CityByCityNameConvoyByIdResponses, DeleteV0CityByCityNameExtmsgAdaptersData, DeleteV0CityByCityNameExtmsgAdaptersError, DeleteV0CityByCityNameExtmsgAdaptersErrors, DeleteV0CityByCityNameExtmsgAdaptersResponse, DeleteV0CityByCityNameExtmsgAdaptersResponses, DeleteV0CityByCityNameExtmsgParticipantsData, DeleteV0CityByCityNameExtmsgParticipantsError, DeleteV0CityByCityNameExtmsgParticipantsErrors, DeleteV0CityByCityNameExtmsgParticipantsResponse, DeleteV0CityByCityNameExtmsgParticipantsResponses, DeleteV0CityByCityNameFormulasByNameData, DeleteV0CityByCityNameFormulasByNameError, DeleteV0CityByCityNameFormulasByNameErrors, DeleteV0CityByCityNameFormulasByNameResponse, DeleteV0CityByCityNameFormulasByNameResponses, DeleteV0CityByCityNameMailByIdData, DeleteV0CityByCityNameMailByIdError, DeleteV0CityByCityNameMailByIdErrors, DeleteV0CityByCityNameMailByIdResponse, DeleteV0CityByCityNameMailByIdResponses, DeleteV0CityByCityNamePacksByNameData, DeleteV0CityByCityNamePacksByNameError, DeleteV0CityByCityNamePacksByNameErrors, DeleteV0CityByCityNamePacksByNameResponse, DeleteV0CityByCityNamePacksByNameResponses, DeleteV0CityByCityNamePatchesAgentByBaseData, DeleteV0CityByCityNamePatchesAgentByBaseError, DeleteV0CityByCityNamePatchesAgentByBaseErrors, DeleteV0CityByCityNamePatchesAgentByBaseResponse, DeleteV0CityByCityNamePatchesAgentByBaseResponses, DeleteV0CityByCityNamePatchesAgentByDirByBaseData, DeleteV0CityByCityNamePatchesAgentByDirByBaseError, DeleteV0CityByCityNamePatchesAgentByDirByBaseErrors, DeleteV0CityByCityNamePatchesAgentByDirByBaseResponse, DeleteV0CityByCityNamePatchesAgentByDirByBaseResponses, DeleteV0CityByCityNamePatchesProviderByNameData, DeleteV0CityByCityNamePatchesProviderByNameError, DeleteV0CityByCityNamePatchesProviderByNameErrors, DeleteV0CityByCityNamePatchesProviderByNameResponse, DeleteV0CityByCityNamePatchesProviderByNameResponses, DeleteV0CityByCityNamePatchesRigByNameData, DeleteV0CityByCityNamePatchesRigByNameError, DeleteV0CityByCityNamePatchesRigByNameErrors, DeleteV0CityByCityNamePatchesRigByNameResponse, DeleteV0CityByCityNamePatchesRigByNameResponses, DeleteV0CityByCityNameProviderByNameData, DeleteV0CityByCityNameProviderByNameError, DeleteV0CityByCityNameProviderByNameErrors, DeleteV0CityByCityNameProviderByNameResponse, DeleteV0CityByCityNameProviderByNameResponses, DeleteV0CityByCityNameRigByNameData, DeleteV0CityByCityNameRigByNameError, DeleteV0CityByCityNameRigByNameErrors, DeleteV0CityByCityNameRigByNameResponse, DeleteV0CityByCityNameRigByNameResponses, DeleteV0CityByCityNameWorkflowByWorkflowIdData, DeleteV0CityByCityNameWorkflowByWorkflowIdError, DeleteV0CityByCityNameWorkflowByWorkflowIdErrors, DeleteV0CityByCityNameWorkflowByWorkflowIdResponse, DeleteV0CityByCityNameWorkflowByWorkflowIdResponses, DeliveryContextRecord, Dep, DoctorAlertPayload, EmitEventData, EmitEventError, EmitEventErrors, EmitEventResponse, EmitEventResponses, EnsureExtmsgGroupData, EnsureExtmsgGroupError, EnsureExtmsgGroupErrors, EnsureExtmsgGroupResponse, EnsureExtmsgGroupResponses, ErrorDetail, ErrorModel, EventEmitOutputBody, EventEmitRequest, EventPayload, EventRotateAnchor, EventRotateArchive, EventRotateResponse, EventStreamEnvelope, ExternalActor, ExternalAttachment, ExternalInboundMessage, ExtmsgAdapterInfo, ExtMsgAdapterRegisterInputBody, ExtMsgAdapterRegisterOutputBody, ExtMsgAdapterUnregisterInputBody, ExtMsgBindInputBody, ExtMsgGroupEnsureInputBody, ExtMsgInboundInputBody, ExtMsgOutboundInputBody, ExtMsgParticipantRemoveInputBody, ExtMsgParticipantUpsertInputBody, ExtMsgTranscriptAckInputBody, ExtMsgUnbindBody, ExtMsgUnbindInputBody, FanoutPolicy, FormulaDetailResponse, FormulaFeedBody, FormulaListBody, FormulaPreviewBody, FormulaPreviewEdgeResponse, FormulaPreviewNodeResponse, FormulaPreviewResponse, FormulaRecentRunResponse, FormulaRunsResponse, FormulaSourceOutputBody, FormulaStepResponse, FormulaSummaryResponse, FormulaValidateOutputBody, FormulaVarDefResponse, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetV0CitiesData, GetV0CitiesError, GetV0CitiesErrors, GetV0CitiesResponse, GetV0CitiesResponses, GetV0CityByCityNameAgentByBaseData, GetV0CityByCityNameAgentByBaseError, GetV0CityByCityNameAgentByBaseErrors, GetV0CityByCityNameAgentByBaseOutputData, GetV0CityByCityNameAgentByBaseOutputError, GetV0CityByCityNameAgentByBaseOutputErrors, GetV0CityByCityNameAgentByBaseOutputResponse, GetV0CityByCityNameAgentByBaseOutputResponses, GetV0CityByCityNameAgentByBaseResponse, GetV0CityByCityNameAgentByBaseResponses, GetV0CityByCityNameAgentByDirByBaseData, GetV0CityByCityNameAgentByDirByBaseError, GetV0CityByCityNameAgentByDirByBaseErrors, GetV0CityByCityNameAgentByDirByBaseOutputData, GetV0CityByCityNameAgentByDirByBaseOutputError, GetV0CityByCityNameAgentByDirByBaseOutputErrors, GetV0CityByCityNameAgentByDirByBaseOutputResponse, GetV0CityByCityNameAgentByDirByBaseOutputResponses, GetV0CityByCityNameAgentByDirByBaseResponse, GetV0CityByCityNameAgentByDirByBaseResponses, GetV0CityByCityNameAgentsData, GetV0CityByCityNameAgentsError, GetV0CityByCityNameAgentsErrors, GetV0CityByCityNameAgentsResponse, GetV0CityByCityNameAgentsResponses, GetV0CityByCityNameBeadByIdData, GetV0CityByCityNameBeadByIdDepsData, GetV0CityByCityNameBeadByIdDepsError, GetV0CityByCityNameBeadByIdDepsErrors, GetV0CityByCityNameBeadByIdDepsResponse, GetV0CityByCityNameBeadByIdDepsResponses, GetV0CityByCityNameBeadByIdError, GetV0CityByCityNameBeadByIdErrors, GetV0CityByCityNameBeadByIdResponse, GetV0CityByCityNameBeadByIdResponses, GetV0CityByCityNameBeadsData, GetV0CityByCityNameBeadsError, GetV0CityByCityNameBeadsErrors, GetV0CityByCityNameBeadsGraphByRootIdData, GetV0CityByCityNameBeadsGraphByRootIdError, GetV0CityByCityNameBeadsGraphByRootIdErrors, GetV0CityByCityNameBeadsGraphByRootIdResponse, GetV0CityByCityNameBeadsGraphByRootIdResponses, GetV0CityByCityNameBeadsReadyData, GetV0CityByCityNameBeadsReadyError, GetV0CityByCityNameBeadsReadyErrors, GetV0CityByCityNameBeadsReadyResponse, GetV0CityByCityNameBeadsReadyResponses, GetV0CityByCityNameBeadsResponse, GetV0CityByCityNameBeadsResponses, GetV0CityByCityNameConfigData, GetV0CityByCityNameConfigDefaultsData, GetV0CityByCityNameConfigDefaultsError, GetV0CityByCityNameConfigDefaultsErrors, GetV0CityByCityNameConfigDefaultsResponse, GetV0CityByCityNameConfigDefaultsResponses, GetV0CityByCityNameConfigError, GetV0CityByCityNameConfigErrors, GetV0CityByCityNameConfigExplainData, GetV0CityByCityNameConfigExplainError, GetV0CityByCityNameConfigExplainErrors, GetV0CityByCityNameConfigExplainResponse, GetV0CityByCityNameConfigExplainResponses, GetV0CityByCityNameConfigResponse, GetV0CityByCityNameConfigResponses, GetV0CityByCityNameConfigValidateData, GetV0CityByCityNameConfigValidateError, GetV0CityByCityNameConfigValidateErrors, GetV0CityByCityNameConfigValidateResponse, GetV0CityByCityNameConfigValidateResponses, GetV0CityByCityNameConvoyByIdCheckData, GetV0CityByCityNameConvoyByIdCheckError, GetV0CityByCityNameConvoyByIdCheckErrors, GetV0CityByCityNameConvoyByIdCheckResponse, GetV0CityByCityNameConvoyByIdCheckResponses, GetV0CityByCityNameConvoyByIdData, GetV0CityByCityNameConvoyByIdError, GetV0CityByCityNameConvoyByIdErrors, GetV0CityByCityNameConvoyByIdResponse, GetV0CityByCityNameConvoyByIdResponses, GetV0CityByCityNameConvoysData, GetV0CityByCityNameConvoysError, GetV0CityByCityNameConvoysErrors, GetV0CityByCityNameConvoysResponse, GetV0CityByCityNameConvoysResponses, GetV0CityByCityNameData, GetV0CityByCityNameError, GetV0CityByCityNameErrors, GetV0CityByCityNameEventsData, GetV0CityByCityNameEventsError, GetV0CityByCityNameEventsErrors, GetV0CityByCityNameEventsResponse, GetV0CityByCityNameEventsResponses, GetV0CityByCityNameExtmsgAdaptersData, GetV0CityByCityNameExtmsgAdaptersError, GetV0CityByCityNameExtmsgAdaptersErrors, GetV0CityByCityNameExtmsgAdaptersResponse, GetV0CityByCityNameExtmsgAdaptersResponses, GetV0CityByCityNameExtmsgBindingsData, GetV0CityByCityNameExtmsgBindingsError, GetV0CityByCityNameExtmsgBindingsErrors, GetV0CityByCityNameExtmsgBindingsResponse, GetV0CityByCityNameExtmsgBindingsResponses, GetV0CityByCityNameExtmsgGroupsData, GetV0CityByCityNameExtmsgGroupsError, GetV0CityByCityNameExtmsgGroupsErrors, GetV0CityByCityNameExtmsgGroupsResponse, GetV0CityByCityNameExtmsgGroupsResponses, GetV0CityByCityNameExtmsgTranscriptData, GetV0CityByCityNameExtmsgTranscriptError, GetV0CityByCityNameExtmsgTranscriptErrors, GetV0CityByCityNameExtmsgTranscriptResponse, GetV0CityByCityNameExtmsgTranscriptResponses, GetV0CityByCityNameFormulaByNameData, GetV0CityByCityNameFormulaByNameError, GetV0CityByCityNameFormulaByNameErrors, GetV0CityByCityNameFormulaByNameResponse, GetV0CityByCityNameFormulaByNameResponses, GetV0CityByCityNameFormulasByNameData, GetV0CityByCityNameFormulasByNameError, GetV0CityByCityNameFormulasByNameErrors, GetV0CityByCityNameFormulasByNameResponse, GetV0CityByCityNameFormulasByNameResponses, GetV0CityByCityNameFormulasByNameRunsData, GetV0CityByCityNameFormulasByNameRunsError, GetV0CityByCityNameFormulasByNameRunsErrors, GetV0CityByCityNameFormulasByNameRunsResponse, GetV0CityByCityNameFormulasByNameRunsResponses, GetV0CityByCityNameFormulasByNameSourceData, GetV0CityByCityNameFormulasByNameSourceError, GetV0CityByCityNameFormulasByNameSourceErrors, GetV0CityByCityNameFormulasByNameSourceResponse, GetV0CityByCityNameFormulasByNameSourceResponses, GetV0CityByCityNameFormulasData, GetV0CityByCityNameFormulasError, GetV0CityByCityNameFormulasErrors, GetV0CityByCityNameFormulasFeedData, GetV0CityByCityNameFormulasFeedError, GetV0CityByCityNameFormulasFeedErrors, GetV0CityByCityNameFormulasFeedResponse, GetV0CityByCityNameFormulasFeedResponses, GetV0CityByCityNameFormulasResponse, GetV0CityByCityNameFormulasResponses, GetV0CityByCityNameHealthData, GetV0CityByCityNameHealthError, GetV0CityByCityNameHealthErrors, GetV0CityByCityNameHealthResponse, GetV0CityByCityNameHealthResponses, GetV0CityByCityNameMailByIdData, GetV0CityByCityNameMailByIdError, GetV0CityByCityNameMailByIdErrors, GetV0CityByCityNameMailByIdResponse, GetV0CityByCityNameMailByIdResponses, GetV0CityByCityNameMailCountData, GetV0CityByCityNameMailCountError, GetV0CityByCityNameMailCountErrors, GetV0CityByCityNameMailCountResponse, GetV0CityByCityNameMailCountResponses, GetV0CityByCityNameMailData, GetV0CityByCityNameMailError, GetV0CityByCityNameMailErrors, GetV0CityByCityNameMailResponse, GetV0CityByCityNameMailResponses, GetV0CityByCityNameMailThreadByIdData, GetV0CityByCityNameMailThreadByIdError, GetV0CityByCityNameMailThreadByIdErrors, GetV0CityByCityNameMailThreadByIdResponse, GetV0CityByCityNameMailThreadByIdResponses, GetV0CityByCityNameMaintenanceStatusData, GetV0CityByCityNameMaintenanceStatusError, GetV0CityByCityNameMaintenanceStatusErrors, GetV0CityByCityNameMaintenanceStatusResponse, GetV0CityByCityNameMaintenanceStatusResponses, GetV0CityByCityNameOrderByNameData, GetV0CityByCityNameOrderByNameError, GetV0CityByCityNameOrderByNameErrors, GetV0CityByCityNameOrderByNameResponse, GetV0CityByCityNameOrderByNameResponses, GetV0CityByCityNameOrderHistoryByBeadIdData, GetV0CityByCityNameOrderHistoryByBeadIdError, GetV0CityByCityNameOrderHistoryByBeadIdErrors, GetV0CityByCityNameOrderHistoryByBeadIdResponse, GetV0CityByCityNameOrderHistoryByBeadIdResponses, GetV0CityByCityNameOrdersCheckData, GetV0CityByCityNameOrdersCheckError, GetV0CityByCityNameOrdersCheckErrors, GetV0CityByCityNameOrdersCheckResponse, GetV0CityByCityNameOrdersCheckResponses, GetV0CityByCityNameOrdersData, GetV0CityByCityNameOrdersError, GetV0CityByCityNameOrdersErrors, GetV0CityByCityNameOrdersFeedData, GetV0CityByCityNameOrdersFeedError, GetV0CityByCityNameOrdersFeedErrors, GetV0CityByCityNameOrdersFeedResponse, GetV0CityByCityNameOrdersFeedResponses, GetV0CityByCityNameOrdersHistoryData, GetV0CityByCityNameOrdersHistoryError, GetV0CityByCityNameOrdersHistoryErrors, GetV0CityByCityNameOrdersHistoryResponse, GetV0CityByCityNameOrdersHistoryResponses, GetV0CityByCityNameOrdersResponse, GetV0CityByCityNameOrdersResponses, GetV0CityByCityNamePacksData, GetV0CityByCityNamePacksError, GetV0CityByCityNamePacksErrors, GetV0CityByCityNamePacksResponse, GetV0CityByCityNamePacksResponses, GetV0CityByCityNamePatchesAgentByBaseData, GetV0CityByCityNamePatchesAgentByBaseError, GetV0CityByCityNamePatchesAgentByBaseErrors, GetV0CityByCityNamePatchesAgentByBaseResponse, GetV0CityByCityNamePatchesAgentByBaseResponses, GetV0CityByCityNamePatchesAgentByDirByBaseData, GetV0CityByCityNamePatchesAgentByDirByBaseError, GetV0CityByCityNamePatchesAgentByDirByBaseErrors, GetV0CityByCityNamePatchesAgentByDirByBaseResponse, GetV0CityByCityNamePatchesAgentByDirByBaseResponses, GetV0CityByCityNamePatchesAgentsData, GetV0CityByCityNamePatchesAgentsError, GetV0CityByCityNamePatchesAgentsErrors, GetV0CityByCityNamePatchesAgentsResponse, GetV0CityByCityNamePatchesAgentsResponses, GetV0CityByCityNamePatchesProviderByNameData, GetV0CityByCityNamePatchesProviderByNameError, GetV0CityByCityNamePatchesProviderByNameErrors, GetV0CityByCityNamePatchesProviderByNameResponse, GetV0CityByCityNamePatchesProviderByNameResponses, GetV0CityByCityNamePatchesProvidersData, GetV0CityByCityNamePatchesProvidersError, GetV0CityByCityNamePatchesProvidersErrors, GetV0CityByCityNamePatchesProvidersResponse, GetV0CityByCityNamePatchesProvidersResponses, GetV0CityByCityNamePatchesRigByNameData, GetV0CityByCityNamePatchesRigByNameError, GetV0CityByCityNamePatchesRigByNameErrors, GetV0CityByCityNamePatchesRigByNameResponse, GetV0CityByCityNamePatchesRigByNameResponses, GetV0CityByCityNamePatchesRigsData, GetV0CityByCityNamePatchesRigsError, GetV0CityByCityNamePatchesRigsErrors, GetV0CityByCityNamePatchesRigsResponse, GetV0CityByCityNamePatchesRigsResponses, GetV0CityByCityNamePendingData, GetV0CityByCityNamePendingError, GetV0CityByCityNamePendingErrors, GetV0CityByCityNamePendingResponse, GetV0CityByCityNamePendingResponses, GetV0CityByCityNameProviderByNameData, GetV0CityByCityNameProviderByNameError, GetV0CityByCityNameProviderByNameErrors, GetV0CityByCityNameProviderByNameResponse, GetV0CityByCityNameProviderByNameResponses, GetV0CityByCityNameProviderReadinessData, GetV0CityByCityNameProviderReadinessError, GetV0CityByCityNameProviderReadinessErrors, GetV0CityByCityNameProviderReadinessResponse, GetV0CityByCityNameProviderReadinessResponses, GetV0CityByCityNameProvidersData, GetV0CityByCityNameProvidersError, GetV0CityByCityNameProvidersErrors, GetV0CityByCityNameProvidersPublicData, GetV0CityByCityNameProvidersPublicError, GetV0CityByCityNameProvidersPublicErrors, GetV0CityByCityNameProvidersPublicResponse, GetV0CityByCityNameProvidersPublicResponses, GetV0CityByCityNameProvidersResponse, GetV0CityByCityNameProvidersResponses, GetV0CityByCityNameReadinessData, GetV0CityByCityNameReadinessError, GetV0CityByCityNameReadinessErrors, GetV0CityByCityNameReadinessResponse, GetV0CityByCityNameReadinessResponses, GetV0CityByCityNameResponse, GetV0CityByCityNameResponses, GetV0CityByCityNameRigByNameData, GetV0CityByCityNameRigByNameError, GetV0CityByCityNameRigByNameErrors, GetV0CityByCityNameRigByNameResponse, GetV0CityByCityNameRigByNameResponses, GetV0CityByCityNameRigsData, GetV0CityByCityNameRigsError, GetV0CityByCityNameRigsErrors, GetV0CityByCityNameRigsResponse, GetV0CityByCityNameRigsResponses, GetV0CityByCityNameRunsByRunIdData, GetV0CityByCityNameRunsByRunIdError, GetV0CityByCityNameRunsByRunIdErrors, GetV0CityByCityNameRunsByRunIdResponse, GetV0CityByCityNameRunsByRunIdResponses, GetV0CityByCityNameRunsByRunIdStepsData, GetV0CityByCityNameRunsByRunIdStepsError, GetV0CityByCityNameRunsByRunIdStepsErrors, GetV0CityByCityNameRunsByRunIdStepsResponse, GetV0CityByCityNameRunsByRunIdStepsResponses, GetV0CityByCityNameRunsCensusData, GetV0CityByCityNameRunsCensusError, GetV0CityByCityNameRunsCensusErrors, GetV0CityByCityNameRunsCensusResponse, GetV0CityByCityNameRunsCensusResponses, GetV0CityByCityNameRunsData, GetV0CityByCityNameRunsError, GetV0CityByCityNameRunsErrors, GetV0CityByCityNameRunsResponse, GetV0CityByCityNameRunsResponses, GetV0CityByCityNameServiceByNameData, GetV0CityByCityNameServiceByNameError, GetV0CityByCityNameServiceByNameErrors, GetV0CityByCityNameServiceByNameResponse, GetV0CityByCityNameServiceByNameResponses, GetV0CityByCityNameServicesData, GetV0CityByCityNameServicesError, GetV0CityByCityNameServicesErrors, GetV0CityByCityNameServicesResponse, GetV0CityByCityNameServicesResponses, GetV0CityByCityNameSessionByIdAgentsByAgentIdData, GetV0CityByCityNameSessionByIdAgentsByAgentIdError, GetV0CityByCityNameSessionByIdAgentsByAgentIdErrors, GetV0CityByCityNameSessionByIdAgentsByAgentIdResponse, GetV0CityByCityNameSessionByIdAgentsByAgentIdResponses, GetV0CityByCityNameSessionByIdAgentsData, GetV0CityByCityNameSessionByIdAgentsError, GetV0CityByCityNameSessionByIdAgentsErrors, GetV0CityByCityNameSessionByIdAgentsResponse, GetV0CityByCityNameSessionByIdAgentsResponses, GetV0CityByCityNameSessionByIdData, GetV0CityByCityNameSessionByIdError, GetV0CityByCityNameSessionByIdErrors, GetV0CityByCityNameSessionByIdPendingData, GetV0CityByCityNameSessionByIdPendingError, GetV0CityByCityNameSessionByIdPendingErrors, GetV0CityByCityNameSessionByIdPendingResponse, GetV0CityByCityNameSessionByIdPendingResponses, GetV0CityByCityNameSessionByIdResponse, GetV0CityByCityNameSessionByIdResponses, GetV0CityByCityNameSessionByIdTranscriptData, GetV0CityByCityNameSessionByIdTranscriptError, GetV0CityByCityNameSessionByIdTranscriptErrors, GetV0CityByCityNameSessionByIdTranscriptResponse, GetV0CityByCityNameSessionByIdTranscriptResponses, GetV0CityByCityNameSessionsData, GetV0CityByCityNameSessionsError, GetV0CityByCityNameSessionsErrors, GetV0CityByCityNameSessionsResponse, GetV0CityByCityNameSessionsResponses, GetV0CityByCityNameStatusData, GetV0CityByCityNameStatusError, GetV0CityByCityNameStatusErrors, GetV0CityByCityNameStatusResponse, GetV0CityByCityNameStatusResponses, GetV0CityByCityNameUsageData, GetV0CityByCityNameUsageError, GetV0CityByCityNameUsageErrors, GetV0CityByCityNameUsageResponse, GetV0CityByCityNameUsageResponses, GetV0CityByCityNameWaitByIdData, GetV0CityByCityNameWaitByIdError, GetV0CityByCityNameWaitByIdErrors, GetV0CityByCityNameWaitByIdResponse, GetV0CityByCityNameWaitByIdResponses, GetV0CityByCityNameWaitsData, GetV0CityByCityNameWaitsError, GetV0CityByCityNameWaitsErrors, GetV0CityByCityNameWaitsResponse, GetV0CityByCityNameWaitsResponses, GetV0CityByCityNameWorkflowByWorkflowIdData, GetV0CityByCityNameWorkflowByWorkflowIdError, GetV0CityByCityNameWorkflowByWorkflowIdErrors, GetV0CityByCityNameWorkflowByWorkflowIdResponse, GetV0CityByCityNameWorkflowByWorkflowIdResponses, GetV0EventsData, GetV0EventsError, GetV0EventsErrors, GetV0EventsResponse, GetV0EventsResponses, GetV0ProviderReadinessData, GetV0ProviderReadinessError, GetV0ProviderReadinessErrors, GetV0ProviderReadinessResponse, GetV0ProviderReadinessResponses, GetV0ReadinessData, GetV0ReadinessError, GetV0ReadinessErrors, GetV0ReadinessResponse, GetV0ReadinessResponses, GitStatus, GroupCreatedEventPayload, GroupRouteDecision, HealthOutputBody, HeartbeatEvent, InboundEventPayload, InboundResult, ListBodyAgentPatch, ListBodyAgentResponse, ListBodyBead, ListBodyCityPendingEntry, ListBodyConversationTranscriptRecord, ListBodyExtmsgAdapterInfo, ListBodyProviderPatch, ListBodyProviderResponse, ListBodyRigPatch, ListBodyRigResponse, ListBodySessionBindingRecord, ListBodySessionResponse, ListBodyStatus, ListBodyWireEvent, LogicalNode, MailCountOutputBody, MailEventPayload, MailListBody, MailReplyInputBody, MailSendInputBody, MaintenanceRunBody, MaintenanceStatusBody, MaintenanceTriggerBody, Message, MoleculeResolvedPayload, MonitorFeedItemResponse, NoPayload, OkResponseBody, OkWithIdResponseBody, OptionChoiceDto, OrderCheckListBody, OrderCheckResponse, OrderGateTimeoutFailOpenPayload, OrderHistoryDetailResponse, OrderHistoryEntry, OrderHistoryListBody, OrderListBody, OrderResponse, OrderRunInputBody, OrderRunOutputBody, OrdersFeedBody, OutboundChannelMismatchPayload, OutboundEventPayload, OutboundResult, OutputTurn, PackAddedOutputBody, PackAddInputBody, PackListBody, PackRemovedOutputBody, PackResponse, PaginationInfo, PatchDeletedResponseBody, PatchOkResponseBody, PatchV0CityByCityNameAgentByBaseData, PatchV0CityByCityNameAgentByBaseError, PatchV0CityByCityNameAgentByBaseErrors, PatchV0CityByCityNameAgentByBaseResponse, PatchV0CityByCityNameAgentByBaseResponses, PatchV0CityByCityNameAgentByDirByBaseData, PatchV0CityByCityNameAgentByDirByBaseError, PatchV0CityByCityNameAgentByDirByBaseErrors, PatchV0CityByCityNameAgentByDirByBaseResponse, PatchV0CityByCityNameAgentByDirByBaseResponses, PatchV0CityByCityNameBeadByIdData, PatchV0CityByCityNameBeadByIdError, PatchV0CityByCityNameBeadByIdErrors, PatchV0CityByCityNameBeadByIdResponse, PatchV0CityByCityNameBeadByIdResponses, PatchV0CityByCityNameData, PatchV0CityByCityNameError, PatchV0CityByCityNameErrors, PatchV0CityByCityNameProviderByNameData, PatchV0CityByCityNameProviderByNameError, PatchV0CityByCityNameProviderByNameErrors, PatchV0CityByCityNameProviderByNameResponse, PatchV0CityByCityNameProviderByNameResponses, PatchV0CityByCityNameResponse, PatchV0CityByCityNameResponses, PatchV0CityByCityNameRigByNameData, PatchV0CityByCityNameRigByNameError, PatchV0CityByCityNameRigByNameErrors, PatchV0CityByCityNameRigByNameResponse, PatchV0CityByCityNameRigByNameResponses, PatchV0CityByCityNameSessionByIdData, PatchV0CityByCityNameSessionByIdError, PatchV0CityByCityNameSessionByIdErrors, PatchV0CityByCityNameSessionByIdResponse, PatchV0CityByCityNameSessionByIdResponses, PendingInteraction, PoolOverride, PostgresCredentialResolvedPayload, PostV0CityByCityNameAgentByBaseByActionData, PostV0CityByCityNameAgentByBaseByActionError, PostV0CityByCityNameAgentByBaseByActionErrors, PostV0CityByCityNameAgentByBaseByActionResponse, PostV0CityByCityNameAgentByBaseByActionResponses, PostV0CityByCityNameAgentByDirByBaseByActionData, PostV0CityByCityNameAgentByDirByBaseByActionError, PostV0CityByCityNameAgentByDirByBaseByActionErrors, PostV0CityByCityNameAgentByDirByBaseByActionResponse, PostV0CityByCityNameAgentByDirByBaseByActionResponses, PostV0CityByCityNameBeadByIdAssignData, PostV0CityByCityNameBeadByIdAssignError, PostV0CityByCityNameBeadByIdAssignErrors, PostV0CityByCityNameBeadByIdAssignResponse, PostV0CityByCityNameBeadByIdAssignResponses, PostV0CityByCityNameBeadByIdCloseData, PostV0CityByCityNameBeadByIdCloseError, PostV0CityByCityNameBeadByIdCloseErrors, PostV0CityByCityNameBeadByIdCloseResponse, PostV0CityByCityNameBeadByIdCloseResponses, PostV0CityByCityNameBeadByIdReopenData, PostV0CityByCityNameBeadByIdReopenError, PostV0CityByCityNameBeadByIdReopenErrors, PostV0CityByCityNameBeadByIdReopenResponse, PostV0CityByCityNameBeadByIdReopenResponses, PostV0CityByCityNameBeadByIdUpdateData, PostV0CityByCityNameBeadByIdUpdateError, PostV0CityByCityNameBeadByIdUpdateErrors, PostV0CityByCityNameBeadByIdUpdateResponse, PostV0CityByCityNameBeadByIdUpdateResponses, PostV0CityByCityNameConvoyByIdAddData, PostV0CityByCityNameConvoyByIdAddError, PostV0CityByCityNameConvoyByIdAddErrors, PostV0CityByCityNameConvoyByIdAddResponse, PostV0CityByCityNameConvoyByIdAddResponses, PostV0CityByCityNameConvoyByIdCloseData, PostV0CityByCityNameConvoyByIdCloseError, PostV0CityByCityNameConvoyByIdCloseErrors, PostV0CityByCityNameConvoyByIdCloseResponse, PostV0CityByCityNameConvoyByIdCloseResponses, PostV0CityByCityNameConvoyByIdRemoveData, PostV0CityByCityNameConvoyByIdRemoveError, PostV0CityByCityNameConvoyByIdRemoveErrors, PostV0CityByCityNameConvoyByIdRemoveResponse, PostV0CityByCityNameConvoyByIdRemoveResponses, PostV0CityByCityNameExtmsgBindData, PostV0CityByCityNameExtmsgBindError, PostV0CityByCityNameExtmsgBindErrors, PostV0CityByCityNameExtmsgBindResponse, PostV0CityByCityNameExtmsgBindResponses, PostV0CityByCityNameExtmsgInboundData, PostV0CityByCityNameExtmsgInboundError, PostV0CityByCityNameExtmsgInboundErrors, PostV0CityByCityNameExtmsgInboundResponse, PostV0CityByCityNameExtmsgInboundResponses, PostV0CityByCityNameExtmsgOutboundData, PostV0CityByCityNameExtmsgOutboundError, PostV0CityByCityNameExtmsgOutboundErrors, PostV0CityByCityNameExtmsgOutboundResponse, PostV0CityByCityNameExtmsgOutboundResponses, PostV0CityByCityNameExtmsgParticipantsData, PostV0CityByCityNameExtmsgParticipantsError, PostV0CityByCityNameExtmsgParticipantsErrors, PostV0CityByCityNameExtmsgParticipantsResponse, PostV0CityByCityNameExtmsgParticipantsResponses, PostV0CityByCityNameExtmsgTranscriptAckData, PostV0CityByCityNameExtmsgTranscriptAckError, PostV0CityByCityNameExtmsgTranscriptAckErrors, PostV0CityByCityNameExtmsgTranscriptAckResponse, PostV0CityByCityNameExtmsgTranscriptAckResponses, PostV0CityByCityNameExtmsgUnbindData, PostV0CityByCityNameExtmsgUnbindError, PostV0CityByCityNameExtmsgUnbindErrors, PostV0CityByCityNameExtmsgUnbindResponse, PostV0CityByCityNameExtmsgUnbindResponses, PostV0CityByCityNameFormulasByNamePreviewData, PostV0CityByCityNameFormulasByNamePreviewError, PostV0CityByCityNameFormulasByNamePreviewErrors, PostV0CityByCityNameFormulasByNamePreviewResponse, PostV0CityByCityNameFormulasByNamePreviewResponses, PostV0CityByCityNameFormulasByNameValidateData, PostV0CityByCityNameFormulasByNameValidateError, PostV0CityByCityNameFormulasByNameValidateErrors, PostV0CityByCityNameFormulasByNameValidateResponse, PostV0CityByCityNameFormulasByNameValidateResponses, PostV0CityByCityNameMailByIdArchiveData, PostV0CityByCityNameMailByIdArchiveError, PostV0CityByCityNameMailByIdArchiveErrors, PostV0CityByCityNameMailByIdArchiveResponse, PostV0CityByCityNameMailByIdArchiveResponses, PostV0CityByCityNameMailByIdMarkUnreadData, PostV0CityByCityNameMailByIdMarkUnreadError, PostV0CityByCityNameMailByIdMarkUnreadErrors, PostV0CityByCityNameMailByIdMarkUnreadResponse, PostV0CityByCityNameMailByIdMarkUnreadResponses, PostV0CityByCityNameMailByIdReadData, PostV0CityByCityNameMailByIdReadError, PostV0CityByCityNameMailByIdReadErrors, PostV0CityByCityNameMailByIdReadResponse, PostV0CityByCityNameMailByIdReadResponses, PostV0CityByCityNameOrderByNameDisableData, PostV0CityByCityNameOrderByNameDisableError, PostV0CityByCityNameOrderByNameDisableErrors, PostV0CityByCityNameOrderByNameDisableResponse, PostV0CityByCityNameOrderByNameDisableResponses, PostV0CityByCityNameOrderByNameEnableData, PostV0CityByCityNameOrderByNameEnableError, PostV0CityByCityNameOrderByNameEnableErrors, PostV0CityByCityNameOrderByNameEnableResponse, PostV0CityByCityNameOrderByNameEnableResponses, PostV0CityByCityNameOrderByNameRunData, PostV0CityByCityNameOrderByNameRunError, PostV0CityByCityNameOrderByNameRunErrors, PostV0CityByCityNameOrderByNameRunResponse, PostV0CityByCityNameOrderByNameRunResponses, PostV0CityByCityNameRigByNameByActionData, PostV0CityByCityNameRigByNameByActionError, PostV0CityByCityNameRigByNameByActionErrors, PostV0CityByCityNameRigByNameByActionResponse, PostV0CityByCityNameRigByNameByActionResponses, PostV0CityByCityNameRunsByRunIdCancelData, PostV0CityByCityNameRunsByRunIdCancelError, PostV0CityByCityNameRunsByRunIdCancelErrors, PostV0CityByCityNameRunsByRunIdCancelResponse, PostV0CityByCityNameRunsByRunIdCancelResponses, PostV0CityByCityNameServiceByNameRestartData, PostV0CityByCityNameServiceByNameRestartError, PostV0CityByCityNameServiceByNameRestartErrors, PostV0CityByCityNameServiceByNameRestartResponse, PostV0CityByCityNameServiceByNameRestartResponses, PostV0CityByCityNameSessionByIdCloseData, PostV0CityByCityNameSessionByIdCloseError, PostV0CityByCityNameSessionByIdCloseErrors, PostV0CityByCityNameSessionByIdCloseResponse, PostV0CityByCityNameSessionByIdCloseResponses, PostV0CityByCityNameSessionByIdKillData, PostV0CityByCityNameSessionByIdKillError, PostV0CityByCityNameSessionByIdKillErrors, PostV0CityByCityNameSessionByIdKillResponse, PostV0CityByCityNameSessionByIdKillResponses, PostV0CityByCityNameSessionByIdPermissionModeData, PostV0CityByCityNameSessionByIdPermissionModeError, PostV0CityByCityNameSessionByIdPermissionModeErrors, PostV0CityByCityNameSessionByIdPermissionModeResponse, PostV0CityByCityNameSessionByIdPermissionModeResponses, PostV0CityByCityNameSessionByIdRenameData, PostV0CityByCityNameSessionByIdRenameError, PostV0CityByCityNameSessionByIdRenameErrors, PostV0CityByCityNameSessionByIdRenameResponse, PostV0CityByCityNameSessionByIdRenameResponses, PostV0CityByCityNameSessionByIdStopData, PostV0CityByCityNameSessionByIdStopError, PostV0CityByCityNameSessionByIdStopErrors, PostV0CityByCityNameSessionByIdStopResponse, PostV0CityByCityNameSessionByIdStopResponses, PostV0CityByCityNameSessionByIdSuspendData, PostV0CityByCityNameSessionByIdSuspendError, PostV0CityByCityNameSessionByIdSuspendErrors, PostV0CityByCityNameSessionByIdSuspendResponse, PostV0CityByCityNameSessionByIdSuspendResponses, PostV0CityByCityNameSessionByIdWakeData, PostV0CityByCityNameSessionByIdWakeError, PostV0CityByCityNameSessionByIdWakeErrors, PostV0CityByCityNameSessionByIdWakeResponse, PostV0CityByCityNameSessionByIdWakeResponses, PostV0CityByCityNameSlingData, PostV0CityByCityNameSlingError, PostV0CityByCityNameSlingErrors, PostV0CityByCityNameSlingResponse, PostV0CityByCityNameSlingResponses, PostV0CityByCityNameUnregisterData, PostV0CityByCityNameUnregisterError, PostV0CityByCityNameUnregisterErrors, PostV0CityByCityNameUnregisterResponse, PostV0CityByCityNameUnregisterResponses, PostV0CityData, PostV0CityError, PostV0CityErrors, PostV0CityResponse, PostV0CityResponses, ProjectIdentityStampedPayload, ProviderCreatedOutputBody, ProviderCreateInputBody, ProviderOptionDto, ProviderPatch, ProviderPatchSetInputBody, ProviderPublicListBody, ProviderPublicResponse, ProviderReadiness, ProviderReadinessResponse, ProviderResponse, ProviderSpecJson, ProviderUpdateInputBody, ProxyReapedPayload, PublishReceipt, PutV0CityByCityNameFormulasByNameData, PutV0CityByCityNameFormulasByNameError, PutV0CityByCityNameFormulasByNameErrors, PutV0CityByCityNameFormulasByNameResponse, PutV0CityByCityNameFormulasByNameResponses, PutV0CityByCityNamePatchesAgentsData, PutV0CityByCityNamePatchesAgentsError, PutV0CityByCityNamePatchesAgentsErrors, PutV0CityByCityNamePatchesAgentsResponse, PutV0CityByCityNamePatchesAgentsResponses, PutV0CityByCityNamePatchesProvidersData, PutV0CityByCityNamePatchesProvidersError, PutV0CityByCityNamePatchesProvidersErrors, PutV0CityByCityNamePatchesProvidersResponse, PutV0CityByCityNamePatchesProvidersResponses, PutV0CityByCityNamePatchesRigsData, PutV0CityByCityNamePatchesRigsError, PutV0CityByCityNamePatchesRigsErrors, PutV0CityByCityNamePatchesRigsResponse, PutV0CityByCityNamePatchesRigsResponses, QuotaObservedPayload, QuotaPollFailedPayload, ReadinessItem, ReadinessResponse, Record, RegisterExtmsgAdapterData, RegisterExtmsgAdapterError, RegisterExtmsgAdapterErrors, RegisterExtmsgAdapterResponse, RegisterExtmsgAdapterResponses, ReplyMailData, ReplyMailError, ReplyMailErrors, ReplyMailResponse, ReplyMailResponses, RequestFailedPayload, RespondSessionData, RespondSessionError, RespondSessionErrors, RespondSessionResponse, RespondSessionResponses, RigActionBody, RigCreateBody, RigCreateResponseBody, RigCreateSucceededPayload, RigPatch, RigPatchSetInputBody, RigProvisionProgressPayload, RigResponse, RigUpdateInputBody, RotatedPayload, RotateEventsData, RotateEventsError, RotateEventsErrors, RotateEventsResponse, RotateEventsResponses, Run, RunCancelOutputBody, RunLastError, RunRef, RunsCensusOutputBody, RunScope, RunsListOutputBody, RunStatus, RunStatusCounts, RunStep, RunStepsOutputBody, RunStepStatus, ScopeGroup, SendMailData, SendMailError, SendMailErrors, SendMailResponse, SendMailResponses, SendSessionMessageData, SendSessionMessageError, SendSessionMessageErrors, SendSessionMessageResponse, SendSessionMessageResponses, ServiceRestartOutputBody, SessionActivityEvent, SessionAgentGetResponse, SessionAgentListResponse, SessionBindingRecord, SessionCreateBody, SessionCreateSucceededPayload, SessionDrainAckedWithAssignedWorkPayload, SessionInfo, SessionLifecyclePayload, SessionMessageInputBody, SessionMessageSucceededPayload, SessionPatchBody, SessionPendingClearedEvent, SessionPendingResponse, SessionPermissionModeBody, SessionRawMessageFrame, SessionRenameInputBody, SessionResetStalledPayload, SessionRespondInputBody, SessionRespondOutputBody, SessionResponse, SessionStrandedPayload, SessionStreamCommonEvent, SessionStreamMessageEvent, SessionStreamRawMessageEvent, SessionStreamStructuredMessageEvent, SessionStructuredArgument, SessionStructuredBlock, SessionStructuredBlockImage, SessionStructuredBlockInteraction, SessionStructuredBlockText, SessionStructuredBlockThinking, SessionStructuredBlockToolResult, SessionStructuredBlockToolUse, SessionStructuredBlockUnknown, SessionStructuredContinuity, SessionStructuredCursor, SessionStructuredDiagnostic, SessionStructuredGeneration, SessionStructuredHistory, SessionStructuredIdeSelection, SessionStructuredInteraction, SessionStructuredMessage, SessionStructuredMessageAssistant, SessionStructuredMessageSystem, SessionStructuredMessageTool, SessionStructuredMessageUnknown, SessionStructuredMessageUser, SessionStructuredPatchHunk, SessionStructuredPlanStep, SessionStructuredQuestion, SessionStructuredQuestionOption, SessionStructuredSearchResultItem, SessionStructuredSystemEvent, SessionStructuredTailState, SessionStructuredTodoItem, SessionStructuredToolError, SessionStructuredToolInput, SessionStructuredToolInputArguments, SessionStructuredToolInputCode, SessionStructuredToolInputCommand, SessionStructuredToolInputFetch, SessionStructuredToolInputFile, SessionStructuredToolInputGlob, SessionStructuredToolInputPatch, SessionStructuredToolInputPlan, SessionStructuredToolInputQuestion, SessionStructuredToolInputSearch, SessionStructuredToolInputStdin, SessionStructuredToolInputTask, SessionStructuredToolInputText, SessionStructuredToolInputTodo, SessionStructuredToolInputUnknown, SessionStructuredToolInputWrite, SessionStructuredToolResult, SessionStructuredToolResultBash, SessionStructuredToolResultEdit, SessionStructuredToolResultFetch, SessionStructuredToolResultGlob, SessionStructuredToolResultGrep, SessionStructuredToolResultPlan, SessionStructuredToolResultPython, SessionStructuredToolResultQuestion, SessionStructuredToolResultRead, SessionStructuredToolResultSearch, SessionStructuredToolResultStdin, SessionStructuredToolResultTask, SessionStructuredToolResultText, SessionStructuredToolResultTodo, SessionStructuredToolResultUnknown, SessionStructuredToolResultWrite, SessionStructuredUploadedFile, SessionStructuredUsage, SessionStructuredUserPrompt, SessionSubmitInputBody, SessionSubmitSucceededPayload, SessionTranscriptConversationResponse, SessionTranscriptGetResponse, SessionTranscriptRawResponse, SessionTranscriptStructuredResponse, SessionUnknownStatePayload, SlingInputBody, SlingResponse, Status, StatusAgentCounts, StatusAgentDetail, StatusBody, StatusConditionalWrites, StatusConditionalWriteStoreVerdict, StatusMailCounts, StatusNamedSessionDetail, StatusRigCounts, StatusRigDetail, StatusRolloutNotice, StatusSessionCountsDetail, StatusStoreHealth, StatusWorkCounts, StoreDegradedPayload, StoreDiskCriticalPayload, StoreDiskWarnPayload, StoreMaintenanceDonePayload, StoreMaintenanceFailedPayload, StoreProbeFailedPayload, StoreRecoveredPayload, StreamAgentOutputData, StreamAgentOutputError, StreamAgentOutputErrors, StreamAgentOutputQualifiedData, StreamAgentOutputQualifiedError, StreamAgentOutputQualifiedErrors, StreamAgentOutputQualifiedResponse, StreamAgentOutputQualifiedResponses, StreamAgentOutputResponse, StreamAgentOutputResponses, StreamEventsData, StreamEventsError, StreamEventsErrors, StreamEventsResponse, StreamEventsResponses, StreamSessionData, StreamSessionError, StreamSessionErrors, StreamSessionResponse, StreamSessionResponses, StreamSupervisorEventsData, StreamSupervisorEventsError, StreamSupervisorEventsErrors, StreamSupervisorEventsResponse, StreamSupervisorEventsResponses, SubmissionCapabilities, SubmitIntent, SubmitSessionData, SubmitSessionError, SubmitSessionErrors, SubmitSessionResponse, SubmitSessionResponses, SupervisorCitiesOutputBody, SupervisorEventListOutputBody, SupervisorFsPressureSkippedTickPayload, SupervisorHealthOutputBody, SupervisorRequestPayload, SupervisorShutdownPayload, SupervisorStartedPayload, SupervisorStartup, TaggedEventStreamEnvelope, TranscriptMessageKind, TranscriptProvenance, TriggerMaintenanceDoltGcData, TriggerMaintenanceDoltGcError, TriggerMaintenanceDoltGcErrors, TriggerMaintenanceDoltGcResponse, TriggerMaintenanceDoltGcResponses, TypedEventStreamEnvelope, TypedEventStreamEnvelopeBeadClaimRejected, TypedEventStreamEnvelopeBeadClosed, TypedEventStreamEnvelopeBeadCreated, TypedEventStreamEnvelopeBeadDeadAssigneeReopened, TypedEventStreamEnvelopeBeadDeleted, TypedEventStreamEnvelopeBeadsConditionalWritesDegraded, TypedEventStreamEnvelopeBeadUpdated, TypedEventStreamEnvelopeBeadWorktreeReaped, TypedEventStreamEnvelopeBeadWorktreeReapSkipped, TypedEventStreamEnvelopeBreakerStateChanged, TypedEventStreamEnvelopeCityCreated, TypedEventStreamEnvelopeCityResumed, TypedEventStreamEnvelopeCitySuspended, TypedEventStreamEnvelopeCityUnregisterRequested, TypedEventStreamEnvelopeControllerStarted, TypedEventStreamEnvelopeControllerStopped, TypedEventStreamEnvelopeControllerTickCompleted, TypedEventStreamEnvelopeConvoyClosed, TypedEventStreamEnvelopeConvoyCreated, TypedEventStreamEnvelopeCustom, TypedEventStreamEnvelopeDoctorAlert, TypedEventStreamEnvelopeEmergencyAcked, TypedEventStreamEnvelopeEmergencySignaled, TypedEventStreamEnvelopeEventsRotated, TypedEventStreamEnvelopeExecutionStepCompleted, TypedEventStreamEnvelopeExecutionStepDefined, TypedEventStreamEnvelopeExecutionStepStarted, TypedEventStreamEnvelopeExecutionWorkAssociated, TypedEventStreamEnvelopeExtmsgAdapterAdded, TypedEventStreamEnvelopeExtmsgAdapterRemoved, TypedEventStreamEnvelopeExtmsgBound, TypedEventStreamEnvelopeExtmsgGroupCreated, TypedEventStreamEnvelopeExtmsgInbound, TypedEventStreamEnvelopeExtmsgOutbound, TypedEventStreamEnvelopeExtmsgOutboundChannelMismatch, TypedEventStreamEnvelopeExtmsgUnbound, TypedEventStreamEnvelopeGcStoreDiskCritical, TypedEventStreamEnvelopeGcStoreDiskWarn, TypedEventStreamEnvelopeGcStoreMaintenanceDone, TypedEventStreamEnvelopeGcStoreMaintenanceFailed, TypedEventStreamEnvelopeMailArchived, TypedEventStreamEnvelopeMailDeleted, TypedEventStreamEnvelopeMailMarkedRead, TypedEventStreamEnvelopeMailMarkedUnread, TypedEventStreamEnvelopeMailRead, TypedEventStreamEnvelopeMailReplied, TypedEventStreamEnvelopeMailSent, TypedEventStreamEnvelopeMoleculeResolved, TypedEventStreamEnvelopeOrderCompleted, TypedEventStreamEnvelopeOrderFailed, TypedEventStreamEnvelopeOrderFired, TypedEventStreamEnvelopeOrderGateTimeoutFailOpen, TypedEventStreamEnvelopePgCredentialResolved, TypedEventStreamEnvelopeProjectIdentityStamped, TypedEventStreamEnvelopeProviderQuotaObserved, TypedEventStreamEnvelopeProviderQuotaPollFailed, TypedEventStreamEnvelopeProviderSwapped, TypedEventStreamEnvelopeProxyReaped, TypedEventStreamEnvelopeRequestFailed, TypedEventStreamEnvelopeRequestResultCityCreate, TypedEventStreamEnvelopeRequestResultCityUnregister, TypedEventStreamEnvelopeRequestResultRigCreate, TypedEventStreamEnvelopeRequestResultSessionCreate, TypedEventStreamEnvelopeRequestResultSessionMessage, TypedEventStreamEnvelopeRequestResultSessionSubmit, TypedEventStreamEnvelopeRigProvisionProgress, TypedEventStreamEnvelopeSessionColdStartTimeout, TypedEventStreamEnvelopeSessionCrashed, TypedEventStreamEnvelopeSessionDrainAckedWithAssignedWork, TypedEventStreamEnvelopeSessionDraining, TypedEventStreamEnvelopeSessionIdleKilled, TypedEventStreamEnvelopeSessionMaxAgeKilled, TypedEventStreamEnvelopeSessionQuarantined, TypedEventStreamEnvelopeSessionResetStalled, TypedEventStreamEnvelopeSessionStopped, TypedEventStreamEnvelopeSessionStranded, TypedEventStreamEnvelopeSessionSuspended, TypedEventStreamEnvelopeSessionUndrained, TypedEventStreamEnvelopeSessionUnknownState, TypedEventStreamEnvelopeSessionUpdated, TypedEventStreamEnvelopeSessionWoke, TypedEventStreamEnvelopeSessionWorkQueryFailed, TypedEventStreamEnvelopeStoreDegraded, TypedEventStreamEnvelopeStoreProbeFailed, TypedEventStreamEnvelopeStoreRecovered, TypedEventStreamEnvelopeSupervisorFsPressureSkippedTick, TypedEventStreamEnvelopeSupervisorRequest, TypedEventStreamEnvelopeSupervisorShutdownRequested, TypedEventStreamEnvelopeSupervisorStarted, TypedEventStreamEnvelopeWebhookReceived, TypedEventStreamEnvelopeWebhookRejected, TypedEventStreamEnvelopeWorkerOperation, TypedTaggedEventStreamEnvelope, TypedTaggedEventStreamEnvelopeBeadClaimRejected, TypedTaggedEventStreamEnvelopeBeadClosed, TypedTaggedEventStreamEnvelopeBeadCreated, TypedTaggedEventStreamEnvelopeBeadDeadAssigneeReopened, TypedTaggedEventStreamEnvelopeBeadDeleted, TypedTaggedEventStreamEnvelopeBeadsConditionalWritesDegraded, TypedTaggedEventStreamEnvelopeBeadUpdated, TypedTaggedEventStreamEnvelopeBeadWorktreeReaped, TypedTaggedEventStreamEnvelopeBeadWorktreeReapSkipped, TypedTaggedEventStreamEnvelopeBreakerStateChanged, TypedTaggedEventStreamEnvelopeCityCreated, TypedTaggedEventStreamEnvelopeCityResumed, TypedTaggedEventStreamEnvelopeCitySuspended, TypedTaggedEventStreamEnvelopeCityUnregisterRequested, TypedTaggedEventStreamEnvelopeControllerStarted, TypedTaggedEventStreamEnvelopeControllerStopped, TypedTaggedEventStreamEnvelopeControllerTickCompleted, TypedTaggedEventStreamEnvelopeConvoyClosed, TypedTaggedEventStreamEnvelopeConvoyCreated, TypedTaggedEventStreamEnvelopeCustom, TypedTaggedEventStreamEnvelopeDoctorAlert, TypedTaggedEventStreamEnvelopeEmergencyAcked, TypedTaggedEventStreamEnvelopeEmergencySignaled, TypedTaggedEventStreamEnvelopeEventsRotated, TypedTaggedEventStreamEnvelopeExecutionStepCompleted, TypedTaggedEventStreamEnvelopeExecutionStepDefined, TypedTaggedEventStreamEnvelopeExecutionStepStarted, TypedTaggedEventStreamEnvelopeExecutionWorkAssociated, TypedTaggedEventStreamEnvelopeExtmsgAdapterAdded, TypedTaggedEventStreamEnvelopeExtmsgAdapterRemoved, TypedTaggedEventStreamEnvelopeExtmsgBound, TypedTaggedEventStreamEnvelopeExtmsgGroupCreated, TypedTaggedEventStreamEnvelopeExtmsgInbound, TypedTaggedEventStreamEnvelopeExtmsgOutbound, TypedTaggedEventStreamEnvelopeExtmsgOutboundChannelMismatch, TypedTaggedEventStreamEnvelopeExtmsgUnbound, TypedTaggedEventStreamEnvelopeGcStoreDiskCritical, TypedTaggedEventStreamEnvelopeGcStoreDiskWarn, TypedTaggedEventStreamEnvelopeGcStoreMaintenanceDone, TypedTaggedEventStreamEnvelopeGcStoreMaintenanceFailed, TypedTaggedEventStreamEnvelopeMailArchived, TypedTaggedEventStreamEnvelopeMailDeleted, TypedTaggedEventStreamEnvelopeMailMarkedRead, TypedTaggedEventStreamEnvelopeMailMarkedUnread, TypedTaggedEventStreamEnvelopeMailRead, TypedTaggedEventStreamEnvelopeMailReplied, TypedTaggedEventStreamEnvelopeMailSent, TypedTaggedEventStreamEnvelopeMoleculeResolved, TypedTaggedEventStreamEnvelopeOrderCompleted, TypedTaggedEventStreamEnvelopeOrderFailed, TypedTaggedEventStreamEnvelopeOrderFired, TypedTaggedEventStreamEnvelopeOrderGateTimeoutFailOpen, TypedTaggedEventStreamEnvelopePgCredentialResolved, TypedTaggedEventStreamEnvelopeProjectIdentityStamped, TypedTaggedEventStreamEnvelopeProviderQuotaObserved, TypedTaggedEventStreamEnvelopeProviderQuotaPollFailed, TypedTaggedEventStreamEnvelopeProviderSwapped, TypedTaggedEventStreamEnvelopeProxyReaped, TypedTaggedEventStreamEnvelopeRequestFailed, TypedTaggedEventStreamEnvelopeRequestResultCityCreate, TypedTaggedEventStreamEnvelopeRequestResultCityUnregister, TypedTaggedEventStreamEnvelopeRequestResultRigCreate, TypedTaggedEventStreamEnvelopeRequestResultSessionCreate, TypedTaggedEventStreamEnvelopeRequestResultSessionMessage, TypedTaggedEventStreamEnvelopeRequestResultSessionSubmit, TypedTaggedEventStreamEnvelopeRigProvisionProgress, TypedTaggedEventStreamEnvelopeSessionColdStartTimeout, TypedTaggedEventStreamEnvelopeSessionCrashed, TypedTaggedEventStreamEnvelopeSessionDrainAckedWithAssignedWork, TypedTaggedEventStreamEnvelopeSessionDraining, TypedTaggedEventStreamEnvelopeSessionIdleKilled, TypedTaggedEventStreamEnvelopeSessionMaxAgeKilled, TypedTaggedEventStreamEnvelopeSessionQuarantined, TypedTaggedEventStreamEnvelopeSessionResetStalled, TypedTaggedEventStreamEnvelopeSessionStopped, TypedTaggedEventStreamEnvelopeSessionStranded, TypedTaggedEventStreamEnvelopeSessionSuspended, TypedTaggedEventStreamEnvelopeSessionUndrained, TypedTaggedEventStreamEnvelopeSessionUnknownState, TypedTaggedEventStreamEnvelopeSessionUpdated, TypedTaggedEventStreamEnvelopeSessionWoke, TypedTaggedEventStreamEnvelopeSessionWorkQueryFailed, TypedTaggedEventStreamEnvelopeStoreDegraded, TypedTaggedEventStreamEnvelopeStoreProbeFailed, TypedTaggedEventStreamEnvelopeStoreRecovered, TypedTaggedEventStreamEnvelopeSupervisorFsPressureSkippedTick, TypedTaggedEventStreamEnvelopeSupervisorRequest, TypedTaggedEventStreamEnvelopeSupervisorShutdownRequested, TypedTaggedEventStreamEnvelopeSupervisorStarted, TypedTaggedEventStreamEnvelopeWebhookReceived, TypedTaggedEventStreamEnvelopeWebhookRejected, TypedTaggedEventStreamEnvelopeWorkerOperation, UnboundEventPayload, UsageBody, UsageSessionRecent, UsageTotals, WaitListBody, WaitView, WebhookReceivedPayload, WebhookRejectedPayload, WorkerOperationEventPayload, WorkflowAttemptSummary, WorkflowBeadResponse, WorkflowDeleteResponse, WorkflowDepResponse, WorkflowEventProjection, WorkflowSnapshotResponse, WorkspaceResponse } from './types.gen.js'; diff --git a/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/types.gen.ts b/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/types.gen.ts index dd8b0cebd5..c7446f13dc 100644 --- a/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/types.gen.ts +++ b/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/types.gen.ts @@ -5306,8 +5306,12 @@ export type TypedEventStreamEnvelope = ({ } & TypedEventStreamEnvelopeEmergencySignaled) | ({ type: 'events.rotated'; } & TypedEventStreamEnvelopeEventsRotated) | ({ + type: 'execution.step_completed'; +} & TypedEventStreamEnvelopeExecutionStepCompleted) | ({ type: 'execution.step_defined'; } & TypedEventStreamEnvelopeExecutionStepDefined) | ({ + type: 'execution.step_started'; +} & TypedEventStreamEnvelopeExecutionStepStarted) | ({ type: 'execution.work_associated'; } & TypedEventStreamEnvelopeExecutionWorkAssociated) | ({ type: 'extmsg.adapter_added'; @@ -5873,6 +5877,24 @@ export type TypedEventStreamEnvelopeEventsRotated = { workflow?: WorkflowEventProjection; }; +/** + * TypedEventStreamEnvelope execution.step_completed + */ +export type TypedEventStreamEnvelopeExecutionStepCompleted = { + actor: string; + depends_on_step_ids?: Array; + message?: string; + payload: NoPayload; + run_id?: string; + seq: number; + session_id?: string; + step_id?: string; + subject?: string; + ts: string; + type: 'execution.step_completed'; + workflow?: WorkflowEventProjection; +}; + /** * TypedEventStreamEnvelope execution.step_defined */ @@ -5891,6 +5913,24 @@ export type TypedEventStreamEnvelopeExecutionStepDefined = { workflow?: WorkflowEventProjection; }; +/** + * TypedEventStreamEnvelope execution.step_started + */ +export type TypedEventStreamEnvelopeExecutionStepStarted = { + actor: string; + depends_on_step_ids?: Array; + message?: string; + payload: NoPayload; + run_id?: string; + seq: number; + session_id?: string; + step_id?: string; + subject?: string; + ts: string; + type: 'execution.step_started'; + workflow?: WorkflowEventProjection; +}; + /** * TypedEventStreamEnvelope execution.work_associated */ @@ -7113,8 +7153,12 @@ export type TypedTaggedEventStreamEnvelope = ({ } & TypedTaggedEventStreamEnvelopeEmergencySignaled) | ({ type: 'events.rotated'; } & TypedTaggedEventStreamEnvelopeEventsRotated) | ({ + type: 'execution.step_completed'; +} & TypedTaggedEventStreamEnvelopeExecutionStepCompleted) | ({ type: 'execution.step_defined'; } & TypedTaggedEventStreamEnvelopeExecutionStepDefined) | ({ + type: 'execution.step_started'; +} & TypedTaggedEventStreamEnvelopeExecutionStepStarted) | ({ type: 'execution.work_associated'; } & TypedTaggedEventStreamEnvelopeExecutionWorkAssociated) | ({ type: 'extmsg.adapter_added'; @@ -7704,6 +7748,25 @@ export type TypedTaggedEventStreamEnvelopeEventsRotated = { workflow?: WorkflowEventProjection; }; +/** + * TypedTaggedEventStreamEnvelope execution.step_completed + */ +export type TypedTaggedEventStreamEnvelopeExecutionStepCompleted = { + actor: string; + city: string; + depends_on_step_ids?: Array; + message?: string; + payload: NoPayload; + run_id?: string; + seq: number; + session_id?: string; + step_id?: string; + subject?: string; + ts: string; + type: 'execution.step_completed'; + workflow?: WorkflowEventProjection; +}; + /** * TypedTaggedEventStreamEnvelope execution.step_defined */ @@ -7723,6 +7786,25 @@ export type TypedTaggedEventStreamEnvelopeExecutionStepDefined = { workflow?: WorkflowEventProjection; }; +/** + * TypedTaggedEventStreamEnvelope execution.step_started + */ +export type TypedTaggedEventStreamEnvelopeExecutionStepStarted = { + actor: string; + city: string; + depends_on_step_ids?: Array; + message?: string; + payload: NoPayload; + run_id?: string; + seq: number; + session_id?: string; + step_id?: string; + subject?: string; + ts: string; + type: 'execution.step_started'; + workflow?: WorkflowEventProjection; +}; + /** * TypedTaggedEventStreamEnvelope execution.work_associated */ diff --git a/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/zod.gen.ts b/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/zod.gen.ts index 32000c3907..ff5f3930c8 100644 --- a/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/zod.gen.ts +++ b/internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/zod.gen.ts @@ -3852,6 +3852,24 @@ export const zTypedEventStreamEnvelopeEventsRotated = z.object({ workflow: zWorkflowEventProjection.optional() }); +/** + * TypedEventStreamEnvelope execution.step_completed + */ +export const zTypedEventStreamEnvelopeExecutionStepCompleted = z.object({ + actor: z.string(), + depends_on_step_ids: z.array(z.string()).optional(), + message: z.string().optional(), + payload: zNoPayload, + run_id: z.string().optional(), + seq: z.coerce.bigint().gte(BigInt(0)).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), + session_id: z.string().optional(), + step_id: z.string().optional(), + subject: z.string().optional(), + ts: z.iso.datetime(), + type: z.literal('execution.step_completed'), + workflow: zWorkflowEventProjection.optional() +}); + /** * TypedEventStreamEnvelope execution.step_defined */ @@ -3870,6 +3888,24 @@ export const zTypedEventStreamEnvelopeExecutionStepDefined = z.object({ workflow: zWorkflowEventProjection.optional() }); +/** + * TypedEventStreamEnvelope execution.step_started + */ +export const zTypedEventStreamEnvelopeExecutionStepStarted = z.object({ + actor: z.string(), + depends_on_step_ids: z.array(z.string()).optional(), + message: z.string().optional(), + payload: zNoPayload, + run_id: z.string().optional(), + seq: z.coerce.bigint().gte(BigInt(0)).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), + session_id: z.string().optional(), + step_id: z.string().optional(), + subject: z.string().optional(), + ts: z.iso.datetime(), + type: z.literal('execution.step_started'), + workflow: zWorkflowEventProjection.optional() +}); + /** * TypedEventStreamEnvelope execution.work_associated */ @@ -5069,7 +5105,9 @@ export const zTypedEventStreamEnvelope = z.discriminatedUnion('type', [ zTypedEventStreamEnvelopeEmergencyAcked.extend({ type: z.literal('emergency.acked') }), zTypedEventStreamEnvelopeEmergencySignaled.extend({ type: z.literal('emergency.signaled') }), zTypedEventStreamEnvelopeEventsRotated.extend({ type: z.literal('events.rotated') }), + zTypedEventStreamEnvelopeExecutionStepCompleted.extend({ type: z.literal('execution.step_completed') }), zTypedEventStreamEnvelopeExecutionStepDefined.extend({ type: z.literal('execution.step_defined') }), + zTypedEventStreamEnvelopeExecutionStepStarted.extend({ type: z.literal('execution.step_started') }), zTypedEventStreamEnvelopeExecutionWorkAssociated.extend({ type: z.literal('execution.work_associated') }), zTypedEventStreamEnvelopeExtmsgAdapterAdded.extend({ type: z.literal('extmsg.adapter_added') }), zTypedEventStreamEnvelopeExtmsgAdapterRemoved.extend({ type: z.literal('extmsg.adapter_removed') }), @@ -5602,6 +5640,25 @@ export const zTypedTaggedEventStreamEnvelopeEventsRotated = z.object({ workflow: zWorkflowEventProjection.optional() }); +/** + * TypedTaggedEventStreamEnvelope execution.step_completed + */ +export const zTypedTaggedEventStreamEnvelopeExecutionStepCompleted = z.object({ + actor: z.string(), + city: z.string(), + depends_on_step_ids: z.array(z.string()).optional(), + message: z.string().optional(), + payload: zNoPayload, + run_id: z.string().optional(), + seq: z.coerce.bigint().gte(BigInt(0)).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), + session_id: z.string().optional(), + step_id: z.string().optional(), + subject: z.string().optional(), + ts: z.iso.datetime(), + type: z.literal('execution.step_completed'), + workflow: zWorkflowEventProjection.optional() +}); + /** * TypedTaggedEventStreamEnvelope execution.step_defined */ @@ -5621,6 +5678,25 @@ export const zTypedTaggedEventStreamEnvelopeExecutionStepDefined = z.object({ workflow: zWorkflowEventProjection.optional() }); +/** + * TypedTaggedEventStreamEnvelope execution.step_started + */ +export const zTypedTaggedEventStreamEnvelopeExecutionStepStarted = z.object({ + actor: z.string(), + city: z.string(), + depends_on_step_ids: z.array(z.string()).optional(), + message: z.string().optional(), + payload: zNoPayload, + run_id: z.string().optional(), + seq: z.coerce.bigint().gte(BigInt(0)).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }), + session_id: z.string().optional(), + step_id: z.string().optional(), + subject: z.string().optional(), + ts: z.iso.datetime(), + type: z.literal('execution.step_started'), + workflow: zWorkflowEventProjection.optional() +}); + /** * TypedTaggedEventStreamEnvelope execution.work_associated */ @@ -6885,7 +6961,9 @@ export const zTypedTaggedEventStreamEnvelope = z.discriminatedUnion('type', [ zTypedTaggedEventStreamEnvelopeEmergencyAcked.extend({ type: z.literal('emergency.acked') }), zTypedTaggedEventStreamEnvelopeEmergencySignaled.extend({ type: z.literal('emergency.signaled') }), zTypedTaggedEventStreamEnvelopeEventsRotated.extend({ type: z.literal('events.rotated') }), + zTypedTaggedEventStreamEnvelopeExecutionStepCompleted.extend({ type: z.literal('execution.step_completed') }), zTypedTaggedEventStreamEnvelopeExecutionStepDefined.extend({ type: z.literal('execution.step_defined') }), + zTypedTaggedEventStreamEnvelopeExecutionStepStarted.extend({ type: z.literal('execution.step_started') }), zTypedTaggedEventStreamEnvelopeExecutionWorkAssociated.extend({ type: z.literal('execution.work_associated') }), zTypedTaggedEventStreamEnvelopeExtmsgAdapterAdded.extend({ type: z.literal('extmsg.adapter_added') }), zTypedTaggedEventStreamEnvelopeExtmsgAdapterRemoved.extend({ type: z.literal('extmsg.adapter_removed') }), diff --git a/internal/api/genclient/client_gen.go b/internal/api/genclient/client_gen.go index 85583358e7..7dd46cf9d1 100644 --- a/internal/api/genclient/client_gen.go +++ b/internal/api/genclient/client_gen.go @@ -5699,6 +5699,22 @@ type TypedEventStreamEnvelopeEventsRotated struct { Workflow *WorkflowEventProjection `json:"workflow,omitempty"` } +// TypedEventStreamEnvelopeExecutionStepCompleted defines model for TypedEventStreamEnvelopeExecutionStepCompleted. +type TypedEventStreamEnvelopeExecutionStepCompleted struct { + Actor string `json:"actor"` + DependsOnStepIds *[]string `json:"depends_on_step_ids,omitempty"` + Message *string `json:"message,omitempty"` + Payload NoPayload `json:"payload"` + RunId *string `json:"run_id,omitempty"` + Seq int64 `json:"seq"` + SessionId *string `json:"session_id,omitempty"` + StepId *string `json:"step_id,omitempty"` + Subject *string `json:"subject,omitempty"` + Ts time.Time `json:"ts"` + Type string `json:"type"` + Workflow *WorkflowEventProjection `json:"workflow,omitempty"` +} + // TypedEventStreamEnvelopeExecutionStepDefined defines model for TypedEventStreamEnvelopeExecutionStepDefined. type TypedEventStreamEnvelopeExecutionStepDefined struct { Actor string `json:"actor"` @@ -5715,6 +5731,22 @@ type TypedEventStreamEnvelopeExecutionStepDefined struct { Workflow *WorkflowEventProjection `json:"workflow,omitempty"` } +// TypedEventStreamEnvelopeExecutionStepStarted defines model for TypedEventStreamEnvelopeExecutionStepStarted. +type TypedEventStreamEnvelopeExecutionStepStarted struct { + Actor string `json:"actor"` + DependsOnStepIds *[]string `json:"depends_on_step_ids,omitempty"` + Message *string `json:"message,omitempty"` + Payload NoPayload `json:"payload"` + RunId *string `json:"run_id,omitempty"` + Seq int64 `json:"seq"` + SessionId *string `json:"session_id,omitempty"` + StepId *string `json:"step_id,omitempty"` + Subject *string `json:"subject,omitempty"` + Ts time.Time `json:"ts"` + Type string `json:"type"` + Workflow *WorkflowEventProjection `json:"workflow,omitempty"` +} + // TypedEventStreamEnvelopeExecutionWorkAssociated defines model for TypedEventStreamEnvelopeExecutionWorkAssociated. type TypedEventStreamEnvelopeExecutionWorkAssociated struct { Actor string `json:"actor"` @@ -7168,6 +7200,23 @@ type TypedTaggedEventStreamEnvelopeEventsRotated struct { Workflow *WorkflowEventProjection `json:"workflow,omitempty"` } +// TypedTaggedEventStreamEnvelopeExecutionStepCompleted defines model for TypedTaggedEventStreamEnvelopeExecutionStepCompleted. +type TypedTaggedEventStreamEnvelopeExecutionStepCompleted struct { + Actor string `json:"actor"` + City string `json:"city"` + DependsOnStepIds *[]string `json:"depends_on_step_ids,omitempty"` + Message *string `json:"message,omitempty"` + Payload NoPayload `json:"payload"` + RunId *string `json:"run_id,omitempty"` + Seq int64 `json:"seq"` + SessionId *string `json:"session_id,omitempty"` + StepId *string `json:"step_id,omitempty"` + Subject *string `json:"subject,omitempty"` + Ts time.Time `json:"ts"` + Type string `json:"type"` + Workflow *WorkflowEventProjection `json:"workflow,omitempty"` +} + // TypedTaggedEventStreamEnvelopeExecutionStepDefined defines model for TypedTaggedEventStreamEnvelopeExecutionStepDefined. type TypedTaggedEventStreamEnvelopeExecutionStepDefined struct { Actor string `json:"actor"` @@ -7185,6 +7234,23 @@ type TypedTaggedEventStreamEnvelopeExecutionStepDefined struct { Workflow *WorkflowEventProjection `json:"workflow,omitempty"` } +// TypedTaggedEventStreamEnvelopeExecutionStepStarted defines model for TypedTaggedEventStreamEnvelopeExecutionStepStarted. +type TypedTaggedEventStreamEnvelopeExecutionStepStarted struct { + Actor string `json:"actor"` + City string `json:"city"` + DependsOnStepIds *[]string `json:"depends_on_step_ids,omitempty"` + Message *string `json:"message,omitempty"` + Payload NoPayload `json:"payload"` + RunId *string `json:"run_id,omitempty"` + Seq int64 `json:"seq"` + SessionId *string `json:"session_id,omitempty"` + StepId *string `json:"step_id,omitempty"` + Subject *string `json:"subject,omitempty"` + Ts time.Time `json:"ts"` + Type string `json:"type"` + Workflow *WorkflowEventProjection `json:"workflow,omitempty"` +} + // TypedTaggedEventStreamEnvelopeExecutionWorkAssociated defines model for TypedTaggedEventStreamEnvelopeExecutionWorkAssociated. type TypedTaggedEventStreamEnvelopeExecutionWorkAssociated struct { Actor string `json:"actor"` @@ -13617,6 +13683,34 @@ func (t *TypedEventStreamEnvelope) MergeTypedEventStreamEnvelopeEventsRotated(v return err } +// AsTypedEventStreamEnvelopeExecutionStepCompleted returns the union data inside the TypedEventStreamEnvelope as a TypedEventStreamEnvelopeExecutionStepCompleted +func (t TypedEventStreamEnvelope) AsTypedEventStreamEnvelopeExecutionStepCompleted() (TypedEventStreamEnvelopeExecutionStepCompleted, error) { + var body TypedEventStreamEnvelopeExecutionStepCompleted + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTypedEventStreamEnvelopeExecutionStepCompleted overwrites any union data inside the TypedEventStreamEnvelope as the provided TypedEventStreamEnvelopeExecutionStepCompleted +func (t *TypedEventStreamEnvelope) FromTypedEventStreamEnvelopeExecutionStepCompleted(v TypedEventStreamEnvelopeExecutionStepCompleted) error { + v.Type = "execution.step_completed" + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTypedEventStreamEnvelopeExecutionStepCompleted performs a merge with any union data inside the TypedEventStreamEnvelope, using the provided TypedEventStreamEnvelopeExecutionStepCompleted +func (t *TypedEventStreamEnvelope) MergeTypedEventStreamEnvelopeExecutionStepCompleted(v TypedEventStreamEnvelopeExecutionStepCompleted) error { + v.Type = "execution.step_completed" + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + // AsTypedEventStreamEnvelopeExecutionStepDefined returns the union data inside the TypedEventStreamEnvelope as a TypedEventStreamEnvelopeExecutionStepDefined func (t TypedEventStreamEnvelope) AsTypedEventStreamEnvelopeExecutionStepDefined() (TypedEventStreamEnvelopeExecutionStepDefined, error) { var body TypedEventStreamEnvelopeExecutionStepDefined @@ -13645,6 +13739,34 @@ func (t *TypedEventStreamEnvelope) MergeTypedEventStreamEnvelopeExecutionStepDef return err } +// AsTypedEventStreamEnvelopeExecutionStepStarted returns the union data inside the TypedEventStreamEnvelope as a TypedEventStreamEnvelopeExecutionStepStarted +func (t TypedEventStreamEnvelope) AsTypedEventStreamEnvelopeExecutionStepStarted() (TypedEventStreamEnvelopeExecutionStepStarted, error) { + var body TypedEventStreamEnvelopeExecutionStepStarted + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTypedEventStreamEnvelopeExecutionStepStarted overwrites any union data inside the TypedEventStreamEnvelope as the provided TypedEventStreamEnvelopeExecutionStepStarted +func (t *TypedEventStreamEnvelope) FromTypedEventStreamEnvelopeExecutionStepStarted(v TypedEventStreamEnvelopeExecutionStepStarted) error { + v.Type = "execution.step_started" + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTypedEventStreamEnvelopeExecutionStepStarted performs a merge with any union data inside the TypedEventStreamEnvelope, using the provided TypedEventStreamEnvelopeExecutionStepStarted +func (t *TypedEventStreamEnvelope) MergeTypedEventStreamEnvelopeExecutionStepStarted(v TypedEventStreamEnvelopeExecutionStepStarted) error { + v.Type = "execution.step_started" + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + // AsTypedEventStreamEnvelopeExecutionWorkAssociated returns the union data inside the TypedEventStreamEnvelope as a TypedEventStreamEnvelopeExecutionWorkAssociated func (t TypedEventStreamEnvelope) AsTypedEventStreamEnvelopeExecutionWorkAssociated() (TypedEventStreamEnvelopeExecutionWorkAssociated, error) { var body TypedEventStreamEnvelopeExecutionWorkAssociated @@ -15555,8 +15677,12 @@ func (t TypedEventStreamEnvelope) ValueByDiscriminator() (interface{}, error) { return t.AsTypedEventStreamEnvelopeEmergencySignaled() case "events.rotated": return t.AsTypedEventStreamEnvelopeEventsRotated() + case "execution.step_completed": + return t.AsTypedEventStreamEnvelopeExecutionStepCompleted() case "execution.step_defined": return t.AsTypedEventStreamEnvelopeExecutionStepDefined() + case "execution.step_started": + return t.AsTypedEventStreamEnvelopeExecutionStepStarted() case "execution.work_associated": return t.AsTypedEventStreamEnvelopeExecutionWorkAssociated() case "extmsg.adapter_added": @@ -16346,6 +16472,34 @@ func (t *TypedTaggedEventStreamEnvelope) MergeTypedTaggedEventStreamEnvelopeEven return err } +// AsTypedTaggedEventStreamEnvelopeExecutionStepCompleted returns the union data inside the TypedTaggedEventStreamEnvelope as a TypedTaggedEventStreamEnvelopeExecutionStepCompleted +func (t TypedTaggedEventStreamEnvelope) AsTypedTaggedEventStreamEnvelopeExecutionStepCompleted() (TypedTaggedEventStreamEnvelopeExecutionStepCompleted, error) { + var body TypedTaggedEventStreamEnvelopeExecutionStepCompleted + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTypedTaggedEventStreamEnvelopeExecutionStepCompleted overwrites any union data inside the TypedTaggedEventStreamEnvelope as the provided TypedTaggedEventStreamEnvelopeExecutionStepCompleted +func (t *TypedTaggedEventStreamEnvelope) FromTypedTaggedEventStreamEnvelopeExecutionStepCompleted(v TypedTaggedEventStreamEnvelopeExecutionStepCompleted) error { + v.Type = "execution.step_completed" + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTypedTaggedEventStreamEnvelopeExecutionStepCompleted performs a merge with any union data inside the TypedTaggedEventStreamEnvelope, using the provided TypedTaggedEventStreamEnvelopeExecutionStepCompleted +func (t *TypedTaggedEventStreamEnvelope) MergeTypedTaggedEventStreamEnvelopeExecutionStepCompleted(v TypedTaggedEventStreamEnvelopeExecutionStepCompleted) error { + v.Type = "execution.step_completed" + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + // AsTypedTaggedEventStreamEnvelopeExecutionStepDefined returns the union data inside the TypedTaggedEventStreamEnvelope as a TypedTaggedEventStreamEnvelopeExecutionStepDefined func (t TypedTaggedEventStreamEnvelope) AsTypedTaggedEventStreamEnvelopeExecutionStepDefined() (TypedTaggedEventStreamEnvelopeExecutionStepDefined, error) { var body TypedTaggedEventStreamEnvelopeExecutionStepDefined @@ -16374,6 +16528,34 @@ func (t *TypedTaggedEventStreamEnvelope) MergeTypedTaggedEventStreamEnvelopeExec return err } +// AsTypedTaggedEventStreamEnvelopeExecutionStepStarted returns the union data inside the TypedTaggedEventStreamEnvelope as a TypedTaggedEventStreamEnvelopeExecutionStepStarted +func (t TypedTaggedEventStreamEnvelope) AsTypedTaggedEventStreamEnvelopeExecutionStepStarted() (TypedTaggedEventStreamEnvelopeExecutionStepStarted, error) { + var body TypedTaggedEventStreamEnvelopeExecutionStepStarted + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTypedTaggedEventStreamEnvelopeExecutionStepStarted overwrites any union data inside the TypedTaggedEventStreamEnvelope as the provided TypedTaggedEventStreamEnvelopeExecutionStepStarted +func (t *TypedTaggedEventStreamEnvelope) FromTypedTaggedEventStreamEnvelopeExecutionStepStarted(v TypedTaggedEventStreamEnvelopeExecutionStepStarted) error { + v.Type = "execution.step_started" + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTypedTaggedEventStreamEnvelopeExecutionStepStarted performs a merge with any union data inside the TypedTaggedEventStreamEnvelope, using the provided TypedTaggedEventStreamEnvelopeExecutionStepStarted +func (t *TypedTaggedEventStreamEnvelope) MergeTypedTaggedEventStreamEnvelopeExecutionStepStarted(v TypedTaggedEventStreamEnvelopeExecutionStepStarted) error { + v.Type = "execution.step_started" + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + // AsTypedTaggedEventStreamEnvelopeExecutionWorkAssociated returns the union data inside the TypedTaggedEventStreamEnvelope as a TypedTaggedEventStreamEnvelopeExecutionWorkAssociated func (t TypedTaggedEventStreamEnvelope) AsTypedTaggedEventStreamEnvelopeExecutionWorkAssociated() (TypedTaggedEventStreamEnvelopeExecutionWorkAssociated, error) { var body TypedTaggedEventStreamEnvelopeExecutionWorkAssociated @@ -18284,8 +18466,12 @@ func (t TypedTaggedEventStreamEnvelope) ValueByDiscriminator() (interface{}, err return t.AsTypedTaggedEventStreamEnvelopeEmergencySignaled() case "events.rotated": return t.AsTypedTaggedEventStreamEnvelopeEventsRotated() + case "execution.step_completed": + return t.AsTypedTaggedEventStreamEnvelopeExecutionStepCompleted() case "execution.step_defined": return t.AsTypedTaggedEventStreamEnvelopeExecutionStepDefined() + case "execution.step_started": + return t.AsTypedTaggedEventStreamEnvelopeExecutionStepStarted() case "execution.work_associated": return t.AsTypedTaggedEventStreamEnvelopeExecutionWorkAssociated() case "extmsg.adapter_added": diff --git a/internal/api/handler_beads_test.go b/internal/api/handler_beads_test.go index 4a003d764e..dd4ed973cb 100644 --- a/internal/api/handler_beads_test.go +++ b/internal/api/handler_beads_test.go @@ -1754,8 +1754,8 @@ func TestPhase2BeadAssignNormalizesCurrentSessionAlias(t *testing.T) { t.Fatalf("assign alias status = %d, want %d; body: %s", rec.Code, http.StatusOK, rec.Body.String()) } got, _ := store.Get(work.ID) - if got.Assignee != sessionBead.Metadata["session_name"] { - t.Fatalf("assignee = %q, want alias normalized to session_name %q", got.Assignee, sessionBead.Metadata["session_name"]) + if got.Assignee != sessionBead.Metadata["alias"] { + t.Fatalf("assignee = %q, want canonical alias %q", got.Assignee, sessionBead.Metadata["alias"]) } listReq := httptest.NewRequest("GET", cityURL(state, "/beads?assignee=worker"), nil) @@ -1865,8 +1865,8 @@ func TestPhase2BeadAssignNormalizesCurrentSessionName(t *testing.T) { t.Fatalf("assign session_name status = %d, want %d; body: %s", rec.Code, http.StatusOK, rec.Body.String()) } got, _ := store.Get(work.ID) - if got.Assignee != sessionBead.Metadata["session_name"] { - t.Fatalf("assignee = %q, want session_name preserved as %q", got.Assignee, sessionBead.Metadata["session_name"]) + if got.Assignee != sessionBead.Metadata["alias"] { + t.Fatalf("assignee = %q, want session_name normalized to canonical alias %q", got.Assignee, sessionBead.Metadata["alias"]) } } @@ -2000,8 +2000,8 @@ func TestPhase2BeadAssignAcceptsRepairableSessionBeadID(t *testing.T) { t.Fatalf("assign repairable session status = %d, want %d; body: %s", rec.Code, http.StatusOK, rec.Body.String()) } got, _ := store.Get(work.ID) - if got.Assignee != sessionBead.Metadata["session_name"] { - t.Fatalf("assignee = %q, want repairable session_name %q", got.Assignee, sessionBead.Metadata["session_name"]) + if got.Assignee != sessionBead.Metadata["alias"] { + t.Fatalf("assignee = %q, want repairable session alias %q", got.Assignee, sessionBead.Metadata["alias"]) } gotSession, _ := state.cityBeadStore.Get(sessionBead.ID) if gotSession.Type != session.BeadType { @@ -2027,8 +2027,8 @@ func TestPhase2BeadUpdateNormalizesRawAssigneeAlias(t *testing.T) { t.Fatalf("update alias status = %d, want %d; body: %s", rec.Code, http.StatusOK, rec.Body.String()) } got, _ := store.Get(work.ID) - if got.Assignee != sessionBead.Metadata["session_name"] { - t.Fatalf("assignee = %q, want alias normalized to session_name %q", got.Assignee, sessionBead.Metadata["session_name"]) + if got.Assignee != sessionBead.Metadata["alias"] { + t.Fatalf("assignee = %q, want canonical alias %q", got.Assignee, sessionBead.Metadata["alias"]) } } @@ -2053,8 +2053,8 @@ func TestPhase2BeadCreateNormalizesRawAssigneeAlias(t *testing.T) { if len(items) != 1 { t.Fatalf("created %d beads, want 1", len(items)) } - if items[0].Assignee != sessionBead.Metadata["session_name"] { - t.Fatalf("created assignee = %q, want alias normalized to session_name %q", items[0].Assignee, sessionBead.Metadata["session_name"]) + if items[0].Assignee != sessionBead.Metadata["alias"] { + t.Fatalf("created assignee = %q, want canonical alias %q", items[0].Assignee, sessionBead.Metadata["alias"]) } } diff --git a/internal/api/openapi.json b/internal/api/openapi.json index f6f337060b..4000245af2 100644 --- a/internal/api/openapi.json +++ b/internal/api/openapi.json @@ -12200,7 +12200,9 @@ "emergency.acked": "#/components/schemas/TypedEventStreamEnvelopeEmergencyAcked", "emergency.signaled": "#/components/schemas/TypedEventStreamEnvelopeEmergencySignaled", "events.rotated": "#/components/schemas/TypedEventStreamEnvelopeEventsRotated", + "execution.step_completed": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepCompleted", "execution.step_defined": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepDefined", + "execution.step_started": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepStarted", "execution.work_associated": "#/components/schemas/TypedEventStreamEnvelopeExecutionWorkAssociated", "extmsg.adapter_added": "#/components/schemas/TypedEventStreamEnvelopeExtmsgAdapterAdded", "extmsg.adapter_removed": "#/components/schemas/TypedEventStreamEnvelopeExtmsgAdapterRemoved", @@ -12339,9 +12341,15 @@ { "$ref": "#/components/schemas/TypedEventStreamEnvelopeEventsRotated" }, + { + "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepCompleted" + }, { "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepDefined" }, + { + "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionStepStarted" + }, { "$ref": "#/components/schemas/TypedEventStreamEnvelopeExecutionWorkAssociated" }, @@ -13692,6 +13700,8 @@ "bead.dead_assignee_reopened", "execution.work_associated", "execution.step_defined", + "execution.step_started", + "execution.step_completed", "mail.sent", "mail.read", "mail.archived", @@ -14001,6 +14011,63 @@ "title": "TypedEventStreamEnvelope events.rotated", "type": "object" }, + "TypedEventStreamEnvelopeExecutionStepCompleted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_completed", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload" + ], + "title": "TypedEventStreamEnvelope execution.step_completed", + "type": "object" + }, "TypedEventStreamEnvelopeExecutionStepDefined": { "additionalProperties": false, "properties": { @@ -14058,6 +14125,63 @@ "title": "TypedEventStreamEnvelope execution.step_defined", "type": "object" }, + "TypedEventStreamEnvelopeExecutionStepStarted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_started", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload" + ], + "title": "TypedEventStreamEnvelope execution.step_started", + "type": "object" + }, "TypedEventStreamEnvelopeExecutionWorkAssociated": { "additionalProperties": false, "properties": { @@ -17790,7 +17914,9 @@ "emergency.acked": "#/components/schemas/TypedTaggedEventStreamEnvelopeEmergencyAcked", "emergency.signaled": "#/components/schemas/TypedTaggedEventStreamEnvelopeEmergencySignaled", "events.rotated": "#/components/schemas/TypedTaggedEventStreamEnvelopeEventsRotated", + "execution.step_completed": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepCompleted", "execution.step_defined": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepDefined", + "execution.step_started": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepStarted", "execution.work_associated": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionWorkAssociated", "extmsg.adapter_added": "#/components/schemas/TypedTaggedEventStreamEnvelopeExtmsgAdapterAdded", "extmsg.adapter_removed": "#/components/schemas/TypedTaggedEventStreamEnvelopeExtmsgAdapterRemoved", @@ -17929,9 +18055,15 @@ { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeEventsRotated" }, + { + "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepCompleted" + }, { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepDefined" }, + { + "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionStepStarted" + }, { "$ref": "#/components/schemas/TypedTaggedEventStreamEnvelopeExecutionWorkAssociated" }, @@ -19361,6 +19493,8 @@ "bead.dead_assignee_reopened", "execution.work_associated", "execution.step_defined", + "execution.step_started", + "execution.step_completed", "mail.sent", "mail.read", "mail.archived", @@ -19687,6 +19821,67 @@ "title": "TypedTaggedEventStreamEnvelope events.rotated", "type": "object" }, + "TypedTaggedEventStreamEnvelopeExecutionStepCompleted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "city": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_completed", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload", + "city" + ], + "title": "TypedTaggedEventStreamEnvelope execution.step_completed", + "type": "object" + }, "TypedTaggedEventStreamEnvelopeExecutionStepDefined": { "additionalProperties": false, "properties": { @@ -19748,6 +19943,67 @@ "title": "TypedTaggedEventStreamEnvelope execution.step_defined", "type": "object" }, + "TypedTaggedEventStreamEnvelopeExecutionStepStarted": { + "additionalProperties": false, + "properties": { + "actor": { + "type": "string" + }, + "city": { + "type": "string" + }, + "depends_on_step_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/NoPayload" + }, + "run_id": { + "type": "string" + }, + "seq": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "session_id": { + "type": "string" + }, + "step_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "ts": { + "format": "date-time", + "type": "string" + }, + "type": { + "const": "execution.step_started", + "type": "string" + }, + "workflow": { + "$ref": "#/components/schemas/WorkflowEventProjection" + } + }, + "required": [ + "seq", + "type", + "ts", + "actor", + "payload", + "city" + ], + "title": "TypedTaggedEventStreamEnvelope execution.step_started", + "type": "object" + }, "TypedTaggedEventStreamEnvelopeExecutionWorkAssociated": { "additionalProperties": false, "properties": { diff --git a/internal/bdflags/bdargs.go b/internal/bdflags/bdargs.go new file mode 100644 index 0000000000..e855aec00c --- /dev/null +++ b/internal/bdflags/bdargs.go @@ -0,0 +1,112 @@ +package bdflags + +import ( + "fmt" + "strings" +) + +// SplitGlobalFlags splits a bd argv into its subcommand and the arguments that +// follow it, skipping the values of global value-flags. +// +// Taking the first non-dash token as the subcommand reads a global flag's VALUE +// instead: `bd --actor bob update ...` yields "bob". Anything keyed off the +// subcommand — a mutation guard, a routing decision — is then bypassed by a +// token the caller never meant as a verb. +func SplitGlobalFlags(args []string) (string, []string) { + globals := GlobalValueFlags() + for i := 0; i < len(args); i++ { + a := args[i] + if !strings.HasPrefix(a, "-") { + return a, args[i+1:] + } + // An inline --flag=value consumes nothing further. + if strings.IndexByte(a, '=') < 0 && globals[a] && i+1 < len(args) { + i++ + } + } + return "", nil +} + +// Positionals returns the positional arguments of a bd subcommand's argv, +// skipping every token consumed as a flag's value. +// +// It needs the FULL value-flag set for the subcommand, not a subset: with a +// partial set the value of any omitted flag is read as a positional. That is how +// `update --add-label role=worker` came to look like a stray key=value +// token rather than a flag value. +func Positionals(sub string, args []string) []string { + needsValue := ValueFlags(sub) + var positionals []string + for i := 0; i < len(args); i++ { + a := args[i] + if !strings.HasPrefix(a, "-") { + positionals = append(positionals, a) + continue + } + hasInlineValue := strings.IndexByte(a, '=') >= 0 + name := a + if hasInlineValue { + name = a[:strings.IndexByte(a, '=')] + } + if !hasInlineValue && needsValue[name] && i+1 < len(args) { + i++ + } + } + return positionals +} + +// DroppedMetadataPairs returns the bare key=value tokens sitting in `bd update`'s +// positional issue-id slot — the --set-metadata pairs bd is about to discard. +// +// --set-metadata is a repeatable flag taking ONE pair per occurrence, so in +// `--set-metadata a=1 b=2 c=3` only a=1 is the flag's value; b=2 and c=3 become +// positional issue ids. bd fails to resolve them, reports the failures on +// stderr, prints its success line for the id that did resolve, and EXITS 0 — +// so a caller cannot distinguish a full write from a 1-of-N write, and no +// exit-code check in any script can see it. +// +// No bead id contains '=', so such a positional never resolved under bd either: +// reporting one cannot condemn an invocation that previously worked. +func DroppedMetadataPairs(args []string) []string { + var dropped []string + for _, p := range Positionals("update", args) { + if strings.IndexByte(p, '=') >= 0 { + dropped = append(dropped, p) + } + } + return dropped +} + +// DroppedMetadataRefusal builds the refusal message for a `bd update` whose +// metadata pairs would be silently dropped, or reports false for any other verb +// and every well-formed invocation. prefix names the entry point (e.g. "gc bd"). +// +// The message names each dropped pair and the form that works, because the +// caller's own output gives it nothing: bd prints success and exits 0 however +// many pairs it discarded. +func DroppedMetadataRefusal(prefix, verb string, args []string) (string, bool) { + if verb != "update" { + return "", false + } + dropped := DroppedMetadataPairs(args) + if len(dropped) == 0 { + return "", false + } + corrected := make([]string, 0, len(dropped)) + for _, pair := range dropped { + corrected = append(corrected, "--set-metadata "+pair) + } + subject, object := "it", "an issue id" + if len(dropped) > 1 { + subject, object = "them", "issue ids" + } + return fmt.Sprintf( + "%s: refusing update: %s would be dropped. --set-metadata takes ONE key=value per flag, so bd reads %s as %s, fails to resolve %s, and still exits 0 after writing only the first pair. Repeat the flag instead: %s\n", + prefix, + strings.Join(dropped, ", "), + strings.Join(dropped, ", "), + object, + subject, + strings.Join(corrected, " "), + ), true +} diff --git a/internal/bdflags/bdargs_test.go b/internal/bdflags/bdargs_test.go new file mode 100644 index 0000000000..19f79475ad --- /dev/null +++ b/internal/bdflags/bdargs_test.go @@ -0,0 +1,162 @@ +package bdflags + +import ( + "reflect" + "testing" +) + +// TestSplitGlobalFlagsSkipsGlobalFlagValues pins that a global flag's VALUE is +// never mistaken for the subcommand. Taking the first non-dash token reads +// "bob" out of `bd --actor bob update ...`, so anything keyed off the +// subcommand is bypassed by a token the caller never meant as a verb. +func TestSplitGlobalFlagsSkipsGlobalFlagValues(t *testing.T) { + cases := []struct { + name string + args []string + wantVerb string + wantRest []string + }{ + {"plain", []string{"update", "bd-1"}, "update", []string{"bd-1"}}, + {"--actor", []string{"--actor", "bob", "update", "bd-1"}, "update", []string{"bd-1"}}, + {"-C dir", []string{"-C", "/some/dir", "update", "bd-1"}, "update", []string{"bd-1"}}, + {"--db", []string{"--db", "/x/y.db", "update", "bd-1"}, "update", []string{"bd-1"}}, + {"--directory", []string{"--directory", "/d", "close", "bd-1"}, "close", []string{"bd-1"}}, + {"inline form consumes nothing", []string{"--actor=bob", "update", "bd-1"}, "update", []string{"bd-1"}}, + {"bool global", []string{"--json", "update", "bd-1"}, "update", []string{"bd-1"}}, + {"stacked", []string{"--actor", "bob", "--json", "-C", "/d", "update", "bd-1"}, "update", []string{"bd-1"}}, + {"no verb", []string{"--actor", "bob"}, "", nil}, + {"empty", nil, "", nil}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + verb, rest := SplitGlobalFlags(tc.args) + if verb != tc.wantVerb { + t.Errorf("verb = %q, want %q", verb, tc.wantVerb) + } + if !reflect.DeepEqual(rest, tc.wantRest) { + t.Errorf("rest = %v, want %v", rest, tc.wantRest) + } + }) + } +} + +// TestGlobalValueFlagsIsComplete pins the global value-flag set against bd's +// own persistent-flag list. A flag missing from this table silently reopens the +// bypass below: SplitGlobalFlags would read that flag's value as the verb, and +// every guard keyed off the verb stops firing — with no test failing. +// +// Sourced from `bd --help` (bd 1.1.0). bd declares exactly four persistent +// flags that consume the next argument; -C and --directory are the two spellings +// of one of them. Every other persistent flag (--global, --ignore-schema-skew, +// --json, --profile, -q/--quiet, --readonly, --sandbox, -v/--verbose, -h/--help, +// -V/--version) is boolean and consumes nothing. +func TestGlobalValueFlagsIsComplete(t *testing.T) { + want := map[string]bool{ + "--actor": true, "--db": true, "-C": true, "--directory": true, + "--dolt-auto-commit": true, + } + if got := GlobalValueFlags(); !reflect.DeepEqual(got, want) { + t.Errorf("GlobalValueFlags() = %v, want %v; re-check `bd --help` persistent flags", got, want) + } +} + +// TestRefusalFiresBehindAGlobalFlag composes the two halves of the guard the way +// the caller does — locate the verb, then judge its args — and pins that a +// global value-flag before the verb does not disarm it. +// +// Testing SplitGlobalFlags and DroppedMetadataRefusal only in isolation leaves +// the composition untested, and the composition is where the bypass lived: +// `bd --actor bob update --set-metadata a=1 b=2` yielded verb "bob", the +// refusal is scoped to "update", so it never fired and bd performed the silent +// 1-of-N write the guard exists to prevent. +func TestRefusalFiresBehindAGlobalFlag(t *testing.T) { + prefixes := [][]string{ + {"--actor", "bob"}, + {"-C", "/some/dir"}, + {"--db", "/x/y.db"}, + {"--directory", "/d"}, + {"--dolt-auto-commit", "off"}, + {"--actor", "bob", "--json", "-C", "/d"}, + } + for _, prefix := range prefixes { + args := append(append([]string{}, prefix...), "update", "bd-1", "--set-metadata", "a=1", "b=2") + verb, rest := SplitGlobalFlags(args) + msg, ok := DroppedMetadataRefusal("gc bd", verb, rest) + if !ok { + t.Errorf("prefix %v: refusal did not fire (verb=%q); the silent 1-of-N write survives", prefix, verb) + continue + } + if !contains(msg, "b=2") { + t.Errorf("prefix %v: message %q does not name the dropped pair", prefix, msg) + } + } +} + +// TestPositionalsKnowsEveryValueTakingFlag is the drift guard: positional +// detection must consume the value of EVERY value-taking flag for the +// subcommand. With a partial set, the value of any omitted flag is read as a +// positional — which is how `update --add-label role=worker` came to look +// like a stray key=value token. +func TestPositionalsKnowsEveryValueTakingFlag(t *testing.T) { + for flag := range ValueFlags("update") { + got := Positionals("update", []string{"bd-1", flag, "role=worker"}) + if len(got) != 1 || got[0] != "bd-1" { + t.Errorf("Positionals(update, bd-1 %s role=worker) = %v; the flag's value was read as an id", flag, got) + } + } +} + +// TestDroppedMetadataPairs pins detection in both directions. +func TestDroppedMetadataPairs(t *testing.T) { + dropped := [][]string{ + {"bd-1", "--set-metadata", "a=1", "b=2"}, + {"bd-1", "--set-metadata", "a=1", "b=2", "c=3"}, + {"bd-1", "--set-metadata=a=1", "b=2"}, + } + for _, args := range dropped { + if len(DroppedMetadataPairs(args)) == 0 { + t.Errorf("DroppedMetadataPairs(%v) = none; want the dropped pair caught", args) + } + } + valid := [][]string{ + {"bd-1", "--set-metadata", "a=1"}, + {"bd-1", "--set-metadata", "a=1", "--set-metadata", "b=2"}, + {"bd-1", "--add-label", "role=worker"}, + {"bd-1", "--set-labels", "a=b"}, + {"bd-1", "--external-ref", "https://example.test/i/ABC-1?tab=activity"}, + {"bd-1", "--metadata", `{"url":"https://x?a=b"}`}, + {"bd-1", "bd-2", "--set-metadata", "a=1"}, + } + for _, args := range valid { + if got := DroppedMetadataPairs(args); len(got) != 0 { + t.Errorf("DroppedMetadataPairs(%v) = %v; this is a valid invocation", args, got) + } + } +} + +// TestDroppedMetadataRefusalOnlyUpdate pins that the refusal is scoped to update. +func TestDroppedMetadataRefusalOnlyUpdate(t *testing.T) { + if _, ok := DroppedMetadataRefusal("gc bd", "create", []string{"t", "--set-metadata", "a=1", "b=2"}); ok { + t.Error("refusal fired for create; --set-metadata is an update flag") + } + msg, ok := DroppedMetadataRefusal("gc bd", "update", []string{"bd-1", "--set-metadata", "a=1", "b=2"}) + if !ok { + t.Fatal("refusal did not fire for update") + } + for _, want := range []string{"b=2", "--set-metadata", "exits 0"} { + if !contains(msg, want) { + t.Errorf("message %q missing %q", msg, want) + } + } +} + +func contains(s, sub string) bool { + return len(s) >= len(sub) && func() bool { + for i := 0; i+len(sub) <= len(s); i++ { + if s[i:i+len(sub)] == sub { + return true + } + } + return false + }() +} diff --git a/internal/bdflags/bdflags.go b/internal/bdflags/bdflags.go index c033c24662..4d63b79997 100644 --- a/internal/bdflags/bdflags.go +++ b/internal/bdflags/bdflags.go @@ -169,6 +169,13 @@ var boolFlagsBySub = map[string]map[string]bool{ "dep remove": {}, } +// GlobalValueFlags returns the flags accepted by every bd subcommand that +// consume the next argument as their value. A caller locating the subcommand in +// an argv must skip these values, or it reads one of them as the verb. +func GlobalValueFlags() map[string]bool { + return mergeFlagSets(globalValueFlags) +} + // Subcommands returns the bd subcommand keys this package has flag // manifests for (e.g. "close", "mol pour"), in no particular order. func Subcommands() []string { diff --git a/internal/beadmeta/keys.go b/internal/beadmeta/keys.go index b2d73b2d96..32b80928df 100644 --- a/internal/beadmeta/keys.go +++ b/internal/beadmeta/keys.go @@ -61,8 +61,11 @@ const ( ControllerErrorClassMetadataKey = "gc.controller_error_class" ControllerErrorMetadataKey = "gc.controller_error" ControllerRetryableMetadataKey = "gc.controller_retryable" - CurrentRunIDMetadataKey = "gc.current_run_id" - CwdMetadataKey = "gc.cwd" + // CoordinatorOutcomeProducerDispositionMetadataKey holds the typed-close JSON + // envelope written by gc-outcome-close. + CoordinatorOutcomeProducerDispositionMetadataKey = "gc.coordinator_outcome.producer_disposition" + CurrentRunIDMetadataKey = "gc.current_run_id" + CwdMetadataKey = "gc.cwd" // AttachFencePendingMetadataKey marks a fenced attach's sub-DAG root // between speculative (deferred, non-runnable) creation and the CAS-last // epoch fence committing. Cleared on activation; a root still carrying it @@ -150,6 +153,7 @@ const ( ReasoningMetadataKey = "gc.reasoning" RequiredArtifactMetadataKey = "gc.required_artifact" RequiredArtifactsMetadataKey = "gc.required_artifacts" + ReviewGateMetadataKey = "gc.review_gate" RetryCountMetadataKey = "gc.retry_count" RetryFromMetadataKey = "gc.retry_from" RetrySessionRecycledMetadataKey = "gc.retry_session_recycled" @@ -314,6 +318,7 @@ var KnownMetadataKeys = []string{ ControllerErrorClassMetadataKey, ControllerErrorMetadataKey, ControllerRetryableMetadataKey, + CoordinatorOutcomeProducerDispositionMetadataKey, CurrentRunIDMetadataKey, CwdMetadataKey, AttachFencePendingMetadataKey, @@ -398,6 +403,7 @@ var KnownMetadataKeys = []string{ ReasoningMetadataKey, RequiredArtifactMetadataKey, RequiredArtifactsMetadataKey, + ReviewGateMetadataKey, RetryCountMetadataKey, RetryFromMetadataKey, RetrySessionRecycledMetadataKey, diff --git a/internal/beadmeta/values.go b/internal/beadmeta/values.go index a5957d4eb1..2df6672caa 100644 --- a/internal/beadmeta/values.go +++ b/internal/beadmeta/values.go @@ -57,6 +57,16 @@ const ( OutcomeMissingRoot = "missing_root" ) +// Values of the CoordinatorOutcomeProducerDispositionMetadataKey typed-close +// envelope. Producer values remain open-world configuration. +const ( + CoordinatorOutcomeContractVersion = 1 + CoordinatorDispositionDeliverable = "deliverable" + CoordinatorDispositionNonDeliverable = "non-deliverable" + CoordinatorPassingVerdictReview = "review_verdict" + CoordinatorPassingVerdictEvidence = "evidence.reviewer_verdict" +) + // Values of WorkOutcomeMetadataKey ("gc.work_outcome"), the typed work-record // close disposition (ADR-0009). Deliberately disjoint from the control-plane // OutcomeMetadataKey vocabulary above so the two never collide on one key. Only diff --git a/internal/beads/native_dolt_store.go b/internal/beads/native_dolt_store.go index 5cc5e82620..a131d38c17 100644 --- a/internal/beads/native_dolt_store.go +++ b/internal/beads/native_dolt_store.go @@ -2,7 +2,6 @@ package beads import ( "context" - "database/sql" "encoding/json" "errors" "fmt" @@ -12,108 +11,9 @@ import ( "sync" "time" - "github.com/go-sql-driver/mysql" beadslib "github.com/steveyegge/beads" ) -// rawDBGetter matches beadslib's internal storage.RawDBAccessor without -// importing its internal package. DoltStore satisfies this interface. -type rawDBGetter interface { - DB() *sql.DB -} - -// idDefaultRepairTables lists the char(36) id columns whose DEFAULT (uuid()) -// some Dolt versions silently strip from the expression default that beads -// migrations add via PREPARE/EXECUTE. Without the default, beadslib INSERTs -// that never supply id fail with "Field 'id' doesn't have a default value": -// - dependencies: DepAdd (migration 0043) -// - events / wisp_events: RecordEventInTable, reached when gc stamps -// metadata (e.g. gc.routed_to during sling) on a non-ephemeral bead. -var idDefaultRepairTables = []string{"dependencies", "events", "wisp_events"} - -// repairIDDefault ensures table.id has DEFAULT (uuid()). It is idempotent and -// tolerant of an absent table (e.g. wisp_events): it only issues the ALTER when -// the id column exists without a default. -// -// The probe is a single-table SHOW COLUMNS, not INFORMATION_SCHEMA.COLUMNS: -// Dolt does not push the WHERE predicate into INFORMATION_SCHEMA, so the old -// probe was a full catalog scan — cheap once, but it runs per store open per -// repair table, and a fleet of concurrent gc/bd sessions firing it several -// times a second pegged the shared Dolt server's CPU. SHOW COLUMNS returns the -// Default cell directly, so one cheap statement replaces the scan. -func repairIDDefault(db *sql.DB, table string) error { - // 'id' contains no LIKE wildcards, but Field is still compared exactly - // (matching upstream beads' SHOW COLUMNS probes) rather than trusting LIKE. - //nolint:gosec // G201: table is drawn from idDefaultRepairTables, hardcoded constants. - rows, err := db.Query(fmt.Sprintf("SHOW COLUMNS FROM `%s` LIKE 'id'", table)) - if err != nil { - if isTableNotExistError(err) { - return nil - } - return fmt.Errorf("checking %s.id default: %w", table, err) - } - defer func() { _ = rows.Close() }() - - cols, err := rows.Columns() - if err != nil { - return fmt.Errorf("checking %s.id default: %w", table, err) - } - defaultIdx := -1 - for i, col := range cols { - if strings.EqualFold(col, "Default") { - defaultIdx = i - break - } - } - if defaultIdx < 0 { - return fmt.Errorf("checking %s.id default: SHOW COLUMNS returned no Default column (got %v)", table, cols) - } - - idFound, withDefault := false, false - cells := make([]sql.RawBytes, len(cols)) - dest := make([]any, len(cols)) - for i := range cells { - dest[i] = &cells[i] - } - for rows.Next() { - if err := rows.Scan(dest...); err != nil { - return fmt.Errorf("checking %s.id default: %w", table, err) - } - if len(cells) > 0 && string(cells[0]) == "id" { - idFound = true - withDefault = cells[defaultIdx] != nil - break - } - } - if err := rows.Err(); err != nil { - return fmt.Errorf("checking %s.id default: %w", table, err) - } - if !idFound || withDefault { - // Column absent, or the default is already present. - return nil - } - //nolint:gosec // G201: table is drawn from idDefaultRepairTables, hardcoded constants. - if _, err := db.Exec(fmt.Sprintf("ALTER TABLE `%s` MODIFY COLUMN `id` char(36) NOT NULL DEFAULT (uuid())", table)); err != nil { - return fmt.Errorf("repairing %s.id default: %w", table, err) - } - return nil -} - -// isTableNotExistError reports whether err is the MySQL/Dolt "table doesn't -// exist" error (1146). SHOW COLUMNS errors on a missing table where the old -// INFORMATION_SCHEMA probe returned zero rows; an absent repair table (e.g. -// wisp_events on an older schema) is not an error. -func isTableNotExistError(err error) bool { - var mysqlErr *mysql.MySQLError - if errors.As(err, &mysqlErr) { - return mysqlErr.Number == 1146 - } - // The embedded Dolt driver surfaces the same condition without the - // go-sql-driver error type; match Dolt's message shape. - msg := strings.ToLower(err.Error()) - return strings.Contains(msg, "table not found") || strings.Contains(msg, "doesn't exist") -} - const nativeDoltStoreActor = "gascity" // nativeDoltOpenReadyStatuses lists the upstream bd statuses Ready() queries @@ -373,7 +273,7 @@ func OpenNativeDoltStoreAt(ctx context.Context, scopeRoot string, env map[string func newNativeDoltStoreAt(parent context.Context, scopeRoot string, env map[string]string, opts ...NativeDoltStoreOption) (*NativeDoltStore, error) { ctx, cancel := nativeDoltOperationContext(parent) defer cancel() - storage, prefix, err := openAndRepairNativeStorage(ctx, scopeRoot, env, true) + storage, prefix, err := openNativeStorage(ctx, scopeRoot, env, true) if err != nil { return nil, err } @@ -396,17 +296,15 @@ func newNativeDoltStoreAt(parent context.Context, scopeRoot string, env map[stri // caller that has re-resolved the CURRENT managed Dolt env (fresh port) passes // it here to get a fresh handle bound to the live server. func OpenNativeStorage(ctx context.Context, scopeRoot string, env map[string]string) (NativeStorage, error) { - storage, _, err := openAndRepairNativeStorage(ctx, scopeRoot, env, false) + storage, _, err := openNativeStorage(ctx, scopeRoot, env, false) return storage, err } -// openAndRepairNativeStorage projects the scoped Dolt env, opens the -// best-available native storage, repairs the id-default columns some Dolt -// versions strip, and (when readPrefix) reads the configured issue prefix while -// the env is still projected. It is shared by the initial open and by the -// read-path reconnect that recovers from a managed-Dolt hard-kill/rebind, so -// both establish an identically configured connection. -func openAndRepairNativeStorage(ctx context.Context, scopeRoot string, env map[string]string, readPrefix bool) (beadslib.Storage, string, error) { +// openNativeStorage projects the scoped Dolt env, opens the best-available +// native storage, and (when readPrefix) reads the configured issue prefix while +// the env is still projected. It is shared by the initial open and the +// read-path reconnect that recovers from a managed-Dolt hard-kill/rebind. +func openNativeStorage(ctx context.Context, scopeRoot string, env map[string]string, readPrefix bool) (beadslib.Storage, string, error) { restoreEnv, err := withNativeDoltOpenEnv(env) if err != nil { return nil, "", err @@ -424,15 +322,6 @@ func openAndRepairNativeStorage(ctx context.Context, scopeRoot string, env map[s return nil, "", fmt.Errorf("reading native issue prefix: %w", err) } } - if accessor, ok := storage.(rawDBGetter); ok { - for _, table := range idDefaultRepairTables { - if repairErr := repairIDDefault(accessor.DB(), table); repairErr != nil { - // Log but don't fail: the error will surface on the first - // DepAdd / event-recording write against the affected table. - fmt.Fprintf(os.Stderr, "WARNING: gc beads: %v\n", repairErr) - } - } - } return storage, prefix, nil } diff --git a/internal/beads/native_dolt_store_integration_test.go b/internal/beads/native_dolt_store_integration_test.go index 1baf20d9fb..aac6d5b737 100644 --- a/internal/beads/native_dolt_store_integration_test.go +++ b/internal/beads/native_dolt_store_integration_test.go @@ -58,62 +58,6 @@ func TestNativeDoltStoreRegularUpdateEventRecording(t *testing.T) { } } -// TestNativeDoltStoreEventsIDDefaultRepair reproduces the live-DB regression -// where Dolt stripped DEFAULT (uuid()) from events.id: RecordEventInTable -// (reached via SetMetadata on a non-ephemeral bead) then fails because the -// upstream INSERT omits the id column. It proves repairIDDefault restores the -// default so the write succeeds — the same self-heal gc applies at store open. -func TestNativeDoltStoreEventsIDDefaultRepair(t *testing.T) { - ctx := context.Background() - storage, err := beadslib.OpenBestAvailable(ctx, filepath.Join(t.TempDir(), ".beads")) - if err != nil { - t.Skipf("upstream native beads storage unavailable: %v", err) - } - t.Cleanup(func() { - if err := storage.Close(); err != nil { - t.Fatalf("close upstream storage: %v", err) - } - }) - if err := storage.SetConfig(ctx, "issue_prefix", "gc"); err != nil { - t.Fatalf("set issue prefix: %v", err) - } - accessor, ok := storage.(rawDBGetter) - if !ok { - t.Skip("storage does not expose a raw DB") - } - db := accessor.DB() - store := newNativeDoltStoreWithStorageAndPrefix(storage, "events-default-repair", "gc") - - // Create while the default is intact (Create itself records an event). - bead, err := store.Create(Bead{Title: "events id default repair bead"}) - if err != nil { - t.Fatalf("Create bead: %v", err) - } - - // Reproduce the regression: strip the DEFAULT from events.id. - if _, err := db.Exec("ALTER TABLE `events` MODIFY COLUMN `id` char(36) NOT NULL"); err != nil { - t.Fatalf("strip events.id default: %v", err) - } - if err := store.SetMetadata(bead.ID, "gc.routed_to", "gascity/builder"); err == nil { - t.Fatalf("SetMetadata succeeded with events.id default stripped, want failure") - } - - // Repair restores the default; the same write then succeeds. - if err := repairIDDefault(db, "events"); err != nil { - t.Fatalf("repairIDDefault(events): %v", err) - } - if err := store.SetMetadata(bead.ID, "gc.routed_to", "gascity/builder"); err != nil { - t.Fatalf("SetMetadata after repair: %v", err) - } - got, err := store.Get(bead.ID) - if err != nil { - t.Fatalf("Get after repair: %v", err) - } - if got.Metadata["gc.routed_to"] != "gascity/builder" { - t.Fatalf("Metadata[gc.routed_to] = %q, want %q", got.Metadata["gc.routed_to"], "gascity/builder") - } -} - // TestNativeDoltStoreEphemeralMailSend verifies that creating an ephemeral message // bead (the gc mail send code path) succeeds through the upstream beads library. // @@ -178,9 +122,29 @@ func TestNativeDoltStoreEphemeralMailSend(t *testing.T) { } } -func TestNativeDoltStoreRealBackendRoundTrip(t *testing.T) { +// testRawDBGetter matches beadslib's internal storage.RawDBAccessor without +// bringing that implementation detail into production code. +type testRawDBGetter interface { + DB() *sql.DB +} + +// TestNativeDoltStoreOpenPreservesMissingIDDefaults verifies the v59 contract: +// dependencies.id, events.id, and wisp_events.id intentionally have no server +// default. Opening a native store must not mutate that schema, and normal +// writes must provide their IDs explicitly. +func TestNativeDoltStoreOpenPreservesMissingIDDefaults(t *testing.T) { ctx := context.Background() - storage, err := beadslib.OpenBestAvailable(ctx, filepath.Join(t.TempDir(), ".beads")) + scopeRoot := t.TempDir() + port := startTestDoltServer(t) + beadsDir := filepath.Join(scopeRoot, ".beads") + if err := os.MkdirAll(beadsDir, 0o755); err != nil { + t.Fatalf("create .beads directory: %v", err) + } + metadata := fmt.Sprintf(`{"backend":"dolt","database":"beads","dolt_mode":"server","dolt_server_host":"127.0.0.1","dolt_server_port":%d}`, port) + if err := os.WriteFile(filepath.Join(beadsDir, "metadata.json"), []byte(metadata), 0o644); err != nil { + t.Fatalf("write metadata.json: %v", err) + } + storage, err := beadslib.OpenBestAvailable(ctx, beadsDir) if err != nil { t.Skipf("upstream native beads storage unavailable: %v", err) } @@ -192,51 +156,65 @@ func TestNativeDoltStoreRealBackendRoundTrip(t *testing.T) { if err := storage.SetConfig(ctx, "issue_prefix", "gc"); err != nil { t.Fatalf("set issue prefix: %v", err) } - store := newNativeDoltStoreWithStorageAndPrefix(storage, "native-integration", "gc") + accessor, ok := storage.(testRawDBGetter) + if !ok { + t.Skip("storage does not expose a raw DB") + } + db := accessor.DB() + for _, table := range []string{"dependencies", "events", "wisp_events"} { + if _, err := db.Exec("ALTER TABLE `" + table + "` MODIFY COLUMN `id` char(36) NOT NULL"); err != nil { + t.Fatalf("strip %s.id default: %v", table, err) + } + assertNativeIDDefaultAbsent(t, db, table) + } - parent, err := store.Create(Bead{Title: "real native parent"}) + store, err := newNativeDoltStoreAt(ctx, scopeRoot, nil) if err != nil { - t.Fatalf("Create parent: %v", err) + t.Fatalf("newNativeDoltStoreAt: %v", err) } - blocker, err := store.Create(Bead{Title: "real native blocker"}) - if err != nil { - t.Fatalf("Create blocker: %v", err) + for _, table := range []string{"dependencies", "events", "wisp_events"} { + assertNativeIDDefaultAbsent(t, db, table) } - child, err := store.Create(Bead{ - Title: "real native child", - ParentID: parent.ID, - Needs: []string{"blocks:" + blocker.ID}, - }) + + issue, err := store.Create(Bead{Title: "missing-default issue"}) if err != nil { - t.Fatalf("Create child: %v", err) + t.Fatalf("Create issue: %v", err) } - got, err := store.Get(child.ID) + dependsOn, err := store.Create(Bead{Title: "missing-default dependency"}) if err != nil { - t.Fatalf("Get child: %v", err) + t.Fatalf("Create dependency target: %v", err) } - if got.ParentID != parent.ID { - t.Fatalf("ParentID = %q, want %q", got.ParentID, parent.ID) + if err := store.DepAdd(issue.ID, dependsOn.ID, "blocks"); err != nil { + t.Fatalf("DepAdd: %v", err) } - assertNativeDependency(t, got.Dependencies, child.ID, blocker.ID, "blocks") - if err := store.Close(child.ID); err != nil { - t.Fatalf("Close child: %v", err) + if err := store.SetMetadata(issue.ID, "gc.routed_to", "gascity/builder"); err != nil { + t.Fatalf("SetMetadata (events write): %v", err) } - closed, err := store.Get(child.ID) - if err != nil { - t.Fatalf("Get closed child: %v", err) + if _, err := store.Create(Bead{ + Title: "missing-default wisp", + Type: "message", + Assignee: "builder", + Ephemeral: true, + }); err != nil { + t.Fatalf("Create ephemeral bead (wisp_events write): %v", err) } - if closed.Status != "closed" { - t.Fatalf("Status = %q, want closed", closed.Status) +} + +func assertNativeIDDefaultAbsent(t *testing.T, db *sql.DB, table string) { + t.Helper() + var field, colType, nullable, key, extra string + var defaultValue any + if err := db.QueryRow("SHOW COLUMNS FROM `"+table+"` LIKE 'id'").Scan(&field, &colType, &nullable, &key, &defaultValue, &extra); err != nil { + t.Fatalf("SHOW COLUMNS FROM %s: %v", table, err) } - if _, err := store.Get("gc-missing"); !errors.Is(err, ErrNotFound) { - t.Fatalf("Get missing error = %v, want ErrNotFound", err) + if defaultValue != nil { + t.Fatalf("%s.id default = %v, want absent", table, defaultValue) } } -// startTestDoltServer launches a throwaway dolt sql-server in a temp data dir -// and returns a *sql.DB connected to a fresh database on it. Skips the test -// when the dolt binary is unavailable. -func startTestDoltServer(t *testing.T) *sql.DB { +// startTestDoltServer launches a throwaway server for tests that need the raw +// SQL accessor exposed by upstream's server-mode Dolt store. +func startTestDoltServer(t *testing.T) int { t.Helper() doltBin, err := exec.LookPath("dolt") if err != nil { @@ -248,7 +226,9 @@ func startTestDoltServer(t *testing.T) *sql.DB { t.Fatalf("pick free port: %v", err) } port := lis.Addr().(*net.TCPAddr).Port - _ = lis.Close() + if err := lis.Close(); err != nil { + t.Fatalf("release test port: %v", err) + } dataDir := t.TempDir() cmd := exec.Command(doltBin, "sql-server", "--host", "127.0.0.1", "--port", strconv.Itoa(port), "--data-dir", dataDir) @@ -261,11 +241,11 @@ func startTestDoltServer(t *testing.T) *sql.DB { _, _ = cmd.Process.Wait() }) - dsn := fmt.Sprintf("root@tcp(127.0.0.1:%d)/", port) - db, err := sql.Open("mysql", dsn) + db, err := sql.Open("mysql", fmt.Sprintf("root@tcp(127.0.0.1:%d)/", port)) if err != nil { t.Fatalf("open dolt connection: %v", err) } + t.Cleanup(func() { _ = db.Close() }) deadline := time.Now().Add(30 * time.Second) for { if err := db.Ping(); err == nil { @@ -276,69 +256,63 @@ func startTestDoltServer(t *testing.T) *sql.DB { } time.Sleep(200 * time.Millisecond) } - if _, err := db.Exec("CREATE DATABASE repairtest"); err != nil { - t.Fatalf("create test database: %v", err) + if _, err := db.Exec("CREATE DATABASE beads"); err != nil { + t.Fatalf("create beads database: %v", err) } - _ = db.Close() + return port +} - db, err = sql.Open("mysql", dsn+"repairtest") +func TestNativeDoltStoreRealBackendRoundTrip(t *testing.T) { + ctx := context.Background() + storage, err := beadslib.OpenBestAvailable(ctx, filepath.Join(t.TempDir(), ".beads")) if err != nil { - t.Fatalf("open test database: %v", err) + t.Skipf("upstream native beads storage unavailable: %v", err) } - t.Cleanup(func() { _ = db.Close() }) - return db -} - -// TestRepairIDDefaultAgainstDoltServer exercises the SHOW COLUMNS-based probe -// end-to-end against a real dolt sql-server (the same wire protocol the live -// fleet uses): a stripped DEFAULT is detected and repaired, an intact DEFAULT -// is left alone, and an absent table is not an error. This covers the probe -// rewrite that replaced the per-open INFORMATION_SCHEMA.COLUMNS catalog scan. -func TestRepairIDDefaultAgainstDoltServer(t *testing.T) { - db := startTestDoltServer(t) - - showIDDefault := func(table string) any { - var field, colType, null, key, extra string - var def any - row := db.QueryRow(fmt.Sprintf("SHOW COLUMNS FROM `%s` LIKE 'id'", table)) - if err := row.Scan(&field, &colType, &null, &key, &def, &extra); err != nil { - t.Fatalf("SHOW COLUMNS FROM %s: %v", table, err) + t.Cleanup(func() { + if err := storage.Close(); err != nil { + t.Fatalf("close upstream storage: %v", err) } - return def + }) + if err := storage.SetConfig(ctx, "issue_prefix", "gc"); err != nil { + t.Fatalf("set issue prefix: %v", err) } + store := newNativeDoltStoreWithStorageAndPrefix(storage, "native-integration", "gc") - // Stripped default: probe detects it and the ALTER restores it. - if _, err := db.Exec("CREATE TABLE events (id char(36) NOT NULL, note text)"); err != nil { - t.Fatalf("create events: %v", err) + parent, err := store.Create(Bead{Title: "real native parent"}) + if err != nil { + t.Fatalf("Create parent: %v", err) } - if err := repairIDDefault(db, "events"); err != nil { - t.Fatalf("repairIDDefault(events): %v", err) + blocker, err := store.Create(Bead{Title: "real native blocker"}) + if err != nil { + t.Fatalf("Create blocker: %v", err) } - if def := showIDDefault("events"); def == nil { - t.Fatal("events.id Default still NULL after repair, want (uuid())") + child, err := store.Create(Bead{ + Title: "real native child", + ParentID: parent.ID, + Needs: []string{"blocks:" + blocker.ID}, + }) + if err != nil { + t.Fatalf("Create child: %v", err) } - - // Intact default: repair is a no-op and must not error. - if _, err := db.Exec("CREATE TABLE dependencies (id char(36) NOT NULL DEFAULT (uuid()), note text)"); err != nil { - t.Fatalf("create dependencies: %v", err) + got, err := store.Get(child.ID) + if err != nil { + t.Fatalf("Get child: %v", err) } - if err := repairIDDefault(db, "dependencies"); err != nil { - t.Fatalf("repairIDDefault(dependencies) with intact default: %v", err) + if got.ParentID != parent.ID { + t.Fatalf("ParentID = %q, want %q", got.ParentID, parent.ID) } - if def := showIDDefault("dependencies"); def == nil { - t.Fatal("dependencies.id Default = NULL after no-op repair, want (uuid())") + assertNativeDependency(t, got.Dependencies, child.ID, blocker.ID, "blocks") + if err := store.Close(child.ID); err != nil { + t.Fatalf("Close child: %v", err) } - - // Absent table (e.g. wisp_events on an older schema): tolerated, not an error. - if err := repairIDDefault(db, "wisp_events"); err != nil { - t.Fatalf("repairIDDefault(wisp_events) on absent table: %v", err) + closed, err := store.Get(child.ID) + if err != nil { + t.Fatalf("Get closed child: %v", err) } - - // Table without an id column: nothing to repair, no error. - if _, err := db.Exec("CREATE TABLE noid (pk int PRIMARY KEY)"); err != nil { - t.Fatalf("create noid: %v", err) + if closed.Status != "closed" { + t.Fatalf("Status = %q, want closed", closed.Status) } - if err := repairIDDefault(db, "noid"); err != nil { - t.Fatalf("repairIDDefault(noid) without id column: %v", err) + if _, err := store.Get("gc-missing"); !errors.Is(err, ErrNotFound) { + t.Fatalf("Get missing error = %v, want ErrNotFound", err) } } diff --git a/internal/bootstrap/packs/core/assets/scripts/renudge-stale-human-gates.sh b/internal/bootstrap/packs/core/assets/scripts/renudge-stale-human-gates.sh index 674a2939bc..e4f6c6c087 100755 --- a/internal/bootstrap/packs/core/assets/scripts/renudge-stale-human-gates.sh +++ b/internal/bootstrap/packs/core/assets/scripts/renudge-stale-human-gates.sh @@ -135,6 +135,15 @@ fi STATE="$(cat "$STATE_FILE" 2>/dev/null || true)" echo "$STATE" | jq -e 'type == "object"' >/dev/null 2>&1 || STATE='{}' +# Atomic write of $STATE to disk: temp file in the same dir, then rename. +# Called after EVERY successful send (not just once at exit) so a process +# death mid-sweep loses at most the gate in flight, never the whole ledger. +write_state() { + __write_state_tmp="$(mktemp "$PACK_STATE_DIR/.renudge-stale-human-gates-state.XXXXXX")" + printf '%s\n' "$STATE" > "$__write_state_tmp" + mv -f "$__write_state_tmp" "$STATE_FILE" +} + RENUDGED=0 FAILED=0 while IFS= read -r scope; do @@ -216,6 +225,7 @@ Resolve with: gc bd gate resolve $gate_id" # undeliverable one surfaces and retries next sweep. if gc mail send "$ADDRESSEE" -s "$SUBJECT" -m "$BODY" --notify >/dev/null 2>&1; then STATE="$(echo "$STATE" | jq --arg k "$gate_id" --arg now "$NOW_ISO" '.[$k] = $now')" + write_state RENUDGED=$((RENUDGED + 1)) else echo "renudge-stale-human-gates: FAILED to re-notify addressee '$ADDRESSEE' of stale human gate $gate_id (will retry next sweep)" >&2 @@ -231,10 +241,7 @@ RETENTION_S="$(duration_to_seconds "$RETENTION")" STATE="$(echo "$STATE" | jq --argjson keep "$RETENTION_S" \ 'with_entries(select((now - (.value | fromdateiso8601)) <= $keep))')" || true -# Atomic write: temp file in the same dir, then rename. -TMP="$(mktemp "$PACK_STATE_DIR/.renudge-stale-human-gates-state.XXXXXX")" -printf '%s\n' "$STATE" > "$TMP" -mv -f "$TMP" "$STATE_FILE" +write_state if [ "$RENUDGED" -gt 0 ]; then echo "renudge-stale-human-gates: re-notified $RENUDGED stale human gate addressee(s)" diff --git a/internal/bootstrap/packs/core/orders/order-tracking-sweep.toml b/internal/bootstrap/packs/core/orders/order-tracking-sweep.toml index 9a9b18e6b5..c662efc5bc 100644 --- a/internal/bootstrap/packs/core/orders/order-tracking-sweep.toml +++ b/internal/bootstrap/packs/core/orders/order-tracking-sweep.toml @@ -6,4 +6,4 @@ description = "Close stale order-tracking beads and prune expired tracking history" trigger = "cooldown" interval = "1m" -exec = "gc order sweep-tracking --stale-after 10m --quiet" +exec = "gc order sweep-tracking --stale-after 10m --quiet --confirm" diff --git a/internal/convergence/condition.go b/internal/convergence/condition.go index c15f6cb3fc..cf74aeef19 100644 --- a/internal/convergence/condition.go +++ b/internal/convergence/condition.go @@ -13,6 +13,7 @@ import ( "unicode/utf8" "github.com/gastownhall/gascity/internal/citylayout" + "github.com/gastownhall/gascity/internal/gchome" "github.com/gastownhall/gascity/internal/pathutil" ) @@ -24,6 +25,13 @@ const ( textFileBusyRetryDelay = 25 * time.Millisecond ) +// conditionGCHome resolves the gc state directory for gate subprocesses. Gate +// HOME is intentionally sandboxed to the city, so it cannot also be used for +// gc's machine-level cache and registry state. +func conditionGCHome() string { + return gchome.ResolveReadOnly().Path() +} + // conditionPATH resolves the tool directories gate scripts actually need. // This keeps the env narrow while ensuring gate scripts use the same bd/gc // binaries as the running city instead of whatever older copy happens to live @@ -90,6 +98,7 @@ func (ce ConditionEnv) Environ() []string { env := []string{ "PATH=" + conditionPATH(), "HOME=" + home, + "GC_HOME=" + conditionGCHome(), "TMPDIR=" + os.TempDir(), "BEADS_DIR=" + filepath.Join(storePath, ".beads"), "GC_BEAD_ID=" + ce.BeadID, diff --git a/internal/convergence/condition_test.go b/internal/convergence/condition_test.go index 2a3fcbdd39..a62c679ef1 100644 --- a/internal/convergence/condition_test.go +++ b/internal/convergence/condition_test.go @@ -9,10 +9,13 @@ import ( "testing" "time" + "github.com/gastownhall/gascity/internal/gchome" "github.com/gastownhall/gascity/internal/testutil" ) func TestConditionEnvEnviron(t *testing.T) { + t.Setenv("GC_HOME", "/operator/gc-home") + env := ConditionEnv{ BeadID: "bead-123", Iteration: 3, @@ -41,6 +44,7 @@ func TestConditionEnvEnviron(t *testing.T) { // Required vars. checks := map[string]string{ "PATH": conditionPATH(), + "GC_HOME": "/operator/gc-home", "BEADS_DIR": "/home/test/city/.beads", "GC_BEAD_ID": "bead-123", "GC_ITERATION": "3", @@ -79,6 +83,18 @@ func TestConditionEnvEnviron(t *testing.T) { } } +func TestConditionGCHomeFallbackIsNotSharedTempDir(t *testing.T) { + t.Setenv("GC_HOME", "") + + got := conditionGCHome() + if got == filepath.Join(os.TempDir(), ".gc") { + t.Fatalf("conditionGCHome() = %q, must not be the shared world-writable temp home (gastownhall/gascity#3506)", got) + } + if want := gchome.ResolveReadOnly().Path(); got != want { + t.Fatalf("conditionGCHome() = %q, want canonical gchome resolution %q", got, want) + } +} + func TestConditionEnvEnvironOptionalEmpty(t *testing.T) { env := ConditionEnv{ BeadID: "bead-789", diff --git a/internal/dispatch/control.go b/internal/dispatch/control.go index d699d09a91..d37fe74848 100644 --- a/internal/dispatch/control.go +++ b/internal/dispatch/control.go @@ -463,6 +463,9 @@ func IsTransientControllerError(err error) bool { "database is locked", "database table is locked", "sqlite_busy", + // A workflow root may remain blocked briefly while sibling work closes. + // Retrying preserves the open finalize bead for the next serve cycle. + "cannot close blocked issue", // bd's client-side Dolt breaker fails fast while the server is down. // These errors are recoverable, so a long-running control dispatcher // must keep sweeping rather than exit permanently during the outage. diff --git a/internal/dispatch/control_test.go b/internal/dispatch/control_test.go index ddd48ede54..323217b17f 100644 --- a/internal/dispatch/control_test.go +++ b/internal/dispatch/control_test.go @@ -713,6 +713,59 @@ func TestProcessRetryControlRetriesInvalidWorkerResultContract(t *testing.T) { } } +// TestProcessRetryControlFoldsTypedCoordinatorOutcomeWithoutRetry reproduces +// gc-e2xqk end to end: a typed deliverable close must not mint attempt 2. +func TestProcessRetryControlFoldsTypedCoordinatorOutcomeWithoutRetry(t *testing.T) { + t.Parallel() + store := beads.NewMemStore() + + root := mustCreate(t, store, beads.Bead{ + Title: "workflow", + Metadata: map[string]string{"gc.kind": "workflow"}, + }) + control := mustCreate(t, store, beads.Bead{ + Title: "review", + Metadata: map[string]string{ + "gc.kind": "retry", + "gc.root_bead_id": root.ID, + "gc.step_ref": "mol-test.review", + "gc.step_id": "review", + "gc.max_attempts": "3", + "gc.on_exhausted": "hard_fail", + "gc.source_step_spec": `{"id":"review","title":"Review","type":"task","retry":{"max_attempts":3}}`, + "gc.control_epoch": "1", + }, + }) + attempt1 := mustCreate(t, store, beads.Bead{ + Title: "review attempt 1", + Metadata: map[string]string{ + "gc.root_bead_id": root.ID, + "gc.step_ref": "mol-test.review.attempt.1", + "gc.attempt": "1", + "gc.outcome.producer": "formula-step", + }, + }) + // gc-outcome-close records work_id = the closed bead's own ID. + disposition := fmt.Sprintf(`{"contract_version":1,"disposition":"deliverable","work_id":%q,"recorded_by":"formula-step","reason":"done","producer":"formula-step"}`, attempt1.ID) + if err := store.SetMetadata(attempt1.ID, "gc.coordinator_outcome.producer_disposition", disposition); err != nil { + t.Fatalf("set producer_disposition: %v", err) + } + mustClose(t, store, attempt1.ID) + mustDep(t, store, control.ID, attempt1.ID, "blocks") + + result, err := processRetryControl(store, mustGet(t, store, control.ID), ProcessOptions{}) + if err != nil { + t.Fatalf("processRetryControl: %v", err) + } + if !result.Processed || result.Action != "pass" { + t.Fatalf("result = %+v, want processed pass (no spurious retry)", result) + } + after := mustGet(t, store, control.ID) + if after.Status != "closed" || after.Metadata["gc.outcome"] != "pass" { + t.Fatalf("control = status %q outcome %q, want closed/pass", after.Status, after.Metadata["gc.outcome"]) + } +} + func TestProcessRetryControlClosesEnclosingScopeOnFailure(t *testing.T) { t.Parallel() store := beads.NewMemStore() @@ -1643,6 +1696,7 @@ func TestIsTransientControllerError(t *testing.T) { {name: "dolt breaker open", err: errors.New("Error: failed to open database: dolt circuit breaker is open: server appears down, failing fast (cooldown 5s)"), want: true}, {name: "dolt breaker failing fast", err: errors.New(`querying control work for fixture/core.control-dispatcher: running work query "bd ready": exit status 1: server appears down, failing fast (cooldown 5s)`), want: true}, {name: "dolt server unreachable", err: errors.New("begin read tx: dolt server unreachable"), want: true}, + {name: "workflow root close blocked", err: errors.New("gsp-p68ch6: completing workflow head: updating bead \"gsp-p68ch6\": exit status 1: cannot close blocked issue: gsp-p68ch6 is blocked by [gsp-yl7fpr]"), want: true}, {name: "non work query sigterm", err: errors.New("starting provider: exit status 143: Terminated"), want: false}, {name: "bad step spec", err: errors.New("deserializing step spec: invalid character 'n'"), want: false}, } diff --git a/internal/dispatch/retry.go b/internal/dispatch/retry.go index 71c891874a..e5790fd46f 100644 --- a/internal/dispatch/retry.go +++ b/internal/dispatch/retry.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "os" "path/filepath" "strconv" @@ -268,8 +269,67 @@ type retryEvalResult struct { Reason string } +// typedDeliverableCloseFor reports whether subject carries a complete, strict +// gc-outcome-close deliverable envelope for itself. Producer names are open-world. +func typedDeliverableCloseFor(subject beads.Bead) bool { + raw := strings.TrimSpace(subject.Metadata[beadmeta.CoordinatorOutcomeProducerDispositionMetadataKey]) + if raw == "" { + return false + } + decoder := json.NewDecoder(strings.NewReader(raw)) + decoder.DisallowUnknownFields() + var envelope struct { + ContractVersion int `json:"contract_version"` + Disposition string `json:"disposition"` + WorkID string `json:"work_id"` + RecordedBy string `json:"recorded_by"` + Reason string `json:"reason"` + Producer *string `json:"producer"` + PassingVerdict string `json:"passing_verdict"` + } + if err := decoder.Decode(&envelope); err != nil { + return false + } + // Reject trailing data after the envelope: DisallowUnknownFields only guards the + // first object, so a valid envelope followed by more JSON or garbage must fail + // closed rather than forge a pass. + if err := decoder.Decode(new(json.RawMessage)); err != io.EOF { + return false + } + if envelope.Disposition != beadmeta.CoordinatorDispositionDeliverable { + return false + } + if envelope.ContractVersion != beadmeta.CoordinatorOutcomeContractVersion { + return false + } + if envelope.WorkID != subject.ID { + return false + } + if strings.TrimSpace(envelope.RecordedBy) == "" || strings.TrimSpace(envelope.Reason) == "" { + return false + } + if envelope.Producer == nil || strings.TrimSpace(*envelope.Producer) == "" { + return false + } + if envelope.PassingVerdict != "" { + switch envelope.PassingVerdict { + case beadmeta.CoordinatorPassingVerdictReview, beadmeta.CoordinatorPassingVerdictEvidence: + default: + return false + } + if subject.Metadata[beadmeta.ReviewGateMetadataKey] != "consumed" || + subject.Metadata[envelope.PassingVerdict] != beadmeta.OutcomePass { + return false + } + } + return true +} + func classifyRetryAttempt(subject beads.Bead) retryEvalResult { outcome := strings.TrimSpace(subject.Metadata[beadmeta.OutcomeMetadataKey]) + if outcome == "" && typedDeliverableCloseFor(subject) { + outcome = beadmeta.OutcomePass + } switch outcome { case beadmeta.OutcomePass: if strings.TrimSpace(subject.Metadata[beadmeta.FailureClassMetadataKey]) != "" || strings.TrimSpace(subject.Metadata[beadmeta.FailureReasonMetadataKey]) != "" { diff --git a/internal/dispatch/retry_test.go b/internal/dispatch/retry_test.go index 3ea3e5995d..46d62d8fe7 100644 --- a/internal/dispatch/retry_test.go +++ b/internal/dispatch/retry_test.go @@ -218,6 +218,173 @@ func TestClassifyRetryAttemptCanceledIsTerminalNonRetry(t *testing.T) { } } +// TestClassifyRetryAttemptConsumesTypedCoordinatorOutcome pins strict validation +// of the typed close that reproduces gc-e2xqk. +func TestClassifyRetryAttemptConsumesTypedCoordinatorOutcome(t *testing.T) { + t.Parallel() + + const attemptID = "gc-attempt1" + const validDeliverable = `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"formula-step"}` + + tests := []struct { + name string + metadata map[string]string + want retryEvalResult + }{ + { + name: "valid deliverable close folds as pass", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": validDeliverable, + "gc.outcome.producer": "formula-step", + }, + want: retryEvalResult{Outcome: "pass"}, + }, + { + name: "valid deliverable close with passing verdict folds as pass", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"formula-step","passing_verdict":"evidence.reviewer_verdict"}`, + "gc.review_gate": "consumed", + "evidence.reviewer_verdict": "pass", + }, + want: retryEvalResult{Outcome: "pass"}, + }, + { + name: "passing verdict requires consumed review gate", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"formula-step","passing_verdict":"evidence.reviewer_verdict"}`, + "gc.review_gate": "pass", + "evidence.reviewer_verdict": "pass", + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "passing verdict requires published pass", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"formula-step","passing_verdict":"review_verdict"}`, + "gc.review_gate": "consumed", + "review_verdict": "reject", + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "unsupported passing verdict stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"formula-step","passing_verdict":"surprise"}`, + "gc.review_gate": "consumed", + "surprise": "pass", + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "explicit gc.outcome takes precedence over typed close", + metadata: map[string]string{ + "gc.outcome": "pass", + "gc.coordinator_outcome.producer_disposition": validDeliverable, + }, + want: retryEvalResult{Outcome: "pass"}, + }, + { + name: "non-deliverable close stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"non-deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"obsolete"}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "deliverable with arbitrary producer folds as pass", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"novel-writer-42"}`, + }, + want: retryEvalResult{Outcome: "pass"}, + }, + { + name: "deliverable absent producer stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped"}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "deliverable empty producer stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":""}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "deliverable empty recorded_by stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"","reason":"shipped","producer":"formula-step"}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "deliverable empty reason stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"","producer":"formula-step"}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "unknown envelope field stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"formula-step","surprise":"x"}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "deliverable with trailing data stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"formula-step"} {"junk":1}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "malformed json stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": "{not json", + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "wrong contract_version stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":2,"disposition":"deliverable","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped","producer":"formula-step"}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "foreign work_id stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"deliverable","work_id":"gc-someone-else","recorded_by":"tester","reason":"shipped","producer":"formula-step"}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "unknown disposition stays missing_outcome", + metadata: map[string]string{ + "gc.coordinator_outcome.producer_disposition": `{"contract_version":1,"disposition":"mystery","work_id":"gc-attempt1","recorded_by":"tester","reason":"shipped"}`, + }, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + { + name: "no typed outcome stays missing_outcome", + metadata: map[string]string{}, + want: retryEvalResult{Outcome: "transient", Reason: "missing_outcome"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + got := classifyRetryAttempt(beads.Bead{ID: attemptID, Metadata: tt.metadata}) + if got != tt.want { + t.Fatalf("classifyRetryAttempt() = %+v, want %+v", got, tt.want) + } + }) + } +} + func TestClassifyRetryAttemptWithPostconditionsRequiresArtifact(t *testing.T) { t.Parallel() diff --git a/internal/dispatch/runtime.go b/internal/dispatch/runtime.go index 0a0d1c6546..06c2934056 100644 --- a/internal/dispatch/runtime.go +++ b/internal/dispatch/runtime.go @@ -841,9 +841,22 @@ func processWorkflowFinalize(store beads.Store, bead beads.Bead, opts ProcessOpt } return ControlResult{}, recordWorkflowFinalizeError(store, bead.ID, fmt.Errorf("%s: completing workflow head: %w", rootID, err)) } + // Generated spec sidecars are topology records rather than executable + // members; preserve their established successful cleanup outcome before the + // remaining subtree is skipped. if _, err := sourceworkflow.CloseSpecSidecarsForRoot(store, rootID, sourceworkflow.WorkflowSpecSidecarClosedReason); err != nil { return ControlResult{}, recordWorkflowFinalizeError(store, bead.ID, fmt.Errorf("%s: closing workflow spec sidecars: %w", rootID, err)) } + // A terminal root makes every still-open generated member non-executable. + // Close the remainder as one ordered, idempotent batch before completing + // the finalizer. This also repairs partially materialized workflows whose + // unused steps were never reached by ordinary dependency progression. + if _, err := molecule.CloseSubtreeWithMetadata(store, rootID, map[string]string{ + beadmeta.OutcomeMetadataKey: beadmeta.OutcomeSkipped, + "close_reason": sourceworkflow.WorkflowSkippedCloseReason, + }); err != nil { + return ControlResult{}, recordWorkflowFinalizeError(store, bead.ID, fmt.Errorf("%s: closing terminal workflow members: %w", rootID, err)) + } if outcome == beadmeta.OutcomePass { if err := closeSourceBeadChain(store, rootID, opts); err != nil { return ControlResult{}, recordWorkflowFinalizeError(store, bead.ID, fmt.Errorf("%s: closing source bead chain: %w", rootID, err)) diff --git a/internal/dispatch/runtime_test.go b/internal/dispatch/runtime_test.go index bb5b25e500..61faed0a84 100644 --- a/internal/dispatch/runtime_test.go +++ b/internal/dispatch/runtime_test.go @@ -2764,6 +2764,57 @@ func TestProcessWorkflowFinalizeClosesOpenSpecSidecars(t *testing.T) { } } +func TestProcessWorkflowFinalizeClosesRemainingGeneratedMembers(t *testing.T) { + t.Parallel() + + store := beads.NewMemStore() + workflow := mustCreateWorkflowBead(t, store, beads.Bead{ + Title: "workflow", + Type: "task", + Metadata: map[string]string{ + "gc.kind": "workflow", + "gc.formula_contract": "graph.v2", + }, + }) + remaining := mustCreateWorkflowBead(t, store, beads.Bead{ + Title: "partially materialized step that can no longer execute", + Type: "task", + Metadata: map[string]string{ + "gc.root_bead_id": workflow.ID, + "gc.step_ref": "unused", + }, + }) + finalizer := mustCreateWorkflowBead(t, store, beads.Bead{ + Title: "Finalize workflow", + Type: "task", + Metadata: map[string]string{ + "gc.kind": "workflow-finalize", + "gc.root_bead_id": workflow.ID, + }, + }) + mustDepAdd(t, store, workflow.ID, finalizer.ID, "blocks") + + result, err := ProcessControl(store, finalizer, ProcessOptions{}) + if err != nil { + t.Fatalf("ProcessControl(workflow-finalize): %v", err) + } + if !result.Processed || result.Action != "workflow-pass" { + t.Fatalf("workflow result = %+v, want processed workflow-pass", result) + } + + remainingAfter := mustGetBead(t, store, remaining.ID) + if remainingAfter.Status != "closed" { + t.Fatalf("remaining generated member status = %q, want closed", remainingAfter.Status) + } + if got := remainingAfter.Metadata["gc.outcome"]; got != "skipped" { + t.Fatalf("remaining generated member gc.outcome = %q, want skipped", got) + } + finalizerAfter := mustGetBead(t, store, finalizer.ID) + if got := finalizerAfter.Metadata["gc.outcome"]; got != "pass" { + t.Fatalf("finalizer gc.outcome = %q, want pass", got) + } +} + func TestProcessWorkflowFinalizeTreatsQuarantinedControlAsFailure(t *testing.T) { t.Parallel() diff --git a/internal/doctor/checks_order_firing.go b/internal/doctor/checks_order_firing.go index b109ec277d..51104d6677 100644 --- a/internal/doctor/checks_order_firing.go +++ b/internal/doctor/checks_order_firing.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strconv" "strings" + "sync" "time" "github.com/gastownhall/gascity/internal/citylayout" @@ -16,17 +17,46 @@ import ( ) const ( - orderFiringCurrentName = "order-firing-current" - orderFiringInspectHintFmt = "Inspect with: gc order check && gc order history %s" - orderFiringHistoryTimeout = 15 * time.Second + // orderFiringLastRunConcurrency caps the parallel order-run lookups. Each + // lookup is one bounded bd read; eight keeps the prefetch comfortably under + // the doctor's own timeout on large cities without stampeding the store. + orderFiringLastRunConcurrency = 8 + orderFiringCurrentName = "order-firing-current" + orderFiringInspectHintFmt = "Inspect with: gc order check && gc order history %s" + orderFiringHistoryTimeout = 15 * time.Second + // orderFiringTimeoutHint names the actual cause of a timeout here. It + // deliberately does NOT mention beads/Dolt connectivity: this check times + // out on read cost, not on reachability, and the old connectivity wording + // sent triage at a healthy data plane for a full cycle (ga-klv). + orderFiringTimeoutHint = "the city event log or order history is large; re-run the inspect commands bounded (gc order history --limit 20) and consider gc events compact" + // orderFiringEventTailLimit bounds the newest-first order.fired read. The + // check needs only each order's most recent firing, so it reads the tail + // of the live log rather than scanning it whole: on a busy city the active + // log reaches hundreds of megabytes and a full scan costs tens of seconds + // per read (measured: 36s against a 161MB/253k-line log), which alone + // blows the check budget above. The Since window prunes matches further; + // a firing outside both bounds is not lost — latestOrderFiredAtUsing falls + // through to the authoritative order-run lookup, and the never-fired + // disambiguation probe walks full history newest-first with early exit. + orderFiringEventTailLimit = 2000 ) -// OrderFiringCurrentLastRunFunc reports the newest persisted run time for an order. +// OrderFiringCurrentLastRunFunc reports the newest persisted run time for an +// order. Implementations MUST be safe for concurrent use: the check resolves +// the orders it cannot answer from the event log in parallel, because these +// lookups are store round-trips and running them serially is what pushes a +// busy city past the check budget (ga-klv). type OrderFiringCurrentLastRunFunc func(order orders.Order) (time.Time, error) // OrderFiringCurrentOption configures the scheduled-order freshness check. type OrderFiringCurrentOption func(*OrderFiringCurrentCheck) +// orderFiringEventReadFunc reads at most limit trailing events matching filter +// from the city event log, newest events last. A non-positive limit reads the +// whole log — the shape events.ReadFilteredTail already implements, and the +// reason the limit is load-bearing here. +type orderFiringEventReadFunc func(path string, filter events.Filter, limit int) ([]events.Event, error) + // WithOrderFiringCurrentLastRunFunc lets callers provide the same order-run // history source used by `gc order history` so doctor can classify manual runs. func WithOrderFiringCurrentLastRunFunc(fn OrderFiringCurrentLastRunFunc) OrderFiringCurrentOption { @@ -42,6 +72,7 @@ type OrderFiringCurrentCheck struct { clock func() time.Time lastRun OrderFiringCurrentLastRunFunc historyTimeout time.Duration + readEvents orderFiringEventReadFunc } // NewOrderFiringCurrentCheck creates a check for cron and cooldown order freshness. @@ -51,6 +82,7 @@ func NewOrderFiringCurrentCheck(cfg *config.City, cityPath string, opts ...Order cityPath: cityPath, clock: time.Now, historyTimeout: orderFiringHistoryTimeout, + readEvents: events.ReadFilteredTail, } for _, opt := range opts { opt(check) @@ -90,7 +122,7 @@ func (c *OrderFiringCurrentCheck) Run(ctx *CheckContext) *CheckResult { Name: c.Name(), Status: StatusError, Message: fmt.Sprintf("order history lookup timed out after %s", timeout), - FixHint: "check beads/Dolt connectivity, then rerun gc doctor", + FixHint: orderFiringTimeoutHint, } } } @@ -133,11 +165,6 @@ func (c *OrderFiringCurrentCheck) run(ctx *CheckContext) *CheckResult { // older than 3x the widest interval can change any verdict. The window is // semantically lossless for this check while pruning the read to // O(recent) instead of all recorded history (vc-89s). - type monitoredOrder struct { - order orders.Order - expected time.Duration - err error - } var monitored []monitoredOrder var maxExpected time.Duration for _, order := range allOrders { @@ -165,10 +192,13 @@ func (c *OrderFiringCurrentCheck) run(ctx *CheckContext) *CheckResult { if maxExpected > 0 { firedFilter.Since = now.Add(-3 * maxExpected) } - // Archive corruption degrades to skip+warning instead of failing the - // whole check — one truncated gzip masked the real verdict for days - // (vc-89s). Live-file errors still fail loudly. - firedEvents, firedWarnings, err := events.ReadFilteredWithWarnings(eventPath, firedFilter) + // The tail read is doubly bounded: at most orderFiringEventTailLimit + // newest matches, further pruned by the Since window above. It reads only + // the live file, so archive corruption cannot touch it; the reads that do + // span archives (the controller-start lookup and the never-fired probe + // below) degrade corruption to skip+warning instead of failing the whole + // check — one truncated gzip masked the real verdict for days (vc-89s). + firedEvents, err := c.readEvents(eventPath, firedFilter, orderFiringEventTailLimit) if err != nil { result.Status = StatusError result.Message = fmt.Sprintf("read order firing events: %v", err) @@ -180,7 +210,13 @@ func (c *OrderFiringCurrentCheck) run(ctx *CheckContext) *CheckResult { result.Message = fmt.Sprintf("read controller start events: %v", err) return result } - degraded := appendUniqueStrings(firedWarnings, startWarnings) + degraded := startWarnings + // Resolve every order-run lookup the loop below will need up front and in + // parallel: each is a store round-trip, and issued serially across the + // monitored orders they alone exceed the check budget (ga-klv). The + // pre-pass filters on the monitored slice the loop iterates, so the two + // cannot disagree on which orders need an authoritative lookup. + lastRunFor := c.prefetchedLastRunFunc(c.pendingLastRunOrders(monitored, firedEvents, now)) worst := StatusOK var firstNonOK string @@ -199,7 +235,7 @@ func (c *OrderFiringCurrentCheck) run(ctx *CheckContext) *CheckResult { blockingErrors++ continue } - lastFired, err := c.latestOrderFiredAt(firedEvents, order, mo.expected, now) + lastFired, err := c.latestOrderFiredAtUsing(lastRunFor, firedEvents, order, mo.expected, now) if err != nil { worst = worseStatus(worst, StatusError) result.Details = append(result.Details, fmt.Sprintf("%s: cannot read order history: %v", orderDisplayName(order), err)) @@ -649,21 +685,126 @@ func appendUniqueStrings(base, extra []string) []string { } func (c *OrderFiringCurrentCheck) latestOrderFiredAt(evts []events.Event, order orders.Order, expected time.Duration, now time.Time) (time.Time, error) { + return c.latestOrderFiredAtUsing(c.lastRun, evts, order, expected, now) +} + +// latestOrderFiredAtUsing is latestOrderFiredAt against a caller-supplied +// order-run resolver, so the classification loop can read prefetched results +// instead of issuing each store round-trip inline. +func (c *OrderFiringCurrentCheck) latestOrderFiredAtUsing(lastRun OrderFiringCurrentLastRunFunc, evts []events.Event, order orders.Order, expected time.Duration, now time.Time) (time.Time, error) { latest := latestOrderFiredAt(evts, order.ScopedName()) - if c.lastRun == nil { + if lastRun == nil { return latest, nil } - if !latest.IsZero() && now.Sub(latest) < expected+expected/2 { - return latest, nil + if !eventEvidenceSuffices(latest, expected, now) { + runAt, err := lastRun(order) + if err != nil { + return time.Time{}, err + } + if runAt.After(latest) { + return runAt, nil + } } - runAt, err := c.lastRun(order) - if err != nil { - return time.Time{}, err + return latest, nil +} + +// monitoredOrder is one enabled cron/cooldown order the check watches, +// carrying its resolved expected interval (or the resolution error the +// classification loop reports). +type monitoredOrder struct { + order orders.Order + expected time.Duration + err error +} + +// prefetchLastRuns resolves, in parallel, the order-run lookups the +// classification loop is about to need. Each lookup is a store round-trip +// costing ~1s on a busy city; issued serially across the monitored orders they +// alone exceed the check budget, while the check's own timeout means a slow +// fan-out reports a blocking failure that says nothing about order firing +// (ga-klv). Results (values AND errors) are handed back verbatim so the +// classification loop behaves exactly as it did when it called inline. +func (c *OrderFiringCurrentCheck) prefetchLastRuns(pending []orders.Order) map[string]orderFiringLastRunResult { + out := make(map[string]orderFiringLastRunResult, len(pending)) + if c.lastRun == nil || len(pending) == 0 { + return out } - if runAt.After(latest) { - return runAt, nil + + limit := orderFiringLastRunConcurrency + if len(pending) < limit { + limit = len(pending) + } + var mu sync.Mutex + var wg sync.WaitGroup + sem := make(chan struct{}, limit) + for _, order := range pending { + wg.Add(1) + go func(order orders.Order) { + defer wg.Done() + sem <- struct{}{} + defer func() { <-sem }() + at, err := c.lastRun(order) + mu.Lock() + out[order.ScopedName()] = orderFiringLastRunResult{at: at, err: err} + mu.Unlock() + }(order) + } + wg.Wait() + return out +} + +// orderFiringLastRunResult is one prefetched order-run lookup outcome. +type orderFiringLastRunResult struct { + at time.Time + err error +} + +// eventEvidenceSuffices reports whether the event log alone answers "is this +// order current". Anything else needs the authoritative order-run lookup: the +// event log can lag, and a stale event must not be reported as a real outage +// without confirmation. +func eventEvidenceSuffices(latest time.Time, expected time.Duration, now time.Time) bool { + return !latest.IsZero() && now.Sub(latest) < expected+expected/2 +} + +// pendingLastRunOrders returns the monitored orders the event log cannot +// answer on its own, in discovery order. It filters the same monitored slice +// the classification loop iterates, so the two cannot disagree on which +// orders need an authoritative lookup. Orders whose expected interval could +// not be computed are skipped: the loop reports that as its own error without +// ever reaching the lookup. +func (c *OrderFiringCurrentCheck) pendingLastRunOrders(monitored []monitoredOrder, firedEvents []events.Event, now time.Time) []orders.Order { + if c.lastRun == nil { + return nil + } + var pending []orders.Order + for _, mo := range monitored { + if mo.err != nil { + continue + } + if eventEvidenceSuffices(latestOrderFiredAt(firedEvents, mo.order.ScopedName()), mo.expected, now) { + continue + } + pending = append(pending, mo.order) + } + return pending +} + +// prefetchedLastRunFunc resolves pending in parallel and returns a resolver +// serving those results. A lookup the pre-pass did not anticipate still falls +// through to the live resolver, so the classification loop can never silently +// lose an answer. +func (c *OrderFiringCurrentCheck) prefetchedLastRunFunc(pending []orders.Order) OrderFiringCurrentLastRunFunc { + if c.lastRun == nil { + return nil + } + prefetched := c.prefetchLastRuns(pending) + return func(order orders.Order) (time.Time, error) { + if result, ok := prefetched[order.ScopedName()]; ok { + return result.at, result.err + } + return c.lastRun(order) } - return latest, nil } func latestOrderFiredAt(evts []events.Event, subject string) time.Time { diff --git a/internal/doctor/checks_order_firing_bounded_test.go b/internal/doctor/checks_order_firing_bounded_test.go new file mode 100644 index 0000000000..5661a110b4 --- /dev/null +++ b/internal/doctor/checks_order_firing_bounded_test.go @@ -0,0 +1,371 @@ +package doctor + +// Ported from upstream's ga-klv regression guards and adapted to this fork's +// structure: here only the order.fired read goes through the readEvents seam +// (bounded tail + Since window), while the controller-start lookup and the +// never-fired disambiguation probe use events.ReadLatestMatch, which walks +// newest-first with early exit by construction. + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/gastownhall/gascity/internal/events" + "github.com/gastownhall/gascity/internal/orders" +) + +// eventReadCall records one event-log read issued through the seam. +type eventReadCall struct { + filter events.Filter + limit int +} + +// spyEventReader wraps the real reader and records every call so a test can +// assert the read shape (bounded vs unbounded) rather than only its result. +func spyEventReader(calls *[]eventReadCall) orderFiringEventReadFunc { + return func(path string, filter events.Filter, limit int) ([]events.Event, error) { + *calls = append(*calls, eventReadCall{filter: filter, limit: limit}) + return events.ReadFilteredTail(path, filter, limit) + } +} + +// TestOrderFiringCurrent_EventReadsAreBounded is the regression guard for +// ga-klv: the check must never issue an unbounded order.fired read against the +// city event log. On a busy city that log reaches hundreds of megabytes, and a +// full scan (36s per read, measured on a 161MB/253k-line log) blows the 15s +// check budget and turns this check permanently red for a reason unrelated to +// order firing. +func TestOrderFiringCurrent_EventReadsAreBounded(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + cityPath, cfg := orderFiringTestCity(t) + writeOrderFiringTestOrder(t, cityPath, "cleanup-cooldown", "cooldown", "1h") + writeOrderFiringTestEvents(t, cityPath, + events.Event{Type: events.ControllerStarted, Ts: now.Add(-24 * time.Hour)}, + events.Event{Type: events.OrderFired, Subject: "cleanup-cooldown", Ts: now.Add(-10 * time.Minute)}, + ) + + var calls []eventReadCall + check := NewOrderFiringCurrentCheck(cfg, cityPath) + check.clock = func() time.Time { return now } + check.readEvents = spyEventReader(&calls) + + result := check.Run(&CheckContext{CityPath: cityPath}) + if result.Status != StatusOK { + t.Fatalf("status = %v, want ok; msg = %s; details = %v", result.Status, result.Message, result.Details) + } + if len(calls) == 0 { + t.Fatal("check issued no event-log reads through the seam; the spy is not wired") + } + for i, call := range calls { + if call.filter.Type != events.OrderFired { + t.Fatalf("call %d: unexpected event filter type %q; only order.fired goes through the seam", i, call.filter.Type) + } + if call.limit <= 0 { + t.Fatalf("call %d: order.fired read is unbounded (limit=%d); a full event-log scan blows the check budget", i, call.limit) + } + if call.filter.Since.IsZero() { + t.Fatalf("call %d: order.fired read carries no Since window; the staleness horizon must prune it (vc-89s)", i) + } + } +} + +// TestOrderFiringCurrent_LargeEventLogStaysInsideBudget is the behavioral half +// of the guard: with a log large enough that a full scan is measurably slow, the +// check must still finish well inside its budget. It fails if anyone reinstates +// an unbounded read, independent of the call-shape assertions above. +func TestOrderFiringCurrent_LargeEventLogStaysInsideBudget(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + cityPath, cfg := orderFiringTestCity(t) + writeOrderFiringTestOrder(t, cityPath, "cleanup-cooldown", "cooldown", "1h") + + // Oldest-first: the controller start and a large body of unrelated noise, + // then the firing we care about last. A tail read reaches the firing after + // a few lines; a full scan pays for every one of them. + evts := []events.Event{{Type: events.ControllerStarted, Ts: now.Add(-24 * time.Hour)}} + for i := 0; i < 40000; i++ { + evts = append(evts, events.Event{ + Type: events.OrderFired, + Subject: fmt.Sprintf("noise-order-%d", i%64), + Ts: now.Add(-12 * time.Hour), + }) + } + evts = append(evts, events.Event{Type: events.OrderFired, Subject: "cleanup-cooldown", Ts: now.Add(-10 * time.Minute)}) + writeOrderFiringTestEvents(t, cityPath, evts...) + + check := NewOrderFiringCurrentCheck(cfg, cityPath) + check.clock = func() time.Time { return now } + check.lastRun = func(orders.Order) (time.Time, error) { + return time.Time{}, fmt.Errorf("lastRun must not be consulted: the firing is in the event tail") + } + + start := time.Now() + result := check.Run(&CheckContext{CityPath: cityPath}) + elapsed := time.Since(start) + + if result.Status != StatusOK { + t.Fatalf("status = %v, want ok; msg = %s; details = %v", result.Status, result.Message, result.Details) + } + // Generous relative to a bounded read (milliseconds) and far under the 15s + // budget, but tight enough that a full-scan regression trips it. + if budget := 5 * time.Second; elapsed > budget { + t.Fatalf("check took %s on a large event log, want under %s; the event read is likely unbounded again", elapsed, budget) + } +} + +// TestOrderFiringCurrent_FiringOlderThanTailFallsBackToLastRun pins the +// correctness contract that makes the bounded read safe: an order whose newest +// firing predates the tail window is not silently reported as never-fired — the +// check falls through to the authoritative (already bounded) order-run lookup. +func TestOrderFiringCurrent_FiringOlderThanTailFallsBackToLastRun(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + cityPath, cfg := orderFiringTestCity(t) + writeOrderFiringTestOrder(t, cityPath, "cleanup-cooldown", "cooldown", "1h") + writeOrderFiringTestEvents(t, cityPath, + events.Event{Type: events.ControllerStarted, Ts: now.Add(-24 * time.Hour)}, + events.Event{Type: events.OrderFired, Subject: "cleanup-cooldown", Ts: now.Add(-10 * time.Minute)}, + ) + + lastRunCalled := false + check := NewOrderFiringCurrentCheck(cfg, cityPath) + check.clock = func() time.Time { return now } + // Simulate a firing that fell outside the tail window: the event read + // returns nothing for this order, so only order-run history can answer. + check.readEvents = func(path string, filter events.Filter, limit int) ([]events.Event, error) { + if filter.Type == events.OrderFired { + return nil, nil + } + return events.ReadFilteredTail(path, filter, limit) + } + check.lastRun = func(orders.Order) (time.Time, error) { + lastRunCalled = true + return now.Add(-10 * time.Minute), nil + } + + result := check.Run(&CheckContext{CityPath: cityPath}) + if !lastRunCalled { + t.Fatal("lastRun was not consulted for a firing outside the event tail; the bounded read would report a false stale") + } + if result.Status != StatusOK { + t.Fatalf("status = %v, want ok (order-run history has a fresh run); msg = %s; details = %v", result.Status, result.Message, result.Details) + } +} + +// TestOrderFiringCurrent_TimeoutHintNamesQueryCost pins the corrected hint. The +// old text blamed "beads/Dolt connectivity", which sent triage at the data +// plane while the data plane was healthy and cost a full triage cycle (ga-klv). +// A timeout here is a query-cost problem, so the hint must say so. +func TestOrderFiringCurrent_TimeoutHintNamesQueryCost(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + cityPath, cfg := orderFiringTestCity(t) + writeOrderFiringTestOrder(t, cityPath, "mol-dog-stalled-history", "cron", "0 */4 * * *") + writeOrderFiringTestEvents(t, cityPath, + events.Event{Type: events.ControllerStarted, Ts: now.Add(-24 * time.Hour)}, + events.Event{Type: events.OrderFired, Subject: "mol-dog-stalled-history", Ts: now.Add(-13 * time.Hour)}, + ) + + release := make(chan struct{}) + t.Cleanup(func() { close(release) }) + check := NewOrderFiringCurrentCheck(cfg, cityPath) + check.clock = func() time.Time { return now } + check.historyTimeout = 20 * time.Millisecond + check.lastRun = func(orders.Order) (time.Time, error) { + <-release + return time.Time{}, nil + } + + result := check.Run(&CheckContext{CityPath: cityPath}) + if result.Status != StatusError { + t.Fatalf("status = %v, want error; msg = %s", result.Status, result.Message) + } + if strings.Contains(strings.ToLower(result.FixHint), "connectivity") { + t.Fatalf("FixHint = %q, must not blame connectivity: a timeout here is a query-cost problem", result.FixHint) + } + for _, want := range []string{"gc order history", "--limit"} { + if !strings.Contains(result.FixHint, want) { + t.Fatalf("FixHint = %q, want it to mention %q", result.FixHint, want) + } + } +} + +// TestOrderFiringCurrent_LastRunLookupsRunInParallel is the regression guard +// for the second half of ga-klv. Each order-run lookup is a store round-trip +// costing about a second on a busy city; issued serially across the monitored +// orders they exceed the check budget on their own, and the check then reports +// a blocking failure that says nothing about whether orders are firing. +func TestOrderFiringCurrent_LastRunLookupsRunInParallel(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + cityPath, cfg := orderFiringTestCity(t) + + // Every order is stale by events, so all of them need the lookup. + const orderCount = 8 + var evts []events.Event + evts = append(evts, events.Event{Type: events.ControllerStarted, Ts: now.Add(-240 * time.Hour)}) + for i := 0; i < orderCount; i++ { + name := fmt.Sprintf("cooldown-order-%d", i) + writeOrderFiringTestOrder(t, cityPath, name, "cooldown", "1h") + evts = append(evts, events.Event{Type: events.OrderFired, Subject: name, Ts: now.Add(-9 * time.Hour)}) + } + writeOrderFiringTestEvents(t, cityPath, evts...) + + // Prove the fan-out overlaps deterministically instead of racing a wall + // clock: every lookup rendezvouses at a barrier and only returns once + // wantConcurrent of them are in flight at the same time. A serial fan-out + // can never gather the quorum, so it trips the failsafe and fails the + // maxInFlight assertion below rather than passing by luck. The failsafe + // never fires while the lookups genuinely run in parallel; it only bounds a + // future regression to serial so the test fails fast instead of hanging. + const wantConcurrent = 2 + const barrierFailsafe = 5 * time.Second + var inFlight, maxInFlight int32 + rendezvous := make(chan struct{}) + var releaseOnce sync.Once + release := func() { releaseOnce.Do(func() { close(rendezvous) }) } + failsafe := time.AfterFunc(barrierFailsafe, release) + defer failsafe.Stop() + + check := NewOrderFiringCurrentCheck(cfg, cityPath) + check.clock = func() time.Time { return now } + check.lastRun = func(orders.Order) (time.Time, error) { + cur := atomic.AddInt32(&inFlight, 1) + defer atomic.AddInt32(&inFlight, -1) + for { + observed := atomic.LoadInt32(&maxInFlight) + if cur <= observed || atomic.CompareAndSwapInt32(&maxInFlight, observed, cur) { + break + } + } + if cur >= wantConcurrent { + release() + } + <-rendezvous + return now.Add(-30 * time.Minute), nil + } + + result := check.Run(&CheckContext{CityPath: cityPath}) + + if result.Status != StatusOK { + t.Fatalf("status = %v, want ok (every order has a fresh run); msg = %s; details = %v", result.Status, result.Message, result.Details) + } + if got := atomic.LoadInt32(&maxInFlight); got < wantConcurrent { + t.Fatalf("max concurrent order-run lookups = %d, want at least %d; the fan-out is still serial", got, wantConcurrent) + } +} + +// TestOrderFiringCurrent_PrefetchPreservesLookupErrors makes sure moving the +// lookups off the classification loop did not swallow their failures: a lookup +// error must still surface as a blocking check error, exactly as it did when +// the loop called the resolver inline. +func TestOrderFiringCurrent_PrefetchPreservesLookupErrors(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + cityPath, cfg := orderFiringTestCity(t) + writeOrderFiringTestOrder(t, cityPath, "cleanup-cooldown", "cooldown", "1h") + writeOrderFiringTestEvents(t, cityPath, + events.Event{Type: events.ControllerStarted, Ts: now.Add(-240 * time.Hour)}, + events.Event{Type: events.OrderFired, Subject: "cleanup-cooldown", Ts: now.Add(-9 * time.Hour)}, + ) + + check := NewOrderFiringCurrentCheck(cfg, cityPath) + check.clock = func() time.Time { return now } + check.lastRun = func(orders.Order) (time.Time, error) { + return time.Time{}, fmt.Errorf("store unreachable") + } + + result := check.Run(&CheckContext{CityPath: cityPath}) + if result.Status != StatusError { + t.Fatalf("status = %v, want error when the order-run lookup fails", result.Status) + } + if joined := strings.Join(result.Details, "\n"); !strings.Contains(joined, "store unreachable") { + t.Fatalf("details = %v, want the lookup error surfaced", result.Details) + } + if result.Severity != SeverityBlocking { + t.Fatalf("Severity = %v, want SeverityBlocking for a failed lookup", result.Severity) + } +} + +// TestOrderFiringCurrent_PrefetchSkipsOrdersTheEventLogAnswers keeps the +// parallel pre-pass from turning into a store stampede: an order the event log +// already proves current must not be looked up at all. It also guards the +// agreement between the pre-pass and the classification loop — a filter drift +// that dropped the stale order from the prefetch set would surface here as a +// second, inline lookup. +func TestOrderFiringCurrent_PrefetchSkipsOrdersTheEventLogAnswers(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + cityPath, cfg := orderFiringTestCity(t) + writeOrderFiringTestOrder(t, cityPath, "fresh-cooldown", "cooldown", "1h") + writeOrderFiringTestOrder(t, cityPath, "stale-cooldown", "cooldown", "1h") + writeOrderFiringTestEvents(t, cityPath, + events.Event{Type: events.ControllerStarted, Ts: now.Add(-240 * time.Hour)}, + events.Event{Type: events.OrderFired, Subject: "fresh-cooldown", Ts: now.Add(-10 * time.Minute)}, + events.Event{Type: events.OrderFired, Subject: "stale-cooldown", Ts: now.Add(-9 * time.Hour)}, + ) + + var mu sync.Mutex + var lookedUp []string + check := NewOrderFiringCurrentCheck(cfg, cityPath) + check.clock = func() time.Time { return now } + check.lastRun = func(o orders.Order) (time.Time, error) { + mu.Lock() + lookedUp = append(lookedUp, o.ScopedName()) + mu.Unlock() + return now.Add(-30 * time.Minute), nil + } + + check.Run(&CheckContext{CityPath: cityPath}) + + mu.Lock() + defer mu.Unlock() + if len(lookedUp) != 1 || lookedUp[0] != "stale-cooldown" { + t.Fatalf("looked up %v, want only the order the event log cannot answer", lookedUp) + } +} + +// TestOrderFiringEventTailLimitIsPositive keeps the tail bound from being +// zeroed out, which would silently restore the unbounded read: the reader +// treats a non-positive limit as "read everything". +func TestOrderFiringEventTailLimitIsPositive(t *testing.T) { + if orderFiringEventTailLimit <= 0 { + t.Fatalf("orderFiringEventTailLimit = %d, want positive; a non-positive limit means an unbounded read", orderFiringEventTailLimit) + } +} + +// TestOrderFiringCurrent_ReadsCityEventLogPath guards against the check reading +// a path other than the city event log; it keeps the bounded read pointed at the +// file the rest of the suite writes. +func TestOrderFiringCurrent_ReadsCityEventLogPath(t *testing.T) { + now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) + cityPath, cfg := orderFiringTestCity(t) + writeOrderFiringTestOrder(t, cityPath, "cleanup-cooldown", "cooldown", "1h") + writeOrderFiringTestEvents(t, cityPath, + events.Event{Type: events.ControllerStarted, Ts: now.Add(-24 * time.Hour)}, + events.Event{Type: events.OrderFired, Subject: "cleanup-cooldown", Ts: now.Add(-10 * time.Minute)}, + ) + + want := filepath.Join(cityPath, ".gc", "events.jsonl") + if _, err := os.Stat(want); err != nil { + t.Fatalf("event log not written where the suite expects: %v", err) + } + + var paths []string + check := NewOrderFiringCurrentCheck(cfg, cityPath) + check.clock = func() time.Time { return now } + check.readEvents = func(path string, filter events.Filter, limit int) ([]events.Event, error) { + paths = append(paths, path) + return events.ReadFilteredTail(path, filter, limit) + } + check.Run(&CheckContext{CityPath: cityPath}) + + if len(paths) == 0 { + t.Fatal("check issued no event-log reads") + } + for _, got := range paths { + if got != want { + t.Fatalf("read path = %q, want %q", got, want) + } + } +} diff --git a/internal/doctor/checks_order_firing_test.go b/internal/doctor/checks_order_firing_test.go index f16cbdb6c4..f68d232a5d 100644 --- a/internal/doctor/checks_order_firing_test.go +++ b/internal/doctor/checks_order_firing_test.go @@ -528,11 +528,15 @@ func TestOrderFiringCurrent_CorruptArchive_DegradesToWarning(t *testing.T) { // check (StatusError), hiding the real verdict for days. It must degrade // instead: Warning naming the skipped file — never StatusError, and // never a silent OK over data the check did not see. + // + // The order.fired read is a live-file tail and never touches archives; + // the archive-spanning read is the controller-start lookup. Keep + // controller.started out of the live log so that lookup must walk into + // the corrupt archive. now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC) cityPath, cfg := orderFiringTestCity(t) writeOrderFiringTestOrder(t, cityPath, "mol-dog-stale-db", "cron", "0 */4 * * *") writeOrderFiringTestEvents(t, cityPath, - events.Event{Type: events.ControllerStarted, Ts: now.Add(-8 * time.Hour)}, events.Event{Type: events.OrderFired, Subject: "mol-dog-stale-db", Ts: now.Add(-1 * time.Hour)}, ) corrupt := writeOrderFiringCorruptArchive(t, cityPath, now.Add(-2*time.Hour), 1, 2) diff --git a/internal/eventfeed/allowlist_drift_test.go b/internal/eventfeed/allowlist_drift_test.go index fcfa00bf41..c4d776d577 100644 --- a/internal/eventfeed/allowlist_drift_test.go +++ b/internal/eventfeed/allowlist_drift_test.go @@ -31,6 +31,8 @@ func TestAllowedTypesMatchEventConstants(t *testing.T) { events.EventsRotated, events.ExecutionWorkAssociated, events.ExecutionStepDefined, + events.ExecutionStepStarted, + events.ExecutionStepCompleted, events.SessionDrainAckedWithAssignedWork, events.SessionResetStalled, events.ProjectIdentityStamped, diff --git a/internal/events/events.go b/internal/events/events.go index c43a840663..d0fff5fe3d 100644 --- a/internal/events/events.go +++ b/internal/events/events.go @@ -40,6 +40,11 @@ const ( // occurrence. Subject carries the physical step bead, RunID the workflow // root, and StepID/DependsOnStepIDs the semantic topology. ExecutionStepDefined = "execution.step_defined" + // ExecutionStepStarted and ExecutionStepCompleted record the lifecycle of one + // physical graph.v2 native step attempt. Subject is the physical step bead; + // RunID, SessionID, StepID, and DependsOnStepIDs carry its durable identity. + ExecutionStepStarted = "execution.step_started" + ExecutionStepCompleted = "execution.step_completed" // BeadDeadAssigneeReopened fires when the reconciler reopens a routed work // bead whose assignee resolves to no open session bead — the owning session // closed/retired while the bead stayed assigned, leaving it open+routed but @@ -286,7 +291,7 @@ var KnownEventTypes = []string{ BeadWorktreeReaped, BeadWorktreeReapSkipped, BeadClaimRejected, BeadDeadAssigneeReopened, - ExecutionWorkAssociated, ExecutionStepDefined, + ExecutionWorkAssociated, ExecutionStepDefined, ExecutionStepStarted, ExecutionStepCompleted, MailSent, MailRead, MailArchived, MailMarkedRead, MailMarkedUnread, MailReplied, MailDeleted, ConvoyCreated, ConvoyClosed, diff --git a/internal/events/execution_payloads.go b/internal/events/execution_payloads.go index 9ba2a83d9e..6461abdf1a 100644 --- a/internal/events/execution_payloads.go +++ b/internal/events/execution_payloads.go @@ -3,4 +3,6 @@ package events func init() { RegisterPayload(ExecutionWorkAssociated, NoPayload{}) RegisterPayload(ExecutionStepDefined, NoPayload{}) + RegisterPayload(ExecutionStepStarted, NoPayload{}) + RegisterPayload(ExecutionStepCompleted, NoPayload{}) } diff --git a/internal/executionevent/lifecycle_test.go b/internal/executionevent/lifecycle_test.go new file mode 100644 index 0000000000..938a77db07 --- /dev/null +++ b/internal/executionevent/lifecycle_test.go @@ -0,0 +1,348 @@ +package executionevent + +import ( + "compress/gzip" + "encoding/json" + "errors" + "io" + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/gastownhall/gascity/internal/beadmeta" + "github.com/gastownhall/gascity/internal/beads" + "github.com/gastownhall/gascity/internal/events" +) + +func TestLifecycleEventsPreserveNativeGraphIdentityAndTopology(t *testing.T) { + root := beads.Bead{ID: "gcg-run", Metadata: map[string]string{ + beadmeta.KindMetadataKey: "workflow", beadmeta.FormulaContractMetadataKey: beadmeta.FormulaContractGraphV2, + }} + rootDeps := "[]" + fanoutDeps := `["root"]` + joinDeps := `["fan-a","fan-b"]` + for _, tc := range []struct { + name, ref, step, topology string + wantDeps *[]string + }{ + {"root", "gcg-root-attempt", "root", rootDeps, lifecycleStrings([]string{})}, + {"fanout", "gcg-fan-a-attempt", "fan-a", fanoutDeps, lifecycleStrings([]string{"root"})}, + {"join", "gcg-join-attempt", "join", joinDeps, lifecycleStrings([]string{"fan-a", "fan-b"})}, + } { + t.Run(tc.name, func(t *testing.T) { + step := beads.Bead{ID: tc.ref, Status: "in_progress", Metadata: map[string]string{ + beadmeta.RootBeadIDMetadataKey: root.ID, beadmeta.StepIDMetadataKey: tc.step, + beadmeta.SessionIDMetadataKey: "gcs-session", beadmeta.NativeStepDependenciesMetadataKey: tc.topology, + }} + started, ok := LifecycleEvent(events.ExecutionStepStarted, root, step, "worker") + if !ok { + t.Fatal("LifecycleEvent(started) = false") + } + if started.Type != events.ExecutionStepStarted || started.Subject != tc.ref || started.RunID != root.ID || started.SessionID != "gcs-session" || started.StepID != tc.step || !reflect.DeepEqual(started.DependsOnStepIDs, tc.wantDeps) { + t.Fatalf("started = %#v", started) + } + step.Status = "closed" + completed, ok := LifecycleEvent(events.ExecutionStepCompleted, root, step, "close-hook") + if !ok || completed.Type != events.ExecutionStepCompleted || !reflect.DeepEqual(completed.DependsOnStepIDs, tc.wantDeps) { + t.Fatalf("completed = %#v, ok=%v", completed, ok) + } + }) + } +} + +func TestEmitCompletedFromClosedNotificationUsesPhysicalSnapshot(t *testing.T) { + graph := beads.NewMemStore() + root := mustCreateProjectionRoot(t, graph, "") + step := mustCreateProjectionStep(t, graph, "gcg-retry-attempt", root.ID, "build", `["prepare"]`) + step.Status = "closed" + step.Metadata[beadmeta.SessionIDMetadataKey] = "gcs-session" + payload, err := json.Marshal(step) + if err != nil { + t.Fatal(err) + } + rec := events.NewFake() + if !EmitCompletedFromClosedNotification(rec, graph, payload, "close-hook") { + t.Fatal("close notification did not emit completed") + } + if len(rec.Events) != 1 { + t.Fatalf("events = %#v", rec.Events) + } + got := rec.Events[0] + if got.Type != events.ExecutionStepCompleted || got.Subject != step.ID || got.RunID != root.ID || got.SessionID != "gcs-session" || got.StepID != "build" || !reflect.DeepEqual(got.DependsOnStepIDs, lifecycleStrings([]string{"prepare"})) { + t.Fatalf("completed = %#v", got) + } + legacy := step + legacy.Metadata[beadmeta.RootBeadIDMetadataKey] = "unknown" + payload, _ = json.Marshal(legacy) + if EmitCompletedFromClosedNotification(rec, graph, payload, "close-hook") { + t.Fatal("unresolved close notification emitted") + } +} + +func TestReconcileCompletedRepairsMissingFactAndRetainsConflictingHistory(t *testing.T) { + graph := beads.NewMemStore() + root := mustCreateProjectionRoot(t, graph, "") + step := mustCreateProjectionStep(t, graph, "gcg-attempt", root.ID, "build", `["prepare"]`) + closed := "closed" + if err := graph.Update(step.ID, beads.UpdateOpts{Status: &closed, Metadata: map[string]string{beadmeta.SessionIDMetadataKey: "gcs-session"}}); err != nil { + t.Fatal(err) + } + recorder := events.NewFake() + // This looks like an already-emitted lifecycle fact by subject, but its + // session is stale. It must not suppress the authoritative correction. + recorder.Record(events.Event{ + Type: events.ExecutionStepCompleted, Subject: step.ID, RunID: root.ID, + SessionID: "gcs-stale", StepID: "build", DependsOnStepIDs: lifecycleStrings([]string{"prepare"}), + }) + + if got := ReconcileCompleted(recorder, beads.GraphStore{Store: graph}, "execution-reconcile"); got != 1 { + t.Fatalf("ReconcileCompleted = %d, want 1 correction", got) + } + if got := ReconcileCompleted(recorder, beads.GraphStore{Store: graph}, "execution-reconcile"); got != 0 { + t.Fatalf("second ReconcileCompleted = %d, want exact-fact no-op", got) + } + completed, err := recorder.List(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if err != nil { + t.Fatal(err) + } + if len(completed) != 2 || completed[1].SessionID != "gcs-session" || completed[1].RunID != root.ID || completed[1].StepID != "build" { + t.Fatalf("completed facts = %#v, want stale history plus authoritative correction", completed) + } +} + +func TestReconcileCompletedDoesNotDuplicateFactDuringFileRecorderRotation(t *testing.T) { + graph := beads.NewMemStore() + root := mustCreateProjectionRoot(t, graph, "") + step := mustCreateProjectionStep(t, graph, "gcg-rotation-attempt", root.ID, "build", "[]") + closed := "closed" + if err := graph.Update(step.ID, beads.UpdateOpts{Status: &closed, Metadata: map[string]string{beadmeta.SessionIDMetadataKey: "gcs-session"}}); err != nil { + t.Fatal(err) + } + step, err := graph.Get(step.ID) + if err != nil { + t.Fatal(err) + } + completed, ok := LifecycleEvent(events.ExecutionStepCompleted, root, step, "close-hook") + if !ok { + t.Fatal("LifecycleEvent(completed) = false") + } + + path := filepath.Join(t.TempDir(), "events.jsonl") + recorder, err := events.NewFileRecorder(path, io.Discard) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = recorder.Close() }) + recorder.Record(completed) + rotation, err := recorder.ForceRotate() + if err != nil { + t.Fatal(err) + } + if !rotation.Rotated { + t.Fatalf("ForceRotate = %#v, want archive", rotation) + } + recorder.WaitForRotations() + if got := ReconcileCompleted(recorder, beads.GraphStore{Store: graph}, "execution-reconcile"); got != 0 { + t.Fatalf("ReconcileCompleted after archived rotation = %d, want 0 duplicate facts", got) + } + + // Re-create the state after the active file is renamed but before its + // asynchronous gzip promotion. FileRecorder.List deliberately cannot see + // this segment; ListInFlight must supply it to a durable reconciler. + rotating := filepath.Join(filepath.Dir(path), "events.jsonl.rotating-20260805T000000Z-seq-1-1") + expandArchiveToRotating(t, rotation.ArchivePath, rotating) + + if got := ReconcileCompleted(recorder, beads.GraphStore{Store: graph}, "execution-reconcile"); got != 0 { + t.Fatalf("ReconcileCompleted during rotation = %d, want 0 duplicate facts", got) + } + all, err := recorder.ListInFlight(events.Filter{Type: events.ExecutionStepCompleted, Subject: step.ID}) + if err != nil { + t.Fatal(err) + } + if len(all) != 1 { + t.Fatalf("completion facts during rotation = %#v, want exactly archived fact", all) + } +} + +func expandArchiveToRotating(t *testing.T, archivePath, rotatingPath string) { + t.Helper() + archive, err := os.Open(archivePath) + if err != nil { + t.Fatal(err) + } + reader, err := gzip.NewReader(archive) + if err != nil { + _ = archive.Close() + t.Fatal(err) + } + data, err := io.ReadAll(reader) + if closeErr := reader.Close(); err == nil { + err = closeErr + } + if closeErr := archive.Close(); err == nil { + err = closeErr + } + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(rotatingPath, data, 0o644); err != nil { + t.Fatal(err) + } + if err := os.Remove(archivePath); err != nil { + t.Fatal(err) + } +} + +func TestReconcileCompletedStoresPreloadsExactFactsOnceAndFailsClosed(t *testing.T) { + firstGraph := beads.NewMemStore() + firstRoot := mustCreateProjectionRoot(t, firstGraph, "") + nilTopologyStep := mustCreateProjectionStep(t, firstGraph, "gcg-nil-topology", firstRoot.ID, "build", "") + closed := "closed" + if err := firstGraph.Update(nilTopologyStep.ID, beads.UpdateOpts{Status: &closed, Metadata: map[string]string{beadmeta.SessionIDMetadataKey: "gcs-session"}}); err != nil { + t.Fatal(err) + } + nilTopologyStep, err := firstGraph.Get(nilTopologyStep.ID) + if err != nil { + t.Fatal(err) + } + nilTopologyFact, ok := LifecycleEvent(events.ExecutionStepCompleted, firstRoot, nilTopologyStep, "prior-reconcile") + if !ok || nilTopologyFact.DependsOnStepIDs != nil { + t.Fatalf("nil topology fact = %#v, ok=%v", nilTopologyFact, ok) + } + + secondGraph := beads.NewMemStore() + secondRoot := mustCreateProjectionRoot(t, secondGraph, "") + emptyTopologyStep := mustCreateProjectionStep(t, secondGraph, "gcg-empty-topology", secondRoot.ID, "test", "[]") + if err := secondGraph.Update(emptyTopologyStep.ID, beads.UpdateOpts{Status: &closed, Metadata: map[string]string{beadmeta.SessionIDMetadataKey: "gcs-session"}}); err != nil { + t.Fatal(err) + } + emptyTopologyStep, err = secondGraph.Get(emptyTopologyStep.ID) + if err != nil { + t.Fatal(err) + } + emptyTopologyFact, ok := LifecycleEvent(events.ExecutionStepCompleted, secondRoot, emptyTopologyStep, "prior-reconcile") + if !ok || !reflect.DeepEqual(emptyTopologyFact.DependsOnStepIDs, lifecycleStrings([]string{})) { + t.Fatalf("empty topology fact = %#v, ok=%v", emptyTopologyFact, ok) + } + + backing := events.NewFake() + backing.Record(nilTopologyFact) // Exact fact: must suppress this candidate. + emptyTopologyFact.DependsOnStepIDs = nil + backing.Record(emptyTopologyFact) // Same tuple except unknown, not known-empty, topology. + provider := &countingEventProvider{Provider: backing} + stores := []beads.GraphStore{{Store: firstGraph}, {Store: secondGraph}} + if got := ReconcileCompletedStores(provider, stores, "execution-reconcile"); got != 1 { + t.Fatalf("ReconcileCompletedStores = %d, want one topology correction", got) + } + if provider.listCalls != 1 { + t.Fatalf("completed fact List calls = %d, want one across both stores", provider.listCalls) + } + if got := ReconcileCompletedStores(provider, stores, "execution-reconcile"); got != 0 { + t.Fatalf("second ReconcileCompletedStores = %d, want exact-fact no-op", got) + } + if provider.listCalls != 2 { + t.Fatalf("completed fact List calls after second pass = %d, want one per pass", provider.listCalls) + } + + before, err := backing.List(events.Filter{Type: events.ExecutionStepCompleted}) + if err != nil { + t.Fatal(err) + } + failing := &countingEventProvider{Provider: backing, listErr: errors.New("journal unavailable")} + if got := ReconcileCompletedStores(failing, stores, "execution-reconcile"); got != 0 { + t.Fatalf("ReconcileCompletedStores with List error = %d, want fail-closed zero", got) + } + if failing.listCalls != 1 { + t.Fatalf("failed completed fact List calls = %d, want one", failing.listCalls) + } + after, err := backing.List(events.Filter{Type: events.ExecutionStepCompleted}) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(after, before) { + t.Fatalf("List error recorded events: before=%#v after=%#v", before, after) + } +} + +type countingEventProvider struct { + events.Provider + listCalls int + listErr error +} + +func (p *countingEventProvider) List(filter events.Filter) ([]events.Event, error) { + p.listCalls++ + if p.listErr != nil { + return nil, p.listErr + } + return p.Provider.List(filter) +} + +func TestCompletedFactKeyDistinguishesUnknownFromKnownEmptyTopology(t *testing.T) { + base := events.Event{Subject: "gcg-attempt", RunID: "gcg-run", SessionID: "gcs-session", StepID: "build"} + var nilSlice []string + emptySlice := []string{} + unknown := completedFactKeyFor(base) + presentNil := completedFactKeyFor(events.Event{ + Subject: base.Subject, RunID: base.RunID, SessionID: base.SessionID, StepID: base.StepID, DependsOnStepIDs: &nilSlice, + }) + presentEmpty := completedFactKeyFor(events.Event{ + Subject: base.Subject, RunID: base.RunID, SessionID: base.SessionID, StepID: base.StepID, DependsOnStepIDs: &emptySlice, + }) + if presentNil != presentEmpty { + t.Fatalf("present nil topology key = %#v, present empty topology key = %#v; want equality", presentNil, presentEmpty) + } + if unknown == presentEmpty { + t.Fatalf("unknown topology key = %#v, known empty topology key = %#v; want distinction", unknown, presentEmpty) + } +} + +func TestLifecycleEventRetainsUnknownAndRejectsNonNativeOrInvalidFacts(t *testing.T) { + root := beads.Bead{ID: "gcg-run", Metadata: map[string]string{beadmeta.KindMetadataKey: "workflow", beadmeta.FormulaContractMetadataKey: beadmeta.FormulaContractGraphV2}} + base := beads.Bead{ID: "gcg-attempt", Status: "in_progress", Metadata: map[string]string{beadmeta.RootBeadIDMetadataKey: root.ID, beadmeta.StepIDMetadataKey: "build", beadmeta.SessionIDMetadataKey: "gcs-session"}} + got, ok := LifecycleEvent(events.ExecutionStepStarted, root, base, "worker") + if !ok || got.DependsOnStepIDs != nil { + t.Fatalf("unknown topology = %#v, ok=%v", got, ok) + } + for _, mutate := range []func(*beads.Bead){ + func(b *beads.Bead) { b.Metadata[beadmeta.SessionIDMetadataKey] = "" }, + func(b *beads.Bead) { b.Metadata[beadmeta.StepIDMetadataKey] = " " }, + func(b *beads.Bead) { b.Metadata[beadmeta.RootBeadIDMetadataKey] = "external-root" }, + } { + step := base + step.Metadata = map[string]string{} + for k, v := range base.Metadata { + step.Metadata[k] = v + } + mutate(&step) + if _, ok := LifecycleEvent(events.ExecutionStepStarted, root, step, "worker"); ok { + t.Fatalf("invalid step emitted: %#v", step) + } + } + invalidTopology := base + invalidTopology.Metadata = map[string]string{} + for k, v := range base.Metadata { + invalidTopology.Metadata[k] = v + } + invalidTopology.Metadata[beadmeta.NativeStepDependenciesMetadataKey] = `["build"]` + if event, ok := LifecycleEvent(events.ExecutionStepStarted, root, invalidTopology, "worker"); !ok || event.DependsOnStepIDs != nil { + t.Fatalf("malformed topology must degrade to unknown, got %#v ok=%v", event, ok) + } + legacy := root + legacy.Metadata = map[string]string{beadmeta.KindMetadataKey: "workflow"} + if _, ok := LifecycleEvent(events.ExecutionStepStarted, legacy, base, "worker"); ok { + t.Fatal("v1 root emitted lifecycle event") + } + control := base + control.Metadata = map[string]string{} + for k, v := range base.Metadata { + control.Metadata[k] = v + } + control.Metadata[beadmeta.KindMetadataKey] = "check" + if _, ok := LifecycleEvent(events.ExecutionStepCompleted, root, control, "close-hook"); ok { + t.Fatal("control close emitted lifecycle event") + } +} + +func lifecycleStrings(v []string) *[]string { return &v } diff --git a/internal/executionevent/projector.go b/internal/executionevent/projector.go index b5f02eef2e..6cf792311e 100644 --- a/internal/executionevent/projector.go +++ b/internal/executionevent/projector.go @@ -235,3 +235,190 @@ func cloneTopology(dependencies *[]string) *[]string { copy(clone, *dependencies) return &clone } + +// LifecycleEvent constructs a lifecycle fact only for a physical native step +// of the supplied authoritative graph.v2 root. It is shared by claim and close +// notification producers so the event contract cannot drift between them. +func LifecycleEvent(eventType string, root, step beads.Bead, actor string) (events.Event, bool) { + if eventType != events.ExecutionStepStarted && eventType != events.ExecutionStepCompleted { + return events.Event{}, false + } + if root.Metadata[beadmeta.KindMetadataKey] != beadmeta.KindWorkflow || + root.Metadata[beadmeta.FormulaContractMetadataKey] != beadmeta.FormulaContractGraphV2 || + !eventexport.IsOpaqueRef(root.ID) || !eventexport.IsOpaqueRef(step.ID) || + step.Metadata[beadmeta.RootBeadIDMetadataKey] != root.ID || + beadmeta.IsControlKind(strings.TrimSpace(step.Metadata[beadmeta.KindMetadataKey])) { + return events.Event{}, false + } + stepID := step.Metadata[beadmeta.StepIDMetadataKey] + sessionID := step.Metadata[beadmeta.SessionIDMetadataKey] + if !validNativeStepID(stepID) || !eventexport.IsOpaqueRef(sessionID) { + return events.Event{}, false + } + return events.Event{ + Type: eventType, Actor: actor, Subject: step.ID, RunID: root.ID, + SessionID: sessionID, StepID: stepID, + DependsOnStepIDs: canonicalTopology(step.Metadata[beadmeta.NativeStepDependenciesMetadataKey], stepID), + }, true +} + +// EmitLifecycle records a validated lifecycle fact for a graph.v2 step. The +// root is loaded from graphStore so a v1 or unrelated parent can never produce +// a lifecycle event by metadata resemblance alone. +func EmitLifecycle(recorder events.Recorder, graphStore beads.Store, eventType string, step beads.Bead, actor string) bool { + if recorder == nil || graphStore == nil { + return false + } + rootID := step.Metadata[beadmeta.RootBeadIDMetadataKey] + if !eventexport.IsOpaqueRef(rootID) { + return false + } + root, err := graphStore.Get(rootID) + if err != nil { + return false + } + event, ok := LifecycleEvent(eventType, root, step, actor) + if !ok { + return false + } + recorder.Record(event) + return true +} + +// EmitCompletedFromClosedNotification is the sole close-side lifecycle entry +// point. It consumes the physical bead snapshot carried by the authoritative +// bead.closed notification rather than inferring completion from dependencies +// or re-projecting current graph state. +func EmitCompletedFromClosedNotification(recorder events.Recorder, graphStore beads.Store, payload json.RawMessage, actor string) bool { + step, ok := beads.DecodeBeadEventPayload(payload) + if !ok || !strings.EqualFold(strings.TrimSpace(step.Status), "closed") { + return false + } + return EmitLifecycle(recorder, graphStore, events.ExecutionStepCompleted, step, actor) +} + +// ReconcileCompleted repairs completed facts that were stranded between a +// durable graph-step close and the best-effort event append. It projects only +// closed physical steps of authoritative graph.v2 roots, and uses the event +// journal as the durable idempotency record: an exact lifecycle fact is not +// repeated, while a conflicting historical fact remains visible alongside the +// newly projected correction. +func ReconcileCompleted(recorder events.Provider, graphStore beads.GraphStore, actor string) int { + return ReconcileCompletedStores(recorder, []beads.GraphStore{graphStore}, actor) +} + +// ReconcileCompletedStores repairs completion facts across graph stores with +// one journal read. The completed-fact index is updated after each append so +// the pass remains idempotent even when more than one source is scanned. +func ReconcileCompletedStores(recorder events.Provider, graphStores []beads.GraphStore, actor string) int { + if recorder == nil { + return 0 + } + hasStore := false + for _, graphStore := range graphStores { + if graphStore.Store != nil { + hasStore = true + break + } + } + if !hasStore { + return 0 + } + + existing, err := completedFacts(recorder) + if err != nil { + // If the journal cannot be read, avoid generating duplicate recovery + // facts. A later reconciliation pass can safely retry. + return 0 + } + completed := make(map[completedFactKey]struct{}, len(existing)) + for _, event := range existing { + if event.Type == events.ExecutionStepCompleted { + completed[completedFactKeyFor(event)] = struct{}{} + } + } + + emitted := 0 + for _, graphStore := range graphStores { + if graphStore.Store == nil { + continue + } + roots, err := graphStore.ListByMetadata( + map[string]string{beadmeta.KindMetadataKey: beadmeta.KindWorkflow}, + 0, + beads.IncludeClosed, + beads.WithBothTiers, + ) + if err != nil { + continue + } + sort.Slice(roots, func(i, j int) bool { return roots[i].ID < roots[j].ID }) + for _, root := range roots { + if root.Metadata[beadmeta.FormulaContractMetadataKey] != beadmeta.FormulaContractGraphV2 { + continue + } + definitions, err := currentSteps(graphStore, root.ID) + if err != nil { + continue + } + for _, definition := range definitions { + step, err := graphStore.Get(definition.BeadID) + if err != nil || !strings.EqualFold(strings.TrimSpace(step.Status), "closed") { + continue + } + event, ok := LifecycleEvent(events.ExecutionStepCompleted, root, step, actor) + if !ok { + continue + } + key := completedFactKeyFor(event) + if _, exists := completed[key]; exists { + continue + } + recorder.Record(event) + completed[key] = struct{}{} + emitted++ + } + } + } + return emitted +} + +// completedFacts returns the retained completion journal, including a +// FileRecorder segment that is temporarily awaiting archive compression. A +// reconciliation pass must see that segment before deciding a close needs a +// recovery fact; otherwise an event rotation can create a duplicate fact. +func completedFacts(recorder events.Provider) ([]events.Event, error) { + filter := events.Filter{Type: events.ExecutionStepCompleted} + if inFlight, ok := recorder.(events.InFlightProvider); ok { + return inFlight.ListInFlight(filter) + } + return recorder.List(filter) +} + +type completedFactKey struct { + subject string + runID string + sessionID string + stepID string + topologyKnown bool + topologyCanonical string +} + +func completedFactKeyFor(event events.Event) completedFactKey { + key := completedFactKey{ + subject: event.Subject, + runID: event.RunID, + sessionID: event.SessionID, + stepID: event.StepID, + } + if event.DependsOnStepIDs != nil { + key.topologyKnown = true + if len(*event.DependsOnStepIDs) == 0 { + key.topologyCanonical = "[]" + return key + } + topology, _ := json.Marshal(*event.DependsOnStepIDs) + key.topologyCanonical = string(topology) + } + return key +} diff --git a/internal/molecule/cleanup.go b/internal/molecule/cleanup.go index a9e30e7d49..bdadc09fa7 100644 --- a/internal/molecule/cleanup.go +++ b/internal/molecule/cleanup.go @@ -83,6 +83,16 @@ func ListSubtree(store beads.Store, rootID string) ([]beads.Bead, error) { // Parent/child depth (deepest first) is used as the tie-breaker when no // blocks edge constrains the order. func CloseSubtree(store beads.Store, rootID string) (int, error) { + return CloseSubtreeWithMetadata(store, rootID, map[string]string{ + "close_reason": SubtreeClosedReason, + }) +} + +// CloseSubtreeWithMetadata closes the root bead and every open descendant, +// stamping metadata on each newly closed bead. It preserves CloseSubtree's +// descendant-first, blocker-first ordering and is idempotent for an already +// closed subtree. +func CloseSubtreeWithMetadata(store beads.Store, rootID string, metadata map[string]string) (int, error) { matched, err := ListSubtree(store, rootID) if err != nil { return 0, err @@ -141,7 +151,5 @@ func CloseSubtree(store beads.Store, rootID string) (int, error) { if err != nil { return 0, err } - return store.CloseAll(ordered, map[string]string{ - "close_reason": SubtreeClosedReason, - }) + return store.CloseAll(ordered, metadata) } diff --git a/internal/orders/order.go b/internal/orders/order.go index 43248d4c11..79683544d2 100644 --- a/internal/orders/order.go +++ b/internal/orders/order.go @@ -73,6 +73,18 @@ type Order struct { // (gastownhall/gascity#2893). Non-idempotent orders (the // default, false) keep failing CLOSED on gate timeout. Idempotent bool `toml:"idempotent,omitempty"` + // NoWorkGate opts an order out of the dispatcher's open-work gates + // entirely. It is for pure probes/sweeps that track NO bead work — + // e.g. provider-health-probe, a cooldown probe that only refreshes a + // cache. The open-work gates issue bd list/query reads against the + // store, bounded by orderGateTimeout; on store slowness they time out + // and the order is skipped every cycle (gastownhall/gascity#2893 + // dispatch starvation), so the probe never runs and its cache goes + // stale. Setting NoWorkGate skips both gates so the order dispatches + // on its trigger schedule regardless of store health. Single-flight + // is the author's responsibility: the order must be self-idempotent + // or interval-bounded, since no gate prevents an overlapping re-run. + NoWorkGate bool `toml:"no_work_gate,omitempty"` // Env is a map of environment variables exported into an exec // order's child process. Use the `[order.env]` TOML table to // override thresholds (e.g. GC_DOCTOR_LATENCY_WARN_S) without @@ -129,6 +141,7 @@ type orderDecode struct { CheckTimeout string `toml:"check_timeout,omitempty"` Enabled *bool `toml:"enabled,omitempty"` Idempotent bool `toml:"idempotent,omitempty"` + NoWorkGate bool `toml:"no_work_gate,omitempty"` Env map[string]string `toml:"env,omitempty"` Params map[string]OrderParam `toml:"params,omitempty"` SkipAliases []string `toml:"skip_aliases,omitempty"` @@ -155,6 +168,7 @@ func (d orderDecode) normalized() Order { CheckTimeout: d.CheckTimeout, Enabled: d.Enabled, Idempotent: d.Idempotent, + NoWorkGate: d.NoWorkGate, Env: d.Env, Params: d.Params, skipAliases: d.SkipAliases, diff --git a/internal/orders/order_test.go b/internal/orders/order_test.go index 68b3827cb5..ea59ba2bcd 100644 --- a/internal/orders/order_test.go +++ b/internal/orders/order_test.go @@ -91,6 +91,78 @@ func TestParseIdempotent(t *testing.T) { } } +// TestOrderNoWorkGateParsed covers vp-cixi.6: an order can opt out of the +// dispatcher's open-work gates via no_work_gate. Pure cooldown probes that +// track no beads (provider-health-probe) set this so a slow Dolt store can't +// time the gate out and skip the probe every cycle (#2893 dispatch starvation). +func TestOrderNoWorkGateParsed(t *testing.T) { + on, err := Parse([]byte("[order]\nexec = \"true\"\ntrigger = \"cooldown\"\ninterval = \"10m\"\nno_work_gate = true\n")) + if err != nil { + t.Fatalf("Parse: %v", err) + } + if !on.NoWorkGate { + t.Error("NoWorkGate = false, want true") + } + off, err := Parse([]byte("[order]\nexec = \"true\"\ntrigger = \"cooldown\"\ninterval = \"10m\"\n")) + if err != nil { + t.Fatalf("Parse: %v", err) + } + if off.NoWorkGate { + t.Error("NoWorkGate = true, want false (default)") + } + // Validate must accept the flag (no extra constraint). + if err := Validate(Order{Name: "probe", Exec: "true", Trigger: "cooldown", Interval: "10m", NoWorkGate: true}); err != nil { + t.Errorf("Validate with NoWorkGate: %v", err) + } +} + +// TestProviderHealthProbeOrderOptsOutOfWorkGate covers the deployed shape of +// provider-health-probe (vp-cixi.6 GAP D): a cooldown-triggered exec probe on +// a 10m interval with a real 120s timeout. The shipped pack will flip +// no_work_gate = true (sling S-1) so the dispatcher skips its open-work gates +// and a slow Dolt store can no longer time them out and skip the probe every +// cycle (#2893 dispatch starvation). This test pins the parse shape so the +// pack flip is mechanically known to be valid: WITH the flag the order opts +// out and passes Validate; WITHOUT it the order parses as a plain cooldown +// probe (NoWorkGate == false, the pre-S-1 default). +func TestProviderHealthProbeOrderOptsOutOfWorkGate(t *testing.T) { + base := `[order] +description = "Probe provider health" +exec = "$ORDER_DIR/scripts/provider-health-probe.sh" +trigger = "cooldown" +interval = "10m" +timeout = "120s" +` + on, err := Parse([]byte(base + "no_work_gate = true\n")) + if err != nil { + t.Fatalf("Parse (with flag): %v", err) + } + if !on.NoWorkGate { + t.Error("NoWorkGate = false, want true for opted-out probe") + } + if on.Trigger != "cooldown" || on.Interval != "10m" || on.Timeout != "120s" { + t.Errorf("probe shape mismatch: trigger=%q interval=%q timeout=%q", on.Trigger, on.Interval, on.Timeout) + } + if err := Validate(Order{ + Name: "provider-health-probe", + Exec: "$ORDER_DIR/scripts/provider-health-probe.sh", + Trigger: "cooldown", + Interval: "10m", + Timeout: "120s", + NoWorkGate: true, + }); err != nil { + t.Errorf("Validate provider-health-probe with NoWorkGate: %v", err) + } + + off, err := Parse([]byte(base)) + if err != nil { + t.Fatalf("Parse (without flag): %v", err) + } + if off.NoWorkGate { + t.Error("NoWorkGate = true, want false (default) for probe without the flag") + } +} + func TestValidateCooldown(t *testing.T) { a := Order{Name: "digest", Formula: "mol-digest", Trigger: "cooldown", Interval: "24h"} if err := Validate(a); err != nil { diff --git a/internal/orders/store.go b/internal/orders/store.go index 0c8c62eedd..acab59fae5 100644 --- a/internal/orders/store.go +++ b/internal/orders/store.go @@ -345,17 +345,30 @@ func (s *Store) CreateRunClosed(scoped string, outcome RunOutcome, cursor *Event // `gc order history` read (cmd_order.go): it confines the order-run-label List // and the bead->OrderRun decode. It reads through the raw store with TierMode // TierBoth (unioning wisp + issue tiers), byte-identical to the `gc order -// history` loop. +// history` loop. A non-positive limit reads every retained run. +// +// The limit is pushed to the backing (AllowBackingCreatedLimit): this read +// projects a newest-first listing, so the bound is over created_at — the very +// column the sort key uses — and a bounded backing read returns the same prefix +// the client-side cut would, up to which of two runs sharing a `created_at` +// lands on the last row. Fetching the full retained corpus and trimming +// afterwards is what made `gc order history` cost 22s on a city with 11k+ +// order-run rows (ga-klv). At the limit boundary the backing breaks created_at +// ties by id ASC rather than the canonical id DESC, so which of two runs sharing +// a timestamp lands on the last row can differ; for a history listing that is +// cosmetic, unlike the Cursor read (store_reads.go), whose max-seq reduction is +// over a different column and therefore must NOT opt in. func (s *Store) RecentRuns(scoped string, limit int) ([]OrderRun, error) { if s.store.Store == nil { return nil, nil } beadsList, err := s.store.List(beads.ListQuery{ - Label: labelOrderRunPrefix + scoped, - Limit: limit, - IncludeClosed: true, - Sort: beads.SortCreatedDesc, - TierMode: beads.TierBoth, + Label: labelOrderRunPrefix + scoped, + Limit: limit, + IncludeClosed: true, + Sort: beads.SortCreatedDesc, + TierMode: beads.TierBoth, + AllowBackingCreatedLimit: true, }) if err != nil { return decodeRuns(scoped, beadsList), err diff --git a/internal/orders/store_reads_bounded_test.go b/internal/orders/store_reads_bounded_test.go new file mode 100644 index 0000000000..8805bc100f --- /dev/null +++ b/internal/orders/store_reads_bounded_test.go @@ -0,0 +1,79 @@ +package orders + +import ( + "testing" + + "github.com/gastownhall/gascity/internal/beads" +) + +// TestLastRunIsBoundedToNewestRun is the regression guard for the read the +// order-firing doctor check depends on (ga-klv). The check answers "did this +// order fire recently", which needs exactly one row; if this query ever loses +// its bound it pulls the order's whole retained run history on a city with tens +// of thousands of order-run beads and blows the check's 15s budget. +func TestLastRunIsBoundedToNewestRun(t *testing.T) { + spy := &listSpyStore{Store: beads.NewMemStore()} + store := NewStore(beads.OrdersStore{Store: spy}) + + if _, err := store.LastRun("digest"); err != nil { + t.Fatalf("LastRun(): %v", err) + } + if len(spy.queries) == 0 { + t.Fatal("LastRun issued no list query") + } + for i, q := range spy.queries { + if q.Limit != 1 { + t.Fatalf("query %d: Limit = %d, want 1; an unbounded last-run read is the ga-klv doctor timeout", i, q.Limit) + } + if !q.AllowBackingCreatedLimit { + t.Fatalf("query %d: AllowBackingCreatedLimit = false, want true so the bound reaches the backing instead of being cut client-side", i) + } + if q.Sort != beads.SortCreatedDesc { + t.Fatalf("query %d: Sort = %v, want SortCreatedDesc so row one is the newest run", i, q.Sort) + } + } +} + +// TestRecentRunsPushesLimitToBacking guards the `gc order history` read. A +// positive limit must reach the backing: cutting client-side still fetches and +// serializes the full retained corpus, which is what made the command take 22s +// interactively on a city with 11k+ order-run rows (ga-klv). +func TestRecentRunsPushesLimitToBacking(t *testing.T) { + spy := &listSpyStore{Store: beads.NewMemStore()} + store := NewStore(beads.OrdersStore{Store: spy}) + + if _, err := store.RecentRuns("digest", 20); err != nil { + t.Fatalf("RecentRuns(): %v", err) + } + if len(spy.queries) == 0 { + t.Fatal("RecentRuns issued no list query") + } + for i, q := range spy.queries { + if q.Limit != 20 { + t.Fatalf("query %d: Limit = %d, want 20 (the caller's bound must be threaded through)", i, q.Limit) + } + if !q.AllowBackingCreatedLimit { + t.Fatalf("query %d: AllowBackingCreatedLimit = false, want true; the bound must reach the backing", i) + } + } +} + +// TestRecentRunsUnlimitedStaysUnlimited keeps the explicit opt-out working: a +// non-positive limit still means "every run", so `--limit 0` remains an honest +// escape hatch for operators who really do want the full history. +func TestRecentRunsUnlimitedStaysUnlimited(t *testing.T) { + spy := &listSpyStore{Store: beads.NewMemStore()} + store := NewStore(beads.OrdersStore{Store: spy}) + + if _, err := store.RecentRuns("digest", 0); err != nil { + t.Fatalf("RecentRuns(): %v", err) + } + if len(spy.queries) == 0 { + t.Fatal("RecentRuns issued no list query") + } + for i, q := range spy.queries { + if q.Limit != 0 { + t.Fatalf("query %d: Limit = %d, want 0 (unlimited opt-out)", i, q.Limit) + } + } +} diff --git a/internal/overlay/overlay.go b/internal/overlay/overlay.go index 3e17e7adfe..5b0561ffd7 100644 --- a/internal/overlay/overlay.go +++ b/internal/overlay/overlay.go @@ -45,7 +45,7 @@ func CopyFileOrDir(src, dst string, stderr io.Writer) error { // If srcDir does not exist, returns nil (no-op). // Individual file copy failures are logged to stderr but don't abort. func CopyDir(srcDir, dstDir string, stderr io.Writer) error { - return copyDir(srcDir, dstDir, stderr, nil) + return copyDir(srcDir, dstDir, stderr, nil, nil) } type preserveExistingFunc func(relPath string) bool @@ -61,12 +61,15 @@ type preserveExistingFunc func(relPath string) bool // legitimately needs to copy a tree containing a top-level `.gc/` would need a // variant that does not carry this guard. Names merely prefixed with ".gc" // (e.g. ".gcignore") are not matched. +// +// It is unconditional: a caller-supplied SkipFunc can only skip more, never +// re-enable staging of the runtime mirror. func skipRuntimeMirror(relPath string) bool { clean := filepath.Clean(relPath) return clean == ".gc" || strings.HasPrefix(clean, ".gc"+string(filepath.Separator)) } -func copyDir(srcDir, dstDir string, stderr io.Writer, preserveExisting preserveExistingFunc) error { +func copyDir(srcDir, dstDir string, stderr io.Writer, preserveExisting preserveExistingFunc, skip SkipFunc) error { info, err := os.Stat(srcDir) if os.IsNotExist(err) { return nil // Missing source dir is a no-op (like Gas Town). @@ -77,11 +80,14 @@ func copyDir(srcDir, dstDir string, stderr io.Writer, preserveExisting preserveE if !info.IsDir() { return fmt.Errorf("overlay: %q is not a directory", srcDir) } - return copyDirRecursive(srcDir, dstDir, "", stderr, preserveExisting) + return copyDirRecursive(srcDir, dstDir, "", stderr, preserveExisting, skip) } -// copyDirRecursive walks srcBase/rel and copies files into dstBase/rel. -func copyDirRecursive(srcBase, dstBase, rel string, stderr io.Writer, preserveExisting preserveExistingFunc) error { +// copyDirRecursive walks srcBase/rel and copies files into dstBase/rel. The +// runtime `.gc` mirror is always skipped. When skip is non-nil, entries for +// which it returns true are additionally omitted (files and whole subtrees), +// matching CopyDirWithSkip semantics on the best-effort path. +func copyDirRecursive(srcBase, dstBase, rel string, stderr io.Writer, preserveExisting preserveExistingFunc, skip SkipFunc) error { srcPath := srcBase if rel != "" { srcPath = filepath.Join(srcBase, rel) @@ -98,7 +104,7 @@ func copyDirRecursive(srcBase, dstBase, rel string, stderr io.Writer, preserveEx entryRel = filepath.Join(rel, entry.Name()) } - if skipRuntimeMirror(entryRel) { + if skipRuntimeMirror(entryRel) || (skip != nil && skip(entryRel, entry.IsDir())) { continue } @@ -109,7 +115,7 @@ func copyDirRecursive(srcBase, dstBase, rel string, stderr io.Writer, preserveEx fmt.Fprintf(stderr, "overlay: mkdir %q: %v\n", dstSubDir, err) //nolint:errcheck continue } - if err := copyDirRecursive(srcBase, dstBase, entryRel, stderr, preserveExisting); err != nil { + if err := copyDirRecursive(srcBase, dstBase, entryRel, stderr, preserveExisting, skip); err != nil { fmt.Fprintf(stderr, "overlay: %v\n", err) //nolint:errcheck } continue @@ -216,6 +222,29 @@ func HasProviderDir(srcDir, providerName string) bool { return err == nil && info.IsDir() } +// isPerProviderPath reports whether relPath is the per-provider/ directory +// itself or any entry beneath it. Universal overlay copies skip this subtree so +// per-provider files are staged only for the resolved provider slots. +func isPerProviderPath(relPath string) bool { + return relPath == PerProviderDir || filepath.Dir(relPath) == PerProviderDir || + len(relPath) > len(PerProviderDir)+1 && relPath[:len(PerProviderDir)+1] == PerProviderDir+string(filepath.Separator) +} + +// universalOverlaySkip composes the skips for the universal (non per-provider) +// copy phase. That phase runs through CopyDirWithSkip, which does not carry +// copyDirRecursive's unconditional runtime-mirror guard, so the guard is +// applied here explicitly: the runtime `.gc` mirror is never staged, the +// per-provider/ subtree is deferred to the resolved provider slots, and the +// caller's optional skip may only skip more. +func universalOverlaySkip(skip SkipFunc) SkipFunc { + return func(relPath string, isDir bool) bool { + if skipRuntimeMirror(relPath) || isPerProviderPath(relPath) { + return true + } + return skip != nil && skip(relPath, isDir) + } +} + // CopyDirForProvider copies overlay files with provider awareness: // 1. Copies everything EXCEPT the per-provider/ subtree (universal files). // 2. If per-provider// exists, copies its contents into dst @@ -234,23 +263,15 @@ func CopyDirForProvider(srcDir, dstDir, providerName string, stderr io.Writer) e return fmt.Errorf("overlay: %q is not a directory", srcDir) } - // Step 1: copy universal files (skip per-provider/). - skip := func(relPath string, _ bool) bool { - if skipRuntimeMirror(relPath) { - return true - } - // Skip the per-provider directory itself and all its contents. - return relPath == PerProviderDir || filepath.Dir(relPath) == PerProviderDir || - len(relPath) > len(PerProviderDir)+1 && relPath[:len(PerProviderDir)+1] == PerProviderDir+string(filepath.Separator) - } - if err := CopyDirWithSkip(srcDir, dstDir, skip, stderr); err != nil { + // Step 1: copy universal files (skip per-provider/ and the runtime mirror). + if err := CopyDirWithSkip(srcDir, dstDir, universalOverlaySkip(nil), stderr); err != nil { return err } // Step 2: copy provider-specific files (flattened into dst). if providerName != "" { providerDir := filepath.Join(srcDir, PerProviderDir, providerName) - if err := copyDir(providerDir, dstDir, stderr, providerPreserveExisting(providerName)); err != nil { + if err := copyDir(providerDir, dstDir, stderr, providerPreserveExisting(providerName), nil); err != nil { return err } } @@ -270,6 +291,26 @@ func CopyDirForProvider(srcDir, dstDir, providerName string, stderr io.Writer) e // wins when two providers ship the same rel path (last-writer-wins via // overwrite or JSON merge). func CopyDirForProviders(srcDir, dstDir string, providers []string, stderr io.Writer) error { + return CopyDirForProvidersWithSkip(srcDir, dstDir, providers, nil, stderr) +} + +// CopyDirForProvidersWithSkip behaves like CopyDirForProviders but additionally +// omits any file for which skip returns true, in BOTH the universal and the +// per-provider copy phases. +// +// It exists for the build_desired_state home-dir staging path: that +// path stages provider overlays and then runs hooks.Install on the SAME +// directory. Reconciler-owned mergeable files (overlay.IsMergeablePath — +// .codex/hooks.json et al.) must be skipped here so hooks.Install is the sole +// writer on that reconcile tick and the two writers cannot leave a permanent +// hybrid hook document. The runtime task-worktree staging path passes a nil +// skip and keeps staging those files, because there hooks.Install never runs +// and staging is the sole writer. +// +// The skip does not make hooks.Install the only writer everywhere: for a +// persistent agent, session-start staging writes the same paths via the +// nil-skip path, so a hybrid can reappear until the next tick converges it. +func CopyDirForProvidersWithSkip(srcDir, dstDir string, providers []string, skip SkipFunc, stderr io.Writer) error { info, err := os.Stat(srcDir) if os.IsNotExist(err) { return nil @@ -281,19 +322,14 @@ func CopyDirForProviders(srcDir, dstDir string, providers []string, stderr io.Wr return fmt.Errorf("overlay: %q is not a directory", srcDir) } - // Step 1: copy universal files (skip per-provider/). - skip := func(relPath string, _ bool) bool { - if skipRuntimeMirror(relPath) { - return true - } - return relPath == PerProviderDir || filepath.Dir(relPath) == PerProviderDir || - len(relPath) > len(PerProviderDir)+1 && relPath[:len(PerProviderDir)+1] == PerProviderDir+string(filepath.Separator) - } - if err := CopyDirWithSkip(srcDir, dstDir, skip, stderr); err != nil { + // Step 1: copy universal files (skip per-provider/, the runtime mirror, and + // caller-skipped paths). + if err := CopyDirWithSkip(srcDir, dstDir, universalOverlaySkip(skip), stderr); err != nil { return err } - // Step 2: copy per-provider slots in order, deduped. + // Step 2: copy per-provider slots in order, deduped. The caller skip is + // applied to the flattened per-provider rel paths (e.g. .codex/hooks.json). seen := make(map[string]bool, len(providers)) for _, p := range providers { if p == "" || seen[p] { @@ -301,7 +337,7 @@ func CopyDirForProviders(srcDir, dstDir string, providers []string, stderr io.Wr } seen[p] = true providerDir := filepath.Join(srcDir, PerProviderDir, p) - if err := copyDir(providerDir, dstDir, stderr, providerPreserveExisting(p)); err != nil { + if err := copyDir(providerDir, dstDir, stderr, providerPreserveExisting(p), skip); err != nil { return err } } diff --git a/internal/overlay/skip_mergeable_test.go b/internal/overlay/skip_mergeable_test.go new file mode 100644 index 0000000000..192e1172b6 --- /dev/null +++ b/internal/overlay/skip_mergeable_test.go @@ -0,0 +1,99 @@ +package overlay + +import ( + "io" + "os" + "path/filepath" + "testing" +) + +// TestCopyDirForProvidersWithSkip_SkipsMergeablePerProviderFile locks the core +// of the codex-hooks-drift fix: when the build_desired_state home-dir +// staging path passes an IsMergeablePath skip, the reconciler-owned mergeable +// hook file (.codex/hooks.json, shipped under per-provider/codex/) must NOT be +// staged, so a subsequent hooks.Install pass is the sole writer. Non-mergeable +// siblings and universal files must still be copied. +func TestCopyDirForProvidersWithSkip_SkipsMergeablePerProviderFile(t *testing.T) { + src := t.TempDir() + dst := t.TempDir() + + // Universal, non-mergeable file (must always copy). + mustWriteFile(t, filepath.Join(src, "AGENTS.md"), []byte("universal"), 0o644) + // Per-provider mergeable file (must be skipped when skip is supplied). + mustMkdirAll(t, filepath.Join(src, "per-provider", "codex", ".codex")) + mustWriteFile(t, filepath.Join(src, "per-provider", "codex", ".codex", "hooks.json"), []byte(`{"hooks":{}}`), 0o644) + // Per-provider non-mergeable file (must still copy). + mustWriteFile(t, filepath.Join(src, "per-provider", "codex", "AGENTS.codex.md"), []byte("codex"), 0o644) + + skip := func(relPath string, isDir bool) bool { + return !isDir && IsMergeablePath(relPath) + } + if err := CopyDirForProvidersWithSkip(src, dst, []string{"codex"}, skip, io.Discard); err != nil { + t.Fatalf("CopyDirForProvidersWithSkip: %v", err) + } + + if _, err := os.Stat(filepath.Join(dst, ".codex", "hooks.json")); !os.IsNotExist(err) { + t.Fatalf("mergeable .codex/hooks.json staged despite skip (err=%v); hooks.Install must be sole writer", err) + } + if got, err := os.ReadFile(filepath.Join(dst, "AGENTS.md")); err != nil || string(got) != "universal" { + t.Fatalf("universal AGENTS.md = %q err=%v, want %q staged", string(got), err, "universal") + } + if got, err := os.ReadFile(filepath.Join(dst, "AGENTS.codex.md")); err != nil || string(got) != "codex" { + t.Fatalf("per-provider non-mergeable AGENTS.codex.md = %q err=%v, want %q staged", string(got), err, "codex") + } +} + +// TestCopyDirForProvidersWithSkip_StillSkipsRuntimeMirrors locks the guard that +// a caller-supplied SkipFunc is strictly additive: supplying a skip must never +// re-enable staging of the runtime `.gc` mirror, in either the universal or the +// per-provider copy phase. TestCopyDirForProviders_SkipsRuntimeMirrors covers +// the nil-skip path; this is its non-nil counterpart. +func TestCopyDirForProvidersWithSkip_StillSkipsRuntimeMirrors(t *testing.T) { + src := t.TempDir() + dst := t.TempDir() + + mustWriteFile(t, filepath.Join(src, "AGENTS.md"), []byte("universal"), 0o644) + // Universal-phase runtime mirror. + mustMkdirAll(t, filepath.Join(src, ".gc", "agents", "mayor")) + mustWriteFile(t, filepath.Join(src, ".gc", "agents", "mayor", "AGENTS.md"), []byte("mirror"), 0o644) + // Per-provider-phase runtime mirror (flattens to a top-level .gc/). + mustMkdirAll(t, filepath.Join(src, "per-provider", "codex", ".gc", "worktrees", "polecat")) + mustWriteFile(t, filepath.Join(src, "per-provider", "codex", ".gc", "worktrees", "polecat", "AGENTS.md"), []byte("mirror"), 0o644) + mustWriteFile(t, filepath.Join(src, "per-provider", "codex", "AGENTS.codex.md"), []byte("codex"), 0o644) + + skip := func(relPath string, isDir bool) bool { + return !isDir && IsMergeablePath(relPath) + } + if err := CopyDirForProvidersWithSkip(src, dst, []string{"codex"}, skip, io.Discard); err != nil { + t.Fatalf("CopyDirForProvidersWithSkip: %v", err) + } + + if _, err := os.Stat(filepath.Join(dst, ".gc")); !os.IsNotExist(err) { + t.Fatalf("runtime .gc mirror staged despite the unconditional guard, stat err = %v", err) + } + if _, err := os.Stat(filepath.Join(dst, "AGENTS.md")); err != nil { + t.Fatalf("universal file should still be copied: %v", err) + } + if _, err := os.Stat(filepath.Join(dst, "AGENTS.codex.md")); err != nil { + t.Fatalf("per-provider file should still be copied: %v", err) + } +} + +// TestCopyDirForProviders_StagesMergeableFileWithoutSkip is the contrast case: +// the runtime task-worktree path passes no skip, so the mergeable codex hook +// file is still staged there (that path is codex's sole hook source for live +// task sessions and must not regress). +func TestCopyDirForProviders_StagesMergeableFileWithoutSkip(t *testing.T) { + src := t.TempDir() + dst := t.TempDir() + + mustMkdirAll(t, filepath.Join(src, "per-provider", "codex", ".codex")) + mustWriteFile(t, filepath.Join(src, "per-provider", "codex", ".codex", "hooks.json"), []byte(`{"hooks":{}}`), 0o644) + + if err := CopyDirForProviders(src, dst, []string{"codex"}, io.Discard); err != nil { + t.Fatalf("CopyDirForProviders: %v", err) + } + if _, err := os.Stat(filepath.Join(dst, ".codex", "hooks.json")); err != nil { + t.Fatalf("runtime path must still stage .codex/hooks.json: %v", err) + } +} diff --git a/internal/productmetrics/control_unix_test.go b/internal/productmetrics/control_unix_test.go index 6889a710c0..17b6720d96 100644 --- a/internal/productmetrics/control_unix_test.go +++ b/internal/productmetrics/control_unix_test.go @@ -1338,7 +1338,9 @@ func TestDisableAndPurgeExactTokenConflictAndPeerCleanRecovery(t *testing.T) { if err != nil { t.Fatal(err) } - service.deps.disableUploaderWait = testutil.GoroutineRaceTimeout + // Peer setup under the barrier can stretch under make test -p=N CPU + // contention; keep the quiescence budget above GoroutineRaceTimeout. + service.deps.disableUploaderWait = 2 * testutil.GoroutineRaceTimeout call := startDisableAndPurge(t, service) owner := waitForMetricsState(t, home, func(state persistedState) bool { return state.Preference == preferenceDisabled && state.CleanupKind == cleanupDisable @@ -1655,12 +1657,14 @@ func TestDisableAndPurgeRejectsUnprovenPeerSuccessor(t *testing.T) { return nil } deps.storageHooks.beforeStep = func(step storageStep) error { + // directorySync also runs during beginDisable; only inject once armed + // after the peer successor is written (do not wait — would deadlock). if armed.Load() && test.failSync && step == storageStepDirectorySync { return injected } return nil } - deps.disableUploaderWait = testutil.GoroutineRaceTimeout + deps.disableUploaderWait = 2 * testutil.GoroutineRaceTimeout service := mustOpenTestService(t, deps) call := startDisableAndPurge(t, service) owner := waitForMetricsState(t, home, func(state persistedState) bool { @@ -1708,16 +1712,27 @@ func TestDisableAndPurgeRejectsPeerSuccessorReplacedDuringCleanProof(t *testing. t.Fatal(err) } - var armed, replaced atomic.Bool + var replaced atomic.Bool + armed := make(chan struct{}) var replacement persistedState var replacementData []byte var replaceErr error replacementTemp := filepath.Join(home.Root(), ".peer-successor-replacement") configPath := filepath.Join(home.Root(), configFileName) deps := defaultTestServiceDependencies(home, 2) - deps.disableUploaderWait = testutil.GoroutineRaceTimeout + // Peer encoding + barrier hold can stretch under make test -p=N load. + deps.disableUploaderWait = 2 * testutil.GoroutineRaceTimeout deps.storageHooks.beforeStep = func(step storageStep) error { - if step != storageStepEnumerate || !armed.Load() || !replaced.CompareAndSwap(false, true) { + if step != storageStepEnumerate { + return nil + } + // beginDisable does not enumerate; the first enumerate is the clean-tree + // proof after the uploader lock. Wait for the test to arm so we never + // race past the injection point before replacementData is ready (#4653). + if !waitForTestArm(armed) { + return nil + } + if !replaced.CompareAndSwap(false, true) { return nil } if err := os.WriteFile(replacementTemp, replacementData, 0o600); err != nil { @@ -1740,7 +1755,7 @@ func TestDisableAndPurgeRejectsPeerSuccessorReplacedDuringCleanProof(t *testing. if err != nil { t.Fatal(err) } - armed.Store(true) + close(armed) if err := barrier.Release(); err != nil { t.Fatal(err) } @@ -2185,6 +2200,19 @@ func startDisableAndPurge(t *testing.T, service *Service) <-chan purgeCallResult return result } +// waitForTestArm blocks until armed is closed, or until GoroutineRaceTimeout, so a +// storage hook cannot inject before the test arms it under -p=N CPU starvation. +func waitForTestArm(armed <-chan struct{}) bool { + timer := time.NewTimer(testutil.GoroutineRaceTimeout) + defer timer.Stop() + select { + case <-armed: + return true + case <-timer.C: + return false + } +} + func receivePurgeCall(t *testing.T, call <-chan purgeCallResult) purgeCallResult { t.Helper() select { diff --git a/internal/productmetrics/lock_unix.go b/internal/productmetrics/lock_unix.go index 1489b0aa6f..4a79f452a1 100644 --- a/internal/productmetrics/lock_unix.go +++ b/internal/productmetrics/lock_unix.go @@ -23,24 +23,39 @@ type unixAdvisoryLock struct { } func (directory *unixStorageDirectory) acquireLock(ctx context.Context, name string) (storageLockBackend, error) { + lock, _, err := directory.acquireLockInternal(ctx, name, true) + return lock, err +} + +func (directory *unixStorageDirectory) tryAcquireLock(name string) (storageLockBackend, bool, error) { + return directory.acquireLockInternal(context.Background(), name, false) +} + +func (directory *unixStorageDirectory) acquireLockInternal( + ctx context.Context, + name string, + wait bool, +) (storageLockBackend, bool, error) { if !directory.mutable { - return nil, errors.New("productmetrics: read-only storage cannot acquire a lock") + return nil, false, errors.New("productmetrics: read-only storage cannot acquire a lock") } if !directory.rootDirectory { - return nil, errors.New("productmetrics: advisory locks are available only at the storage root") + return nil, false, errors.New("productmetrics: advisory locks are available only at the storage root") } - if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("productmetrics: acquire lock %q: %w", name, err) + if wait { + if err := ctx.Err(); err != nil { + return nil, false, fmt.Errorf("productmetrics: acquire lock %q: %w", name, err) + } } directoryFD, err := directory.duplicateFD() if err != nil { - return nil, err + return nil, false, err } defer closeUnixFD(directoryFD) path := filepath.Join(directory.path, name) lockFD, created, err := openStableLockFile(directoryFD, name) if err != nil { - return nil, storagePathError("open advisory lock", path, err) + return nil, false, storagePathError("open advisory lock", path, err) } closeLock := true defer func() { @@ -50,18 +65,18 @@ func (directory *unixStorageDirectory) acquireLock(ctx context.Context, name str }() if created { if err := unix.Fchmod(lockFD, 0o600); err != nil { - return nil, fmt.Errorf("productmetrics: set advisory-lock mode: %w", err) + return nil, false, fmt.Errorf("productmetrics: set advisory-lock mode: %w", err) } } if _, err := validateOpenedRegularFile(directoryFD, name, lockFD, path, directory.euid, created, directory.hooks); err != nil { - return nil, err + return nil, false, err } if created { if err := syncFileFD(lockFD, directory.hooks); err != nil { - return nil, fmt.Errorf("productmetrics: sync new advisory lock: %w", err) + return nil, false, fmt.Errorf("productmetrics: sync new advisory lock: %w", err) } if err := syncDirectoryFD(directoryFD, directory.hooks); err != nil { - return nil, fmt.Errorf("productmetrics: sync advisory-lock directory: %w", err) + return nil, false, fmt.Errorf("productmetrics: sync advisory-lock directory: %w", err) } } @@ -71,11 +86,13 @@ func (directory *unixStorageDirectory) acquireLock(ctx context.Context, name str } defer timer.Stop() for { - if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("productmetrics: acquire lock %q: %w", name, err) + if wait { + if err := ctx.Err(); err != nil { + return nil, false, fmt.Errorf("productmetrics: acquire lock %q: %w", name, err) + } } if err := directory.hooks.run(storageStepLock); err != nil { - return nil, fmt.Errorf("productmetrics: injected advisory-lock failure: %w", err) + return nil, false, fmt.Errorf("productmetrics: injected advisory-lock failure: %w", err) } err := unix.Flock(lockFD, unix.LOCK_EX|unix.LOCK_NB) if err == nil { @@ -85,22 +102,25 @@ func (directory *unixStorageDirectory) acquireLock(ctx context.Context, name str } if validationErr != nil { _ = unix.Flock(lockFD, unix.LOCK_UN) - return nil, validationErr + return nil, false, validationErr } if _, validationErr := validateOpenedRegularFile(directoryFD, name, lockFD, path, directory.euid, false, directory.hooks); validationErr != nil { _ = unix.Flock(lockFD, unix.LOCK_UN) - return nil, validationErr + return nil, false, validationErr } closeLock = false - return &unixAdvisoryLock{fd: lockFD}, nil + return &unixAdvisoryLock{fd: lockFD}, true, nil } if !errors.Is(err, unix.EWOULDBLOCK) && !errors.Is(err, unix.EAGAIN) && !errors.Is(err, unix.EINTR) { - return nil, fmt.Errorf("productmetrics: acquire advisory lock: %w", err) + return nil, false, fmt.Errorf("productmetrics: acquire advisory lock: %w", err) + } + if !wait { + return nil, false, nil } timer.Reset(advisoryLockRetryInterval) select { case <-ctx.Done(): - return nil, fmt.Errorf("productmetrics: acquire lock %q: %w", name, ctx.Err()) + return nil, false, fmt.Errorf("productmetrics: acquire lock %q: %w", name, ctx.Err()) case <-timer.C: } } diff --git a/internal/productmetrics/spawn.go b/internal/productmetrics/spawn.go index 9bca0d9940..fae11852de 100644 --- a/internal/productmetrics/spawn.go +++ b/internal/productmetrics/spawn.go @@ -491,11 +491,12 @@ func normalizePrivateUploaderLocale(value string) (string, bool) { } type privateUploaderRunDependencies struct { - now func() time.Time - start uploadStartFunc - budget spoolWorkBudget - uploaderLockWait time.Duration - beforeOperation func(uploaderOperation) + now func() time.Time + start uploadStartFunc + budget spoolWorkBudget + uploaderLockWait time.Duration + newUploaderLockContext func(context.Context, time.Duration) (context.Context, context.CancelFunc) + beforeOperation func(uploaderOperation) } // RunPrivateUploader runs one attempt-bound batch in a cooperative ten-second @@ -569,6 +570,9 @@ func (service *Service) runPrivateUploader( if dependencies.uploaderLockWait <= 0 || dependencies.uploaderLockWait > privateUploaderWorkBudget { dependencies.uploaderLockWait = privateUploaderLockWait } + if dependencies.newUploaderLockContext == nil { + dependencies.newUploaderLockContext = context.WithTimeout + } eligible, err := service.uploadNeedsMutableWork() if err != nil { return err @@ -581,12 +585,24 @@ func (service *Service) runPrivateUploader( return err } defer func() { returnErr = errors.Join(returnErr, root.Close()) }() - lockContext, cancelLock := context.WithTimeout(ctx, dependencies.uploaderLockWait) - uploader, err := service.lockUploader(lockContext, root) - cancelLock() + if err := ctx.Err(); err != nil { + return fmt.Errorf("productmetrics: acquire lock %q: %w", uploaderLockName, err) + } + uploader, acquired, err := service.tryLockUploader(root) if err != nil { return err } + if !acquired { + lockContext, cancelLock := dependencies.newUploaderLockContext(ctx, dependencies.uploaderLockWait) + if lockContext == nil || cancelLock == nil { + return errors.New("productmetrics: uploader-lock context factory returned an incomplete result") + } + uploader, err = service.lockUploader(lockContext, root) + cancelLock() + if err != nil { + return err + } + } defer func() { returnErr = errors.Join(returnErr, uploader.Close()) }() authorize := func(locked *lockedState) error { return validateSpawnAttemptLocked(locked, invocation.attemptToken, dependencies.now().UTC()) diff --git a/internal/productmetrics/spawn_unix_test.go b/internal/productmetrics/spawn_unix_test.go index 74b6130077..103003e59e 100644 --- a/internal/productmetrics/spawn_unix_test.go +++ b/internal/productmetrics/spawn_unix_test.go @@ -1220,6 +1220,50 @@ func TestPrivateUploaderLosingUploaderLockPerformsZeroNetworkWork(t *testing.T) } } +func TestPrivateUploaderAttemptsFreeLockBeforeStartingContentionWait(t *testing.T) { + home := newMetricsTestHome(t) + writeStateFixture(t, home, activeEnabledStateForSpawnTest()) + root := mustOpenMutableRoot(t, home) + event := testSpoolEvent(testEventIDOne, "1.0.0", testRecordHour, CommandHelp) + data := writeSpoolEventFixture(t, root, queueDirectoryName, testSpoolGeneration, event) + if err := persistSpoolQuota(root, spoolQuota{Events: 1, Bytes: uint64(len(data))}); err != nil { + t.Fatal(err) + } + writeSpawnThrottleToRoot(t, root, spawnThrottleRecord{attemptToken: testSpawnTokenOne, attemptedAt: testRecordHour}) + if err := root.Close(); err != nil { + t.Fatal(err) + } + deps := spawnTestDependencies(home, func() time.Time { return testRecordHour }, func() (string, error) { + return testSpawnTokenTwo, nil + }) + deps.getenv = func(name string) string { + if name == privateUploaderMarkerEnvironment { + return privateUploaderMarkerValue + } + return "" + } + service := mustOpenTestService(t, deps) + + contentionContexts := 0 + sends := 0 + err := service.runPrivateUploader(context.Background(), PrivateUploaderInvocation{attemptToken: testSpawnTokenOne}, privateUploaderRunDependencies{ + uploaderLockWait: 20 * time.Millisecond, + newUploaderLockContext: func(context.Context, time.Duration) (context.Context, context.CancelFunc) { + contentionContexts++ + expired, cancel := context.WithCancel(context.Background()) + cancel() + return expired, func() {} + }, + start: immediateUploadStart(func(context.Context, preparedUploadBatch, uint64) (uploadResponse, error) { + sends++ + return uploadResponse{kind: uploadResponseAccepted, statusCode: http.StatusOK}, nil + }), + }) + if err != nil || sends != 1 || contentionContexts != 0 { + t.Fatalf("free-lock child = err:%v sends:%d contention-contexts:%d, want one send before contention timing", err, sends, contentionContexts) + } +} + func TestPurgeAndCleanProofRequireSpawnThrottleAbsent(t *testing.T) { home := newMetricsTestHome(t) writeStateFixture(t, home, disabledState(7, 2, cleanupDisable)) diff --git a/internal/productmetrics/storage.go b/internal/productmetrics/storage.go index bc4aa6bec5..86845fe4bb 100644 --- a/internal/productmetrics/storage.go +++ b/internal/productmetrics/storage.go @@ -398,6 +398,7 @@ type storageDirectoryBackend interface { unlinkEnumeratedEntry(storageEntry) error removeEnumeratedDirectory(storageEntry) error removeEnumeratedCleanupDirectory(storageEntry) error + tryAcquireLock(string) (storageLockBackend, bool, error) acquireLock(context.Context, string) (storageLockBackend, error) cleanupOnlyHandle() bool } @@ -872,6 +873,17 @@ func (directory *storageDir) acquireLock(ctx context.Context, name string) (*adv return &advisoryLock{backend: backend}, nil } +func (directory *storageDir) tryAcquireUploaderLock() (*advisoryLock, bool, error) { + if directory == nil || directory.backend == nil { + return nil, false, errStorageClosed + } + backend, acquired, err := directory.backend.tryAcquireLock(uploaderLockName) + if err != nil || !acquired { + return nil, false, err + } + return &advisoryLock{backend: backend}, true, nil +} + func (lock *advisoryLock) Release() error { if lock == nil || lock.backend == nil { return nil diff --git a/internal/productmetrics/storage_unix_test.go b/internal/productmetrics/storage_unix_test.go index 0a3df0d106..7017439ee4 100644 --- a/internal/productmetrics/storage_unix_test.go +++ b/internal/productmetrics/storage_unix_test.go @@ -3678,6 +3678,39 @@ func TestStorageAdvisoryLockUsesStableInodeAndHonorsContext(t *testing.T) { } } +func TestStorageTryUploaderLockDistinguishesFreeAndContended(t *testing.T) { + inspection := inspectStorageTestHome(t, true) + firstRoot, err := openStorageRootMutable(inspection) + if err != nil { + t.Fatal(err) + } + defer func() { _ = firstRoot.Close() }() + secondRoot, err := openStorageRootMutable(inspection) + if err != nil { + t.Fatal(err) + } + defer func() { _ = secondRoot.Close() }() + + first, acquired, err := firstRoot.tryAcquireUploaderLock() + if err != nil || !acquired { + t.Fatalf("first tryAcquireUploaderLock = (%v, %v), want acquired", acquired, err) + } + second, acquired, err := secondRoot.tryAcquireUploaderLock() + if err != nil || acquired || second != nil { + t.Fatalf("contended tryAcquireUploaderLock = (%v, %v, %v), want no lock and no error", second, acquired, err) + } + if err := first.Release(); err != nil { + t.Fatal(err) + } + second, acquired, err = secondRoot.tryAcquireUploaderLock() + if err != nil || !acquired { + t.Fatalf("tryAcquireUploaderLock after release = (%v, %v), want acquired", acquired, err) + } + if err := second.Release(); err != nil { + t.Fatal(err) + } +} + func TestStorageCloseRacesOperationsWithTypedClosedResult(t *testing.T) { inspection := inspectStorageTestHome(t, true) seed, err := openStorageRootMutable(inspection) diff --git a/internal/productmetrics/uploader.go b/internal/productmetrics/uploader.go index baef6a84fa..77e2680a03 100644 --- a/internal/productmetrics/uploader.go +++ b/internal/productmetrics/uploader.go @@ -92,6 +92,20 @@ func (service *Service) lockUploader(ctx context.Context, root *storageRoot) (*l return &lockedUploader{root: root, lock: lock}, nil } +func (service *Service) tryLockUploader(root *storageRoot) (*lockedUploader, bool, error) { + if service == nil { + return nil, false, errors.New("productmetrics: service is nil") + } + if root == nil { + return nil, false, errStorageClosed + } + lock, acquired, err := root.tryAcquireUploaderLock() + if err != nil || !acquired { + return nil, false, err + } + return &lockedUploader{root: root, lock: lock}, true, nil +} + func (service *Service) uploadOneBatch(ctx context.Context, dependencies uploaderDependencies) (result uploadRunResult, returnErr error) { if service == nil { return result, errors.New("productmetrics: service is nil") diff --git a/internal/runtime/staging.go b/internal/runtime/staging.go index f7610cca18..e14e3c2041 100644 --- a/internal/runtime/staging.go +++ b/internal/runtime/staging.go @@ -2,6 +2,7 @@ package runtime import ( "bytes" + "crypto/sha256" "fmt" "io" "os" @@ -11,6 +12,31 @@ import ( "github.com/gastownhall/gascity/internal/overlay" ) +// HashHookSettingsContent returns a content hash for a probed hook/settings +// file that is stable across JSON serialization differences. For reconciler-owned +// mergeable settings files (overlay.IsMergeablePath — .gemini/settings.json, +// .codex/hooks.json, etc.) it hashes the canonical JSON form, so a compact +// document and its pretty-printed equivalent fingerprint identically. +// +// This keeps the CopyFiles fingerprint deterministic even though these files +// are rewritten into canonical form out of band by the reconciler — runtime +// overlay staging (StageProviderOverlayDir → MergeSettingsJSON) or hooks.Install. +// Without canonicalization the pre-fingerprint probe could hash a raw +// non-canonical document on one tick and its canonical rewrite on the next, +// producing spurious core-fingerprint drift. Non-mergeable paths, unreadable +// files, and non-JSON content fall back to raw content hashing (HashPathContent). +func HashHookSettingsContent(path, relPath string) string { + if overlay.IsMergeablePath(relPath) { + if data, err := os.ReadFile(path); err == nil { + if canon, cErr := overlay.CanonicalJSON(data); cErr == nil { + sum := sha256.Sum256(canon) + return fmt.Sprintf("%x", sum) + } + } + } + return HashPathContent(path) +} + // StageWorkDir applies a legacy overlay directory and CopyFiles staging before // a provider starts the session process. func StageWorkDir(workDir, overlayDir string, copyFiles []CopyEntry) error { @@ -102,10 +128,49 @@ func stageCopyFiles(workDir string, copyFiles []CopyEntry) error { } // StageProviderOverlayDir copies a provider-aware overlay directory into a -// work directory and writes nonfatal preservation warnings to warnings. +// work directory and writes nonfatal preservation warnings to warnings. This is +// the runtime task-worktree staging path: it stages every overlay file +// (including reconciler-owned mergeable hook files) because staging is the sole +// writer for live task sessions — hooks.Install never runs against these dirs. func StageProviderOverlayDir(srcDir, dstDir string, providers []string, warnings io.Writer) error { + return stageProviderOverlayDir(srcDir, dstDir, providers, nil, warnings) +} + +// StageProviderOverlayDirSkippingMergeable copies a provider-aware overlay +// directory into a work directory like StageProviderOverlayDir, but skips +// reconciler-owned mergeable settings/hook files (overlay.IsMergeablePath — +// .codex/hooks.json, .claude/settings.json, etc.). +// +// It is used only by the build_desired_state home-dir staging path, +// which stages overlays and then immediately runs hooks.Install on the SAME +// directory. Skipping the mergeable files here makes hooks.Install the sole +// writer ON THE RECONCILE TICK, so the two writers can no longer disagree on +// hook-entry matchers and leave a permanent codex-hooks-drift hybrid. +// +// Not a global invariant: for a persistent (non-task) agent the home dir is +// also the session workDir, and session-start staging reaches these same paths +// through the non-skipping StageProviderOverlayDir (tmux.stageStartFiles, +// StageSessionWorkDir). A hybrid can therefore reappear at session start and is +// converged by the next tick — permanent drift becomes transient. +func StageProviderOverlayDirSkippingMergeable(srcDir, dstDir string, providers []string, warnings io.Writer) error { + skip := func(relPath string, isDir bool) bool { + return !isDir && overlay.IsMergeablePath(relPath) + } + return stageProviderOverlayDir(srcDir, dstDir, providers, skip, warnings) +} + +// stageProviderOverlayDir stages srcDir into dstDir for the given provider +// slots, omitting any entry for which skip returns true (nil skips nothing). +// +// skip is spelled as an unnamed func type rather than overlay.SkipFunc — to +// which it stays assignable — because every declaration in package runtime must +// type-check with module-local imports stubbed out: the provider-double +// boundary guard (internal/testutil/providerledger) checks this package +// hermetically and requires module-local references to stay inside function +// bodies. +func stageProviderOverlayDir(srcDir, dstDir string, providers []string, skip func(relPath string, isDir bool) bool, warnings io.Writer) error { var stderr bytes.Buffer - if err := overlay.CopyDirForProviders(srcDir, dstDir, providers, &stderr); err != nil { + if err := overlay.CopyDirForProvidersWithSkip(srcDir, dstDir, providers, skip, &stderr); err != nil { return err } nonfatal, fatal := splitOverlayWarnings(stderr.String()) diff --git a/internal/runtime/staging_hash_test.go b/internal/runtime/staging_hash_test.go new file mode 100644 index 0000000000..95c35e7b8c --- /dev/null +++ b/internal/runtime/staging_hash_test.go @@ -0,0 +1,110 @@ +package runtime + +import ( + "os" + "path/filepath" + "testing" +) + +// HashHookSettingsContent canonicalizes JSON only for overlay.IsMergeablePath +// files, so that a compact document and its pretty-printed equivalent produce +// the same fingerprint. Everything else — non-mergeable paths, non-JSON bodies, +// unreadable/missing files — must fall back to raw HashPathContent. +// +// These cases pin the fingerprint contract directly. The convergence tests +// exercise it only indirectly, so a regression that made canonicalization a +// no-op (or applied it too widely) would otherwise surface as spurious +// core-fingerprint drift and an extra agent restart, not as a test failure. + +// writeHashTestFile writes body to a temp file named after relPath's base and +// returns its absolute path. +func writeHashTestFile(t *testing.T, relPath, body string) string { + t.Helper() + dir := t.TempDir() + path := filepath.Join(dir, filepath.Base(relPath)) + if err := os.WriteFile(path, []byte(body), 0o644); err != nil { + t.Fatalf("write %s: %v", path, err) + } + return path +} + +func TestHashHookSettingsContent_MergeableCanonicalizesJSON(t *testing.T) { + const relPath = ".codex/hooks.json" + compact := `{"hooks":{"SessionStart":[{"matcher":"","hooks":[]}]}}` + pretty := `{ + "hooks": { + "SessionStart": [ + { + "matcher": "", + "hooks": [] + } + ] + } +} +` + compactHash := HashHookSettingsContent(writeHashTestFile(t, relPath, compact), relPath) + prettyHash := HashHookSettingsContent(writeHashTestFile(t, relPath, pretty), relPath) + + if compactHash == "" || prettyHash == "" { + t.Fatalf("empty hash: compact=%q pretty=%q", compactHash, prettyHash) + } + if compactHash != prettyHash { + t.Errorf("compact and pretty-printed %s must hash identically:\n compact=%s\n pretty =%s", + relPath, compactHash, prettyHash) + } +} + +func TestHashHookSettingsContent_MergeableIgnoresKeyOrder(t *testing.T) { + const relPath = ".claude/settings.json" + first := HashHookSettingsContent( + writeHashTestFile(t, relPath, `{"alpha":1,"beta":2}`), relPath) + second := HashHookSettingsContent( + writeHashTestFile(t, relPath, `{"beta":2,"alpha":1}`), relPath) + + if first != second { + t.Errorf("canonical JSON must sort keys, so these must hash identically:\n first =%s\n second=%s", + first, second) + } +} + +func TestHashHookSettingsContent_NonMergeablePathFallsBackToRaw(t *testing.T) { + // Same logical document, different serialization, on a path that is NOT + // mergeable: no canonicalization, so the raw bytes decide the hash. + const relPath = ".codex/config.json" + compactPath := writeHashTestFile(t, relPath, `{"a":1}`) + prettyPath := writeHashTestFile(t, relPath, "{\n \"a\": 1\n}\n") + + compactHash := HashHookSettingsContent(compactPath, relPath) + prettyHash := HashHookSettingsContent(prettyPath, relPath) + + if want := HashPathContent(compactPath); compactHash != want { + t.Errorf("non-mergeable path must fall back to HashPathContent: got %s want %s", compactHash, want) + } + if compactHash == prettyHash { + t.Errorf("non-mergeable path must NOT canonicalize; compact and pretty both hashed %s", compactHash) + } +} + +func TestHashHookSettingsContent_NonJSONBodyFallsBackToRaw(t *testing.T) { + // A mergeable path whose content does not parse: CanonicalJSON fails and the + // raw content hash is used rather than an empty or panicking result. + const relPath = ".codex/hooks.json" + path := writeHashTestFile(t, relPath, "this is not json\n") + + got := HashHookSettingsContent(path, relPath) + if want := HashPathContent(path); got != want { + t.Errorf("unparseable mergeable file must fall back to HashPathContent: got %s want %s", got, want) + } +} + +func TestHashHookSettingsContent_MissingFileMatchesRawHash(t *testing.T) { + // An absent probe target must agree with HashPathContent so a file that has + // not been staged yet does not read as a distinct fingerprint. + const relPath = ".codex/hooks.json" + missing := filepath.Join(t.TempDir(), "hooks.json") + + got := HashHookSettingsContent(missing, relPath) + if want := HashPathContent(missing); got != want { + t.Errorf("missing mergeable file must match HashPathContent: got %s want %s", got, want) + } +} diff --git a/internal/runtime/staging_skip_mergeable_test.go b/internal/runtime/staging_skip_mergeable_test.go new file mode 100644 index 0000000000..cba2d4ecae --- /dev/null +++ b/internal/runtime/staging_skip_mergeable_test.go @@ -0,0 +1,92 @@ +package runtime + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +// codexHooksOverlaySrc seeds a provider overlay dir with a codex hooks file +// (mergeable) and a non-mergeable sibling under per-provider/codex/, returning +// the overlay source root. +func codexHooksOverlaySrc(t *testing.T) string { + t.Helper() + src := t.TempDir() + codexDir := filepath.Join(src, "per-provider", "codex", ".codex") + if err := os.MkdirAll(codexDir, 0o755); err != nil { + t.Fatalf("mkdir codex overlay: %v", err) + } + if err := os.WriteFile(filepath.Join(codexDir, "hooks.json"), []byte(`{"hooks":{"SessionStart":[]}}`), 0o644); err != nil { + t.Fatalf("write codex hooks overlay: %v", err) + } + if err := os.WriteFile(filepath.Join(src, "per-provider", "codex", "AGENTS.codex.md"), []byte("codex"), 0o644); err != nil { + t.Fatalf("write codex sibling overlay: %v", err) + } + return src +} + +// TestStageProviderOverlayDirSkippingMergeableSkipsCodexHooks is the horizon +// guard (invariant #3): the build_desired_state staging entry point +// must skip reconciler-owned mergeable files while still staging non-mergeable +// siblings, so hooks.Install remains the sole writer in the home dir. +func TestStageProviderOverlayDirSkippingMergeableSkipsCodexHooks(t *testing.T) { + t.Parallel() + + src := codexHooksOverlaySrc(t) + workDir := t.TempDir() + + if err := StageProviderOverlayDirSkippingMergeable(src, workDir, []string{"codex"}, nil); err != nil { + t.Fatalf("StageProviderOverlayDirSkippingMergeable: %v", err) + } + if _, err := os.Stat(filepath.Join(workDir, ".codex", "hooks.json")); !os.IsNotExist(err) { + t.Fatalf(".codex/hooks.json staged by home-dir path (err=%v); must be skipped so hooks.Install is sole writer", err) + } + if _, err := os.Stat(filepath.Join(workDir, "AGENTS.codex.md")); err != nil { + t.Fatalf("non-mergeable sibling should still stage: %v", err) + } +} + +// TestStageProviderOverlayDirStagesCodexHooks locks the no-regression contract +// (invariant #3 / #2): the runtime task-worktree path (plain +// StageProviderOverlayDir, used by StageSessionWorkDir) still writes the codex +// hook file, which is the only hook source for live task sessions. +func TestStageProviderOverlayDirStagesCodexHooks(t *testing.T) { + t.Parallel() + + src := codexHooksOverlaySrc(t) + workDir := t.TempDir() + + if err := StageProviderOverlayDir(src, workDir, []string{"codex"}, nil); err != nil { + t.Fatalf("StageProviderOverlayDir: %v", err) + } + if _, err := os.Stat(filepath.Join(workDir, ".codex", "hooks.json")); err != nil { + t.Fatalf("runtime path must stage .codex/hooks.json (codex live-session hook source): %v", err) + } +} + +// TestStageSessionWorkDirStagesFunctionalCodexHooks is the no-regression test +// (invariant #2) at the session-staging boundary: StageSessionWorkDir, invoked +// on every codex task-session Start, must still write a functional +// .codex/hooks.json (SessionStart present). The fix must not touch this path. +func TestStageSessionWorkDirStagesFunctionalCodexHooks(t *testing.T) { + t.Parallel() + + src := codexHooksOverlaySrc(t) + workDir := t.TempDir() + + if err := StageSessionWorkDir(Config{ + WorkDir: workDir, + ProviderName: "codex", + PackOverlayDirs: []string{src}, + }); err != nil { + t.Fatalf("StageSessionWorkDir: %v", err) + } + data, err := os.ReadFile(filepath.Join(workDir, ".codex", "hooks.json")) + if err != nil { + t.Fatalf("codex task worktree missing .codex/hooks.json (P1 regression): %v", err) + } + if !strings.Contains(string(data), "SessionStart") { + t.Fatalf("staged codex hooks not functional, want SessionStart: %s", data) + } +} diff --git a/internal/runtime/tmux/adapter.go b/internal/runtime/tmux/adapter.go index 1ceae848fa..2e2c999a90 100644 --- a/internal/runtime/tmux/adapter.go +++ b/internal/runtime/tmux/adapter.go @@ -1317,7 +1317,14 @@ func launchOrchestration(ctx context.Context, ops startOps, name string, cfg run } if cfg.Nudge != "" { if err := ops.sendKeys(name, cfg.Nudge); err != nil { - return fmt.Errorf("sending startup nudge: %w", err) + // The startup nudge has no retry-capable caller: the keystrokes + // reached tmux and the session is verified alive above, so an + // unconfirmed submit is a warning, not a start failure. Any other + // error still fails the start. + if !errors.Is(err, ErrNudgeSubmitUnconfirmed) { + return fmt.Errorf("sending startup nudge: %w", err) + } + fmt.Fprintf(os.Stderr, "warning: startup nudge to %q delivered but not confirmed: %v\n", name, err) } } diff --git a/internal/runtime/tmux/nudge_poke_integration_test.go b/internal/runtime/tmux/nudge_poke_integration_test.go index 0ec48fac71..e384f0aeef 100644 --- a/internal/runtime/tmux/nudge_poke_integration_test.go +++ b/internal/runtime/tmux/nudge_poke_integration_test.go @@ -3,6 +3,7 @@ package tmux import ( + "errors" "os" "testing" "time" @@ -47,7 +48,12 @@ func TestNudgePokeRealTmux(t *testing.T) { time.Sleep(300 * time.Millisecond) callStart := time.Now() - if err := tm.NudgeSession(sess, "# gc-nudge-neverbusy"); err != nil { + // A never-busy claude pane cannot confirm the submit, so + // ErrNudgeSubmitUnconfirmed is the correct, expected outcome (ra-3x46cy + // finding 1: this must no longer collapse to a false "delivered" nil). + // The keystrokes still reached tmux (delivered=true is set before this + // return), so the poke below must still be recorded. + if err := tm.NudgeSession(sess, "# gc-nudge-neverbusy"); err != nil && !errors.Is(err, ErrNudgeSubmitUnconfirmed) { t.Fatalf("NudgeSession: %v", err) } callEnd := time.Now() diff --git a/internal/runtime/tmux/nudge_submit_confirm_integration_test.go b/internal/runtime/tmux/nudge_submit_confirm_integration_test.go index 92bf3ee330..2314dd879d 100644 --- a/internal/runtime/tmux/nudge_submit_confirm_integration_test.go +++ b/internal/runtime/tmux/nudge_submit_confirm_integration_test.go @@ -3,6 +3,7 @@ package tmux import ( + "errors" "fmt" "os" "os/exec" @@ -127,3 +128,41 @@ func TestNudgeSessionReEntersUntilSubmittedForClaude(t *testing.T) { t.Fatalf("never reached submitted/busy state after re-send:\n%s", out) } } + +// TestNudgeSessionReturnsUnconfirmedErrorWhenNeverBusyForClaude is the +// regression test for ra-3x46cy finding 1: pre-fix, NudgeSession discarded +// the confirmed bool from submitEnterAndConfirm and reported nil ("clean +// delivery") even when the agent's busy indicator was never observed within +// budget — the exact condition that let a drafted-but-unsubmitted nudge go +// undetected for 15+ minutes. NudgeSession must now surface +// ErrNudgeSubmitUnconfirmed instead, so a retry-capable caller (the queue +// dispatcher) does not ack the item. +func TestNudgeSessionReturnsUnconfirmedErrorWhenNeverBusyForClaude(t *testing.T) { + if !hasTmux() { + t.Skip("tmux not installed") + } + tm := testTmux() + dir := t.TempDir() + fake := buildBusyOnEnterBinary(t, dir, "fakeclaude-neverbusy") + sessionName := fmt.Sprintf("gt-test-nudge-unconfirmed-%d", time.Now().UnixNano()%100000) + + _ = tm.KillSession(sessionName) + if err := tm.NewSessionWithCommandAndEnv(sessionName, dir, fake, map[string]string{ + "GC_PROVIDER": "claude", + // Far beyond submitEnterMaxSends * submitConfirmPollsPerSend: busy is + // never observed within the confirm budget. + "GC_TEST_BUSY_AFTER": "100", + }); err != nil { + t.Fatalf("NewSessionWithCommandAndEnv: %v", err) + } + defer func() { _ = tm.KillSession(sessionName) }() + time.Sleep(300 * time.Millisecond) + + err := tm.NudgeSession(sessionName, "hello-unconfirmed") + if err == nil { + t.Fatal("NudgeSession err = nil, want ErrNudgeSubmitUnconfirmed (an unconfirmed submit must not report clean delivery)") + } + if !errors.Is(err, ErrNudgeSubmitUnconfirmed) { + t.Fatalf("err = %v, want errors.Is(err, ErrNudgeSubmitUnconfirmed)", err) + } +} diff --git a/internal/runtime/tmux/nudge_submit_key_sequence_integration_test.go b/internal/runtime/tmux/nudge_submit_key_sequence_integration_test.go new file mode 100644 index 0000000000..bd192a7ed5 --- /dev/null +++ b/internal/runtime/tmux/nudge_submit_key_sequence_integration_test.go @@ -0,0 +1,96 @@ +//go:build integration + +package tmux + +import ( + "fmt" + "os" + "strings" + "testing" + "time" +) + +// TestSendNudgeSubmitSequenceSendsEachKeyInOrder is a live-tmux integration +// test proving sendNudgeSubmitSequence actually emits every key in the +// declared sequence, not just the last one. cat -v echoes control bytes as +// visible caret notation (Escape -> "^["), so a multi-key sequence leaves a +// distinguishing mark in the pane a single-Enter sequence would not. +func TestSendNudgeSubmitSequenceSendsEachKeyInOrder(t *testing.T) { + if !hasTmux() { + t.Skip("tmux not installed") + } + + tm := testTmux() + sessionName := "gt-test-submit-seq-" + fmt.Sprintf("%d", time.Now().UnixNano()%10000) + + _ = tm.KillSession(sessionName) + if err := tm.NewSessionWithCommandAndEnv(sessionName, os.TempDir(), "cat -v", nil); err != nil { + t.Fatalf("NewSessionWithCommandAndEnv: %v", err) + } + defer func() { _ = tm.KillSession(sessionName) }() + time.Sleep(300 * time.Millisecond) + + if err := tm.sendNudgeSubmitSequence(sessionName, []string{"Escape", "Enter"}); err != nil { + t.Fatalf("sendNudgeSubmitSequence: %v", err) + } + time.Sleep(300 * time.Millisecond) + + out, err := tm.CapturePaneAll(sessionName) + if err != nil { + t.Fatalf("CapturePaneAll: %v", err) + } + if !strings.Contains(out, "^[") { + t.Fatalf("CapturePaneAll missing Escape for a declared [Escape, Enter] sequence:\n%s", out) + } +} + +// TestNudgeSessionUsesDeclaredSequenceForProviderFamily proves NudgeSession +// itself (not just the low-level primitive) resolves and sends a registered +// family's declared sequence — the actual wiring a future ra-oudpha +// finding-3 fix would depend on. Registers a throwaway "testfam" family +// pointing at [Escape, Enter] so this doesn't depend on (or change) any +// real provider's shipped behavior. +func TestNudgeSessionUsesDeclaredSequenceForProviderFamily(t *testing.T) { + if !hasTmux() { + t.Skip("tmux not installed") + } + + origSeq := nudgeSubmitKeySequences + nudgeSubmitKeySequences = map[string][]string{"testfam": {"Escape", "Enter"}} + defer func() { nudgeSubmitKeySequences = origSeq }() + + // Step 3 of NudgeSession (unrelated to this patch) also sends a + // pre-submit Escape for any family NOT in this skip list. "testfam" is + // unregistered there, so without also skipping it here, that pre-existing + // step would inject its own "^[" and this test would pass regardless of + // whether the new declarative submit sequence (step 5) is wired up — + // skip it so the observed Escape can only come from step 5. + origSkip := providersSkippingEscapeBeforeEnter + providersSkippingEscapeBeforeEnter = append(append([]string(nil), origSkip...), "testfam") + defer func() { providersSkippingEscapeBeforeEnter = origSkip }() + + tm := testTmux() + sessionName := "gt-test-nudge-testfam-" + fmt.Sprintf("%d", time.Now().UnixNano()%10000) + + _ = tm.KillSession(sessionName) + if err := tm.NewSessionWithCommandAndEnv(sessionName, os.TempDir(), "cat -v", map[string]string{ + "GC_PROVIDER": "testfam", + }); err != nil { + t.Fatalf("NewSessionWithCommandAndEnv: %v", err) + } + defer func() { _ = tm.KillSession(sessionName) }() + time.Sleep(300 * time.Millisecond) + + if err := tm.NudgeSession(sessionName, "hello"); err != nil { + t.Fatalf("NudgeSession: %v", err) + } + time.Sleep(300 * time.Millisecond) + + out, err := tm.CapturePaneAll(sessionName) + if err != nil { + t.Fatalf("CapturePaneAll: %v", err) + } + if !strings.Contains(out, "^[") { + t.Fatalf("CapturePaneAll missing Escape for testfam's declared [Escape, Enter] submit sequence:\n%s", out) + } +} diff --git a/internal/runtime/tmux/nudge_submit_key_sequence_test.go b/internal/runtime/tmux/nudge_submit_key_sequence_test.go new file mode 100644 index 0000000000..096464ba84 --- /dev/null +++ b/internal/runtime/tmux/nudge_submit_key_sequence_test.go @@ -0,0 +1,36 @@ +package tmux + +import "testing" + +// TestNudgeSubmitKeySequenceForFamilyDefaultsToEnter pins the declarative +// table's fallback: a family with no explicit entry in +// nudgeSubmitKeySequences gets the single-Enter default, matching every +// provider's historical behavior before this table existed. +func TestNudgeSubmitKeySequenceForFamilyDefaultsToEnter(t *testing.T) { + for _, family := range []string{"claude", "codex", "gemini", "", "some-unregistered-family"} { + got := nudgeSubmitKeySequenceForFamily(family) + if len(got) != 1 || got[0] != "Enter" { + t.Errorf("nudgeSubmitKeySequenceForFamily(%q) = %v, want [Enter] (no entries are registered today)", family, got) + } + } +} + +// TestNudgeSubmitKeySequenceForFamilyHonorsTableEntry proves the lookup +// actually reads nudgeSubmitKeySequences rather than always returning the +// default — this is the mechanism a future claude-specific (or codex, per +// upstream #4706) fix would rely on. +func TestNudgeSubmitKeySequenceForFamilyHonorsTableEntry(t *testing.T) { + orig := nudgeSubmitKeySequences + nudgeSubmitKeySequences = map[string][]string{"testfam": {"Escape", "Enter"}} + defer func() { nudgeSubmitKeySequences = orig }() + + got := nudgeSubmitKeySequenceForFamily("testfam") + want := []string{"Escape", "Enter"} + if len(got) != len(want) || got[0] != want[0] || got[1] != want[1] { + t.Fatalf("nudgeSubmitKeySequenceForFamily(testfam) = %v, want %v", got, want) + } + // An unrelated family is unaffected by testfam's entry. + if got := nudgeSubmitKeySequenceForFamily("claude"); len(got) != 1 || got[0] != "Enter" { + t.Fatalf("nudgeSubmitKeySequenceForFamily(claude) = %v, want [Enter]", got) + } +} diff --git a/internal/runtime/tmux/startup_test.go b/internal/runtime/tmux/startup_test.go index c37cfd925b..fb45209809 100644 --- a/internal/runtime/tmux/startup_test.go +++ b/internal/runtime/tmux/startup_test.go @@ -906,34 +906,59 @@ func TestDoStartSession_KimiSkipsStartupDialogAcceptance(t *testing.T) { } func TestDoStartSessionReturnsNudgeDeliveryError(t *testing.T) { - ops := &fakeStartOps{ - hasSessionResult: true, - sendKeysErr: errors.New("command too long"), - } - - cfg := runtime.Config{ - Command: "kimi", - Nudge: strings.Repeat("startup prompt\n", 100), - } - - err := doStartSession(context.Background(), ops, "test", cfg, DefaultConfig().SetupTimeout) - if err == nil { - t.Fatal("expected startup nudge delivery error, got nil") - } - if !strings.Contains(err.Error(), "sending startup nudge") { - t.Fatalf("error = %v, want startup nudge context", err) - } - if !strings.Contains(err.Error(), "command too long") { - t.Fatalf("error = %v, want original nudge error", err) - } - - assertCallSequence(t, ops, []string{ + wantCalls := []string{ "createSession", "setRemainOnExit", "disableMouseAndActivity", "hasSession", "isSessionRunning", "sendKeys", + } + + t.Run("generic delivery error is fatal", func(t *testing.T) { + ops := &fakeStartOps{ + hasSessionResult: true, + sendKeysErr: errors.New("command too long"), + } + + cfg := runtime.Config{ + Command: "kimi", + Nudge: strings.Repeat("startup prompt\n", 100), + } + + err := doStartSession(context.Background(), ops, "test", cfg, DefaultConfig().SetupTimeout) + if err == nil { + t.Fatal("expected startup nudge delivery error, got nil") + } + if !strings.Contains(err.Error(), "sending startup nudge") { + t.Fatalf("error = %v, want startup nudge context", err) + } + if !strings.Contains(err.Error(), "command too long") { + t.Fatalf("error = %v, want original nudge error", err) + } + + assertCallSequence(t, ops, wantCalls) + }) + + // The startup nudge has no retry-capable caller, so an unconfirmed submit + // must not fail the start: the keystrokes reached tmux and the session is + // already verified alive. Only genuine delivery errors are fatal (above). + t.Run("unconfirmed submit is not fatal", func(t *testing.T) { + ops := &fakeStartOps{ + hasSessionResult: true, + sendKeysErr: fmt.Errorf("%w: session %q", ErrNudgeSubmitUnconfirmed, "test"), + } + + cfg := runtime.Config{ + Command: "claude", + Nudge: "startup prompt", + } + + if err := doStartSession(context.Background(), ops, "test", cfg, DefaultConfig().SetupTimeout); err != nil { + t.Fatalf("doStartSession = %v, want nil for an unconfirmed startup nudge", err) + } + + assertCallSequence(t, ops, wantCalls) }) } diff --git a/internal/runtime/tmux/tmux.go b/internal/runtime/tmux/tmux.go index 94f0fb55f9..bef2bfef7b 100644 --- a/internal/runtime/tmux/tmux.go +++ b/internal/runtime/tmux/tmux.go @@ -48,6 +48,55 @@ const pollInterval = 100 * time.Millisecond // alongside the family name. var providersSkippingEscapeBeforeEnter = []string{"claude", "codex", "copilot", "gemini", "grok", "kimi", "mimocode", "mimo", ".mimocode", "opencode", "pi", "antigravity"} +// defaultNudgeSubmitKeySequence is the ordered tmux key names sent, in +// order, to submit a pasted nudge for a provider family with no explicit +// entry in nudgeSubmitKeySequences. A single "Enter" is the historical, +// still-correct behavior for every family this fork has verified. +var defaultNudgeSubmitKeySequence = []string{"Enter"} + +// nudgeSubmitKeySequences declares, per provider family, the ordered tmux +// key names sent (via sendNudgeSubmitSequence) to submit a pasted nudge — +// the "declarative per-provider nudge submit-key sequence" design from +// upstream gastownhall/gascity#4706. A family with no entry here gets +// defaultNudgeSubmitKeySequence. +// +// #4706 was filed against a k8s codex agent whose first turn never started: +// codex's TUI buffers a send-keys burst as a paste, so a lone trailing Enter +// is swallowed as a composer newline rather than treated as submit — codex's +// actual submit sequence is Escape then Enter. This fork's tmux carrier does +// not yet carry that fix; adding it here is left to a follow-up once the +// change is exercised against a live codex TUI in this repo's own test +// harness (it is out of scope for this claude-focused patch, but the table +// exists precisely so that follow-up is a one-line addition, not another +// pass through the delivery mechanics). +// +// This table does NOT yet contain an entry for the claude-specific stall +// this patch was scoped to fix (ra-oudpha finding-3 / gascity#5012, #5013's +// "LIVE RESIDUAL": a claude TUI composer left with pasted-but-unsubmitted +// text even after the unconfirmed-submit and clear-before-paste fixes +// landed). Investigation (see ra-oudpha comments) could not identify a wrong +// key as the cause — #4706 itself specifies claude's default submit +// sequence as plain Enter, which is what this fork already sends, and the +// live specimens showed text sitting visibly unsubmitted (not a +// silently-succeeded-but-unconfirmed false negative), ruling out a busy- +// indicator detection gap as the explanation too. Pinning the actual cause +// needs a live trace this fork-patch pass does not have access to (the city +// this bead is scoped against is live and read-only for this pass). Once +// traced, the fix — whatever key sequence or timing claude's TUI turns out +// to need — is a single entry in this table plus a test, not a rewrite of +// NudgeSession. +var nudgeSubmitKeySequences = map[string][]string{} + +// nudgeSubmitKeySequenceForFamily returns the declared submit key sequence +// for a provider family, or defaultNudgeSubmitKeySequence when the family +// has no explicit entry. +func nudgeSubmitKeySequenceForFamily(family string) []string { + if seq, ok := nudgeSubmitKeySequences[family]; ok { + return seq + } + return defaultNudgeSubmitKeySequence +} + // Config holds configurable timeouts and intervals for the tmux provider. // All fields have sensible defaults matching the original hardcoded values. type Config struct { @@ -144,6 +193,16 @@ var ( ErrSessionNotFound = errors.New("session not found") ErrInvalidSessionName = errors.New("invalid session name") ErrIdleTimeout = errors.New("agent not idle before timeout") + // ErrNudgeSubmitUnconfirmed indicates the submit Enter was handed to tmux + // but the agent's busy indicator was never observed within budget: the + // message may be sitting drafted-but-unsubmitted in the pane. Callers + // that can retry (the nudge queue dispatcher, the idle-claim backstop) + // must treat this the same as an undelivered nudge: the queue must not + // ack the item, so it requeues after the normal retry delay and consumes + // one of its bounded attempts, exactly like any other delivery failure. + // ga-bwm proved that treating an unconfirmed submit as a clean success is + // exactly what lets a stalled nudge go undetected for many minutes. + ErrNudgeSubmitUnconfirmed = errors.New("nudge: submit Enter delivered to tmux but not confirmed (busy state never observed)") // ErrServerDegraded indicates the tmux server bound to SocketName is // reachable on the filesystem but unresponsive. Creating a new session // in this state would let tmux's own (very short) liveness probe time @@ -1772,21 +1831,24 @@ const ( submitReEnterBackoff = 200 * time.Millisecond ) -// submitEnterAndConfirm sends Enter and confirms the message submitted by -// observing the agent transition to its busy/processing state. It re-sends -// Enter only while the pane remains idle (submission not yet observed), so a -// turn that already started can never receive a second Enter. +// submitEnterAndConfirm sends the provider's submit key sequence (see +// nudgeSubmitKeySequences — a single Enter for every family this fork has +// verified so far) and confirms the message submitted by observing the +// agent transition to its busy/processing state. It re-sends the sequence +// only while the pane remains idle (submission not yet observed), so a turn +// that already started can never receive a second submit. // // Returns: // - (true, nil) — the agent went busy: the message submitted. -// - (false, nil) — Enter was delivered to tmux but busy was never observed -// within the budget (best-effort; preserves the historical "nil == handed -// to tmux" contract so callers do not re-paste). -// - (false, err) — every Enter send failed at the tmux layer. +// - (false, nil) — the submit sequence was delivered to tmux but busy was +// never observed within the budget (best-effort; preserves the +// historical "nil == handed to tmux" contract so callers do not +// re-paste). +// - (false, err) — every submit attempt failed at the tmux layer. // // All side effects are injected so the decision logic is unit-testable without // a live tmux server. -func submitEnterAndConfirm(sendEnter func() error, wake func(), busy func() (bool, error), sleep func(time.Duration)) (bool, error) { +func submitEnterAndConfirm(sendSubmit func() error, wake func(), busy func() (bool, error), sleep func(time.Duration)) (bool, error) { var lastErr error for send := 0; send < submitEnterMaxSends; send++ { if send > 0 { @@ -1797,7 +1859,7 @@ func submitEnterAndConfirm(sendEnter func() error, wake func(), busy func() (boo } sleep(submitReEnterBackoff) } - if err := sendEnter(); err != nil { + if err := sendSubmit(); err != nil { lastErr = err continue } @@ -1834,6 +1896,48 @@ func (t *Tmux) submitVerifyEligible(target string) bool { return t.targetLooksLikeProvider(target, "claude") } +// nudgeSubmitKeySequence resolves target's declared submit key sequence (see +// nudgeSubmitKeySequences), identifying the provider family the same way +// submitVerifyEligible and shouldSendEscapeBeforeEnter do: prefer the +// GC_PROVIDER pane environment variable, falling back to a process-name +// sniff for panes without it (ad hoc sessions, some test harnesses). +func (t *Tmux) nudgeSubmitKeySequence(target string) []string { + if provider := t.providerEnv(target); provider != "" { + return nudgeSubmitKeySequenceForFamily(sessionlog.ProviderFamily(provider)) + } + for family := range nudgeSubmitKeySequences { + if t.targetLooksLikeProvider(target, family) { + return nudgeSubmitKeySequenceForFamily(family) + } + } + return defaultNudgeSubmitKeySequence +} + +// nudgeSubmitKeySettle is the pause between successive keys within a +// multi-key submit sequence (e.g. a hypothetical Escape-then-Enter entry) — +// long enough for the TUI to process the first key's effect before the next +// arrives, short enough not to meaningfully lengthen the existing submit +// budget. Not used when the sequence has a single key (today's default for +// every family), so it changes no existing timing. +const nudgeSubmitKeySettle = 100 * time.Millisecond + +// sendNudgeSubmitSequence sends target's declared provider-family submit key +// sequence as an ordered series of tmux send-keys calls, pausing +// nudgeSubmitKeySettle between keys. Returns the first error encountered; +// remaining keys are not sent after an error, matching sendEnter's previous +// single-key contract (the caller decides how to react to a failed submit). +func (t *Tmux) sendNudgeSubmitSequence(target string, keys []string) error { + for i, key := range keys { + if i > 0 { + time.Sleep(nudgeSubmitKeySettle) + } + if _, err := t.run("send-keys", "-t", target, key); err != nil { + return err + } + } + return nil +} + // NudgeSession sends a message to a Claude Code session reliably. // This is the canonical way to send messages to Claude sessions. // Uses: literal mode + 500ms debounce + separate Enter. @@ -1910,19 +2014,33 @@ func (t *Tmux) NudgeSession(session, message string) error { // detached but drop the submit key until a terminal resize wakes their loop. t.WakePaneIfDetached(session) - // 5. Send Enter and, for providers with a reliable busy indicator, confirm - // the draft actually submitted — re-sending Enter only while the pane stays - // idle. A lost submit Enter (raced against the paste or a detached-pane - // wake) is the ga-bwm "drafted but not submitted" stall; confirming here - // removes the town's dependence on an external observer re-kicking the - // session. Providers without a reliable indicator keep best-effort delivery. - sendEnter := func() error { _, err := t.run("send-keys", "-t", target, "Enter"); return err } + // 5. Send the provider's declared submit key sequence (see + // nudgeSubmitKeySequences — default plain Enter) and, for providers with + // a reliable busy indicator, confirm the draft actually submitted — + // re-sending the sequence only while the pane stays idle. A lost submit + // (raced against the paste or a detached-pane wake) is the ga-bwm + // "drafted but not submitted" stall; confirming here removes the town's + // dependence on an external observer re-kicking the session. Providers + // without a reliable indicator keep best-effort delivery. + submitKeys := t.nudgeSubmitKeySequence(target) + sendSubmit := func() error { return t.sendNudgeSubmitSequence(target, submitKeys) } wake := func() { t.WakePaneIfDetached(session) } if t.submitVerifyEligible(target) { - if _, err := submitEnterAndConfirm(sendEnter, wake, func() (bool, error) { return t.paneBusy(target) }, time.Sleep); err != nil { - return fmt.Errorf("failed to send Enter: %w", err) + confirmed, err := submitEnterAndConfirm(sendSubmit, wake, func() (bool, error) { return t.paneBusy(target) }, time.Sleep) + if err != nil { + return fmt.Errorf("failed to send submit sequence: %w", err) } delivered = true + if !confirmed { + // Do NOT collapse this to nil: a caller that treats nil as "clean + // delivery" would ack a queued nudge for a message that may still + // be sitting drafted-but-unsubmitted in the pane. Surfacing this + // as an error leaves the item unacked, so it requeues after the + // normal retry delay and spends one of its bounded attempts — + // the same handling as any other delivery failure — instead of + // silently losing the nudge. + return fmt.Errorf("%w: session %q", ErrNudgeSubmitUnconfirmed, session) + } return nil } // Fallback: best-effort single delivery (unchanged historical behavior). @@ -1931,7 +2049,7 @@ func (t *Tmux) NudgeSession(session, message string) error { if attempt > 0 { time.Sleep(submitReEnterBackoff) } - if err := sendEnter(); err != nil { + if err := sendSubmit(); err != nil { lastErr = err continue } @@ -1940,7 +2058,7 @@ func (t *Tmux) NudgeSession(session, message string) error { delivered = true return nil } - return fmt.Errorf("failed to send Enter after %d attempts: %w", submitEnterMaxSends, lastErr) + return fmt.Errorf("failed to send submit sequence after %d attempts: %w", submitEnterMaxSends, lastErr) } // NudgePane sends a message to a specific pane reliably. @@ -1984,13 +2102,15 @@ func (t *Tmux) NudgePane(pane, message string) error { // happens before and after submit. t.WakePaneIfDetached(pane) - // 5. Send Enter with retry (critical for message submission) + // 5. Send the provider's declared submit key sequence with retry + // (critical for message submission). See NudgeSession/nudgeSubmitKeySequences. + submitKeys := t.nudgeSubmitKeySequence(pane) var lastErr error for attempt := 0; attempt < 3; attempt++ { if attempt > 0 { time.Sleep(200 * time.Millisecond) } - if _, err := t.run("send-keys", "-t", pane, "Enter"); err != nil { + if err := t.sendNudgeSubmitSequence(pane, submitKeys); err != nil { lastErr = err continue } @@ -1999,7 +2119,7 @@ func (t *Tmux) NudgePane(pane, message string) error { delivered = true return nil } - return fmt.Errorf("failed to send Enter after 3 attempts: %w", lastErr) + return fmt.Errorf("failed to send submit sequence after 3 attempts: %w", lastErr) } func (t *Tmux) shouldSendEscapeBeforeEnter(target string) bool { diff --git a/internal/runtime/tmux/tmux_test.go b/internal/runtime/tmux/tmux_test.go index 149e0a7742..06ae4207bc 100644 --- a/internal/runtime/tmux/tmux_test.go +++ b/internal/runtime/tmux/tmux_test.go @@ -2451,7 +2451,14 @@ func TestNudgeSessionSkipsEscapeForClaude(t *testing.T) { defer func() { _ = tm.KillSession(sessionName) }() time.Sleep(300 * time.Millisecond) - if err := tm.NudgeSession(sessionName, "hello"); err != nil { + // The "claude" provider is submit-verify-eligible, so NudgeSession waits to + // observe a busy indicator before reporting success — but the fake command + // here is plain `cat -v`, which can never produce one. That makes + // ErrNudgeSubmitUnconfirmed the correct, expected outcome (see + // ra-3x46cy/finding 1: NudgeSession must no longer swallow this into a + // false "delivered" nil). This test only cares whether Escape was sent + // before the paste, which is unaffected by the confirm outcome. + if err := tm.NudgeSession(sessionName, "hello"); err != nil && !errors.Is(err, ErrNudgeSubmitUnconfirmed) { t.Fatalf("NudgeSession: %v", err) } time.Sleep(300 * time.Millisecond) diff --git a/internal/session/REQUIREMENTS.md b/internal/session/REQUIREMENTS.md index e10874996f..d418674af1 100644 --- a/internal/session/REQUIREMENTS.md +++ b/internal/session/REQUIREMENTS.md @@ -108,6 +108,7 @@ unless the row names how they map to the canonical projection. | SESSION-ID-009 | Mail is session-targeting | Mail rejects template factory targets and bare ordinary config recipients. Bare configured named session mail uses the configured mailbox without materializing a session; existing live named session mail uses the live mailbox. | `internal/api/session_model_phase0_interface_spec_test.go` | | SESSION-ID-010 | Aliasless multi-session identity | Aliasless multi-session or pool sessions use generated concrete runtime identities so independent sessions do not collide. | `internal/session/manager_test.go`; `cmd/gc/session_template_start_test.go` | | SESSION-ID-011 | API target classification ladder | API session target resolution classifies through a fixed ladder: template-form rejection, exact bead ID, configured named session (lookup errors and matched outcomes are terminal — no fallthrough to live matching; conflicts and ambiguity surface as the carried step error), live session_name then alias (named-session matches whose configured identity is absent are rejected by config, on live-only and allow-closed surfaces alike), live path alias by title, then on allow-closed surfaces only: named-spec rejection ahead of closed session_name then closed alias. Lookups run one vector at a time and stop at the first terminal outcome. | `internal/session/target_classifier.go` (`DecideSessionTarget`); `internal/session/target_classifier_test.go`; `internal/api/session_resolution_precedence_test.go`; `internal/api/session_resolution_path_alias_test.go`; `internal/api/session_materialization_guard_test.go` | +| SESSION-ID-012 | Bead actor aligns with canonical alias | The durable ownership identity (`AssigneeIdentifier`) is alias-first: current public alias, then configured named identity, then runtime session name, falling back to the bead ID. `GC_AGENT` and `BEADS_ACTOR` both carry this identity (GC_AGENT mirrors for compatibility), so a session owns work under the same exact string it presents to bd. `SyncRuntimeAlias` updates `GC_ALIAS`/`GC_AGENT`/`BEADS_ACTOR` in the runtime metadata together and rolls back already-applied keys on partial failure. | `internal/session/assignee_identities.go` (`AssigneeIdentifier`); `internal/session/lifecycle.go` (`SyncRuntimeAlias`); `internal/session/lifecycle_actor_test.go`; upstream commit `2e1a9cf76` (#4981) | ### Start, Wake, Suspend, Close diff --git a/internal/session/assignee_identities.go b/internal/session/assignee_identities.go index e26714a167..87ac55e0a4 100644 --- a/internal/session/assignee_identities.go +++ b/internal/session/assignee_identities.go @@ -46,17 +46,15 @@ func AssigneeIdentities(i Info) []string { return identities } -// AssigneeIdentifier returns the durable agent-facing identity form of a -// session — its session_name, else alias, else configured named identity — -// falling back to the bead ID when no name metadata is present so a resolved -// assignment is never silently cleared. This is the form the agent claims and -// verifies work with (BEADS_ACTOR / GC_SESSION_NAME), so stamping it keeps -// assign/update consistent with the claim path (which already stores the raw -// session-name) and with the form-agnostic matching in AssigneeIdentities. -// Stamping the bare bead ID here instead made template-routed continuation work -// unclaimable by name-matching agents. +// AssigneeIdentifier returns the durable agent-facing ownership identity of a +// session: its current public alias, configured named identity, or runtime +// session name, falling back to the bead ID when no name metadata is present. +// This is the same alias-first identity RuntimeEnvWithSessionContext exposes +// through GC_ALIAS and BEADS_ACTOR; GC_AGENT mirrors it only for compatibility. +// Keeping API assignment normalization on this rule prevents one session from +// owning work under a different exact string than it presents to bd. func AssigneeIdentifier(i Info) string { - for _, v := range []string{i.SessionNameMetadata, i.Alias, i.ConfiguredNamedIdentity} { + for _, v := range []string{i.Alias, i.ConfiguredNamedIdentity, i.SessionNameMetadata} { if v = strings.TrimSpace(v); v != "" { return v } diff --git a/internal/session/assignee_identities_test.go b/internal/session/assignee_identities_test.go index f4836a7654..2698df743b 100644 --- a/internal/session/assignee_identities_test.go +++ b/internal/session/assignee_identities_test.go @@ -130,20 +130,20 @@ func TestAssigneeIdentifier(t *testing.T) { want string }{ { - name: "session_name wins", + name: "alias wins", info: Info{ID: "s1", SessionNameMetadata: "sn", Alias: "al", ConfiguredNamedIdentity: "ni"}, - want: "sn", - }, - { - name: "alias when no session_name", - info: Info{ID: "s1", Alias: "al", ConfiguredNamedIdentity: "ni"}, want: "al", }, { - name: "configured named identity when no session_name or alias", - info: Info{ID: "s1", ConfiguredNamedIdentity: "ni"}, + name: "configured named identity when no alias", + info: Info{ID: "s1", SessionNameMetadata: "sn", ConfiguredNamedIdentity: "ni"}, want: "ni", }, + { + name: "session_name when no public identity", + info: Info{ID: "s1", SessionNameMetadata: "sn"}, + want: "sn", + }, { name: "bead id fallback when no name metadata", info: Info{ID: "s1"}, @@ -156,8 +156,8 @@ func TestAssigneeIdentifier(t *testing.T) { }, { name: "values trimmed", - info: Info{ID: "s1", SessionNameMetadata: " sn "}, - want: "sn", + info: Info{ID: "s1", Alias: " al ", SessionNameMetadata: " sn "}, + want: "al", }, } for _, tt := range tests { diff --git a/internal/session/chat.go b/internal/session/chat.go index e6848ac7b2..14b77cd3db 100644 --- a/internal/session/chat.go +++ b/internal/session/chat.go @@ -373,11 +373,7 @@ func (m *Manager) ensureRunning(ctx context.Context, id string, b beads.Bead, se b.Metadata["instance_token"] = instanceToken } cfg.Env = mergeEnv(cfg.Env, RuntimeEnvWithSessionContext( - id, - sessName, - strings.TrimSpace(b.Metadata["alias"]), - strings.TrimSpace(b.Metadata["template"]), - strings.TrimSpace(b.Metadata["session_origin"]), + infoFromPersistedBead(b), generation, continuationEpoch, instanceToken, @@ -492,11 +488,7 @@ func (m *Manager) ensureRunningRuntimeOnly(ctx context.Context, id string, b bea b.Metadata["instance_token"] = instanceToken } cfg.Env = mergeEnv(cfg.Env, RuntimeEnvWithSessionContext( - id, - sessName, - strings.TrimSpace(b.Metadata["alias"]), - strings.TrimSpace(b.Metadata["template"]), - strings.TrimSpace(b.Metadata["session_origin"]), + infoFromPersistedBead(b), generation, continuationEpoch, instanceToken, diff --git a/internal/session/lifecycle.go b/internal/session/lifecycle.go index 9000c81e81..8010575195 100644 --- a/internal/session/lifecycle.go +++ b/internal/session/lifecycle.go @@ -3,7 +3,10 @@ package session import ( "crypto/rand" "encoding/hex" + "errors" + "fmt" "strconv" + "strings" "github.com/gastownhall/gascity/internal/runtime" ) @@ -56,32 +59,81 @@ func RuntimeEnvWithAlias(sessionID, sessionName, alias string, generation, conti return env } -// RuntimeEnvWithSessionContext extends RuntimeEnvWithAlias with the -// session-model context shared by controller, CLI, and API starts. -func RuntimeEnvWithSessionContext(sessionID, sessionName, alias, template, origin string, generation, continuationEpoch int, instanceToken string) map[string]string { - env := RuntimeEnvWithAlias(sessionID, sessionName, alias, generation, continuationEpoch, instanceToken) - if template != "" { +// RuntimeEnvWithSessionContext projects one session Info into the runtime +// identity environment shared by controller, CLI, and API starts. Keeping the +// runtime handle and raw persisted identity on Info lets AssigneeIdentifier +// choose the exact same ownership string as API assignment normalization, +// including the bead-ID fallback for a repairable session with no stored name. +func RuntimeEnvWithSessionContext(info Info, generation, continuationEpoch int, instanceToken string) map[string]string { + publicAlias := runtimePublicAlias(info) + env := RuntimeEnvWithAlias(info.ID, info.SessionName, publicAlias, generation, continuationEpoch, instanceToken) + if template := strings.TrimSpace(info.Template); template != "" { env["GC_TEMPLATE"] = template } - if origin != "" { + if origin := strings.TrimSpace(info.SessionOrigin); origin != "" { env["GC_SESSION_ORIGIN"] = origin } - if alias != "" { - env["GC_AGENT"] = alias - } else if sessionName != "" { - env["GC_AGENT"] = sessionName + if identity := AssigneeIdentifier(info); identity != "" { + env["GC_AGENT"] = identity + env["BEADS_ACTOR"] = identity } return env } -// SyncRuntimeAlias updates the live runtime session metadata to reflect the -// current public alias. Clearing the alias removes GC_ALIAS from the runtime. -func SyncRuntimeAlias(sp runtime.Provider, sessionName, alias string) error { +func runtimePublicAlias(info Info) string { + if alias := strings.TrimSpace(info.Alias); alias != "" { + return alias + } + return strings.TrimSpace(info.ConfiguredNamedIdentity) +} + +// SyncRuntimeAlias updates live runtime metadata from the session's current +// public alias and durable ownership identity. Clearing an alias therefore +// falls back to the same raw session name or bead ID that API assignment uses. +func SyncRuntimeAlias(sp runtime.Provider, info Info) error { + sessionName := strings.TrimSpace(info.SessionName) if sp == nil || sessionName == "" { return nil } - if alias == "" { - return sp.RemoveMeta(sessionName, "GC_ALIAS") + type metaUpdate struct { + key string + value string + remove bool + } + publicAlias := runtimePublicAlias(info) + identity := AssigneeIdentifier(info) + updates := []metaUpdate{ + {key: "GC_ALIAS", value: publicAlias, remove: publicAlias == ""}, + {key: "GC_AGENT", value: identity, remove: identity == ""}, + {key: "BEADS_ACTOR", value: identity, remove: identity == ""}, + } + previous := make(map[string]string, len(updates)) + for _, update := range updates { + value, err := sp.GetMeta(sessionName, update.key) + if err != nil { + return fmt.Errorf("reading %s before runtime identity update: %w", update.key, err) + } + previous[update.key] = value + } + apply := func(update metaUpdate) error { + if update.remove { + return sp.RemoveMeta(sessionName, update.key) + } + return sp.SetMeta(sessionName, update.key, update.value) + } + applied := make([]metaUpdate, 0, len(updates)) + for _, update := range updates { + if err := apply(update); err != nil { + errs := []error{fmt.Errorf("updating runtime identity %s: %w", update.key, err)} + for i := len(applied) - 1; i >= 0; i-- { + rollback := metaUpdate{key: applied[i].key, value: previous[applied[i].key], remove: previous[applied[i].key] == ""} + if rollbackErr := apply(rollback); rollbackErr != nil { + errs = append(errs, fmt.Errorf("rolling back runtime identity %s: %w", rollback.key, rollbackErr)) + } + } + return errors.Join(errs...) + } + applied = append(applied, update) } - return sp.SetMeta(sessionName, "GC_ALIAS", alias) + return nil } diff --git a/internal/session/lifecycle_actor_test.go b/internal/session/lifecycle_actor_test.go new file mode 100644 index 0000000000..f938034674 --- /dev/null +++ b/internal/session/lifecycle_actor_test.go @@ -0,0 +1,130 @@ +package session + +import ( + "errors" + "testing" + + "github.com/gastownhall/gascity/internal/runtime" +) + +type failingMetaProvider struct { + runtime.Provider + failKey string +} + +func (p failingMetaProvider) SetMeta(name, key, value string) error { + if key == p.failKey { + return errors.New("set denied") + } + return p.Provider.SetMeta(name, key, value) +} + +func TestRuntimeEnvWithSessionContextAlignsAgentAndBeadsActor(t *testing.T) { + for _, tc := range []struct { + name string + alias string + configuredIdentity string + sessionName string + persistedSessionName string + want string + }{ + {name: "canonical alias", alias: "rig/worker", sessionName: "rig--worker", persistedSessionName: "rig--worker", want: "rig/worker"}, + {name: "configured named identity fallback", configuredIdentity: "rig/worker", sessionName: "rig--worker", persistedSessionName: "rig--worker", want: "rig/worker"}, + {name: "session name fallback", sessionName: "rig--worker", persistedSessionName: "rig--worker", want: "rig--worker"}, + {name: "bead id fallback", sessionName: "s-session-id", want: "session-id"}, + } { + t.Run(tc.name, func(t *testing.T) { + info := Info{ + ID: "session-id", + SessionName: tc.sessionName, + SessionNameMetadata: tc.persistedSessionName, + Alias: tc.alias, + ConfiguredNamedIdentity: tc.configuredIdentity, + Template: "rig/template", + SessionOrigin: "ephemeral", + } + env := RuntimeEnvWithSessionContext( + info, + DefaultGeneration, + DefaultContinuationEpoch, + "instance-token", + ) + + if got := env["GC_SESSION_NAME"]; got != tc.sessionName { + t.Fatalf("GC_SESSION_NAME = %q, want %q", got, tc.sessionName) + } + for _, key := range []string{"GC_AGENT", "BEADS_ACTOR"} { + if got := env[key]; got != tc.want { + t.Fatalf("%s = %q, want %q", key, got, tc.want) + } + } + if got := AssigneeIdentifier(info); got != env["BEADS_ACTOR"] { + t.Fatalf("AssigneeIdentifier = %q, BEADS_ACTOR = %q", got, env["BEADS_ACTOR"]) + } + }) + } +} + +func TestSyncRuntimeAliasAlignsOwnershipMetadata(t *testing.T) { + sp := runtime.NewFake() + assertMeta := func(sessionName, key, want string) { + t.Helper() + got, err := sp.GetMeta(sessionName, key) + if err != nil { + t.Fatalf("GetMeta(%s): %v", key, err) + } + if got != want { + t.Fatalf("%s = %q, want %q", key, got, want) + } + } + + info := Info{ID: "session-id", SessionName: "rig--worker", SessionNameMetadata: "rig--worker", Alias: "rig/worker"} + if err := SyncRuntimeAlias(sp, info); err != nil { + t.Fatalf("SyncRuntimeAlias(set): %v", err) + } + for _, key := range []string{"GC_ALIAS", "GC_AGENT", "BEADS_ACTOR"} { + assertMeta(info.SessionName, key, "rig/worker") + } + + info.Alias = "" + if err := SyncRuntimeAlias(sp, info); err != nil { + t.Fatalf("SyncRuntimeAlias(clear): %v", err) + } + assertMeta(info.SessionName, "GC_ALIAS", "") + for _, key := range []string{"GC_AGENT", "BEADS_ACTOR"} { + assertMeta(info.SessionName, key, "rig--worker") + } + + repairInfo := Info{ID: "repair-id", SessionName: "s-repair-id"} + if err := SyncRuntimeAlias(sp, repairInfo); err != nil { + t.Fatalf("SyncRuntimeAlias(repair): %v", err) + } + assertMeta(repairInfo.SessionName, "GC_ALIAS", "") + for _, key := range []string{"GC_AGENT", "BEADS_ACTOR"} { + assertMeta(repairInfo.SessionName, key, "repair-id") + } +} + +func TestSyncRuntimeAliasRollsBackOnPartialFailure(t *testing.T) { + base := runtime.NewFake() + for _, key := range []string{"GC_ALIAS", "GC_AGENT", "BEADS_ACTOR"} { + if err := base.SetMeta("rig--worker", key, "old-alias"); err != nil { + t.Fatalf("seed %s: %v", key, err) + } + } + sp := failingMetaProvider{Provider: base, failKey: "BEADS_ACTOR"} + info := Info{ID: "session-id", SessionName: "rig--worker", SessionNameMetadata: "rig--worker", Alias: "new-alias"} + + if err := SyncRuntimeAlias(sp, info); err == nil { + t.Fatal("SyncRuntimeAlias() error = nil, want BEADS_ACTOR failure") + } + for _, key := range []string{"GC_ALIAS", "GC_AGENT", "BEADS_ACTOR"} { + got, err := base.GetMeta("rig--worker", key) + if err != nil { + t.Fatalf("GetMeta(%s): %v", key, err) + } + if got != "old-alias" { + t.Fatalf("%s after rollback = %q, want old-alias", key, got) + } + } +} diff --git a/internal/session/lifecycle_holder_token_test.go b/internal/session/lifecycle_holder_token_test.go index 60253fcde2..be469919b8 100644 --- a/internal/session/lifecycle_holder_token_test.go +++ b/internal/session/lifecycle_holder_token_test.go @@ -24,7 +24,7 @@ func TestRuntimeEnvVariantsPropagateHolderToken(t *testing.T) { if alias["BEADS_HOLDER_TOKEN"] != "tok-a" { t.Errorf("WithAlias BEADS_HOLDER_TOKEN = %q, want tok-a", alias["BEADS_HOLDER_TOKEN"]) } - ctx := RuntimeEnvWithSessionContext("sid", "sname", "al", "tmpl", "cli", DefaultGeneration, DefaultContinuationEpoch, "tok-c") + ctx := RuntimeEnvWithSessionContext(Info{ID: "sid", SessionName: "sname", SessionNameMetadata: "sname", Alias: "al", ConfiguredNamedIdentity: "named", Template: "tmpl", SessionOrigin: "cli"}, DefaultGeneration, DefaultContinuationEpoch, "tok-c") if ctx["BEADS_HOLDER_TOKEN"] != "tok-c" { t.Errorf("WithSessionContext BEADS_HOLDER_TOKEN = %q, want tok-c", ctx["BEADS_HOLDER_TOKEN"]) } diff --git a/internal/session/manager.go b/internal/session/manager.go index 8a03432b49..fd0dd01d2b 100644 --- a/internal/session/manager.go +++ b/internal/session/manager.go @@ -972,16 +972,9 @@ func (m *Manager) createStarted(ctx context.Context, spec CreateOptions) (Info, cfg := hints cfg.Command = startCommand cfg.WorkDir = workDir - runtimeAlias := alias - if runtimeAlias == "" { - runtimeAlias = strings.TrimSpace(extraMeta["agent_name"]) - } + runtimeInfo := m.infoFromBead(b) cfg.Env = mergeEnv(mergeEnv(cfg.Env, env), RuntimeEnvWithSessionContext( - b.ID, - sessName, - runtimeAlias, - template, - meta["session_origin"], + runtimeInfo, DefaultGeneration, DefaultContinuationEpoch, meta["instance_token"], @@ -1576,15 +1569,19 @@ func (m *Manager) UpdatePresentation(id string, title *string, alias *string) er } } update.Metadata = UpdatedAliasMetadata(b.Metadata, nextAlias) + runtimeInfo := m.infoFromBead(b) + runtimeInfo.SessionName = sessName + nextRuntimeInfo := runtimeInfo + nextRuntimeInfo.Alias = nextAlias runtimeRunning := sessName != "" && m.sp != nil && m.sp.IsRunning(sessName) if runtimeRunning { - if err := SyncRuntimeAlias(m.sp, sessName, nextAlias); err != nil { + if err := SyncRuntimeAlias(m.sp, nextRuntimeInfo); err != nil { return fmt.Errorf("updating runtime alias: %w", err) } } if err := m.store.Update(id, update); err != nil { if runtimeRunning { - if rollbackErr := SyncRuntimeAlias(m.sp, sessName, currentAlias); rollbackErr != nil { + if rollbackErr := SyncRuntimeAlias(m.sp, runtimeInfo); rollbackErr != nil { log.Printf("session %s: restoring runtime alias %q on %s failed: %v", id, currentAlias, sessName, rollbackErr) } } diff --git a/internal/session/manager_test.go b/internal/session/manager_test.go index 3b19da3c81..d09483b93e 100644 --- a/internal/session/manager_test.go +++ b/internal/session/manager_test.go @@ -1728,7 +1728,7 @@ func TestCreateInjectsUnifiedSessionRuntimeEnv(t *testing.T) { mgr := NewManagerWithOptions(store, sp) info, err := mgr.CreateSession( - context.Background(), CreateOptions{Alias: "mayor", ExplicitName: "test-city--mayor", Template: "reviewer", Title: "Mayor", Command: "claude", WorkDir: "/tmp", Provider: "claude", Transport: "", Env: map[string]string{"GC_AGENT": "stale"}, Resume: ProviderResume{}, Hints: runtime.Config{}, ExtraMeta: map[string]string{ + context.Background(), CreateOptions{Alias: "", ExplicitName: "test-city--mayor", Template: "reviewer", Title: "Mayor", Command: "claude", WorkDir: "/tmp", Provider: "claude", Transport: "", Env: map[string]string{"GC_AGENT": "stale"}, Resume: ProviderResume{}, Hints: runtime.Config{}, ExtraMeta: map[string]string{ "configured_named_session": "true", "configured_named_identity": "mayor", "session_origin": "named", @@ -1755,6 +1755,7 @@ func TestCreateInjectsUnifiedSessionRuntimeEnv(t *testing.T) { "GC_TEMPLATE": "reviewer", "GC_SESSION_ORIGIN": "named", "GC_AGENT": "mayor", + "BEADS_ACTOR": "mayor", } { if got := env[key]; got != want { t.Fatalf("Env[%s] = %q, want %q (env=%v)", key, got, want, env) @@ -1849,10 +1850,11 @@ func TestCreateAliaslessMultiSessionUsesConcreteRuntimeIdentity(t *testing.T) { for key, want := range map[string]string{ "GC_SESSION_ID": info.ID, "GC_SESSION_NAME": "ant-adhoc-123", - "GC_ALIAS": "demo/ant-adhoc-123", + "GC_ALIAS": "", "GC_TEMPLATE": "demo/ant", "GC_SESSION_ORIGIN": "manual", - "GC_AGENT": "demo/ant-adhoc-123", + "GC_AGENT": "ant-adhoc-123", + "BEADS_ACTOR": "ant-adhoc-123", } { if got := env[key]; got != want { t.Fatalf("Env[%s] = %q, want %q (env=%v)", key, got, want, env) @@ -2573,12 +2575,14 @@ func TestUpdatePresentationSyncsRuntimeAlias(t *testing.T) { t.Fatalf("UpdatePresentation(alias): %v", err) } - got, err := sp.GetMeta(info.SessionName, "GC_ALIAS") - if err != nil { - t.Fatalf("GetMeta(GC_ALIAS): %v", err) - } - if got != nextAlias { - t.Fatalf("GC_ALIAS = %q, want %q", got, nextAlias) + for _, key := range []string{"GC_ALIAS", "GC_AGENT", "BEADS_ACTOR"} { + got, err := sp.GetMeta(info.SessionName, key) + if err != nil { + t.Fatalf("GetMeta(%s): %v", key, err) + } + if got != nextAlias { + t.Fatalf("%s = %q, want %q", key, got, nextAlias) + } } bead, err := store.Get(info.ID) diff --git a/internal/session/names.go b/internal/session/names.go index c0f0bb10ee..207f26e433 100644 --- a/internal/session/names.go +++ b/internal/session/names.go @@ -608,6 +608,35 @@ func ensureSessionAliasAvailable(store beads.Store, cfg *config.City, alias, sel continue } if strings.TrimSpace(b.Metadata["session_name"]) == alias { + // A superseded, non-running (asleep) configured-named-session + // predecessor for the SAME identity must not block that + // identity's own live holder from claiming its canonical alias + // (#2885, Fix Candidate A). Scoped narrowly: only when (1) the + // claimant asserts the exact owner identity the holder was + // minted for, (2) the holder is asleep rather than genuinely + // running, and (3) the holder is recognizably a + // configured-named-session bead FOR THAT SAME IDENTITY. This + // mirrors the self-owner exception the agent_name branch below + // already has, and does not resurrect or steal an alias from an + // unrelated, live, or ambiguous session. + // + // Condition (3) is two-part on purpose. + // wasConfiguredNamedSession(b) establishes the holder is a + // configured-named-session bead at all, but it is owner-AGNOSTIC + // — a bead minted for a DIFFERENT configured identity that merely + // persisted this identity's runtime session_name would satisfy it + // and hand the alias over on the claimant's assertion alone. + // configuredNamedIdentitySignalsMatch is the owner-scoped + // recognizer introduced for the identical trap in + // name_claim_sweep.go (review #3373); it matches the recorded + // identity, alias, agent_name, or template/role signal against + // THIS identity. + if selfOwner != "" && selfOwner == alias && + strings.TrimSpace(b.Metadata["state"]) == string(StateAsleep) && + wasConfiguredNamedSession(b) && + configuredNamedIdentitySignalsMatch(b, selfOwner) { + continue + } return fmt.Errorf("%w: %q conflicts with session name on %s", ErrSessionAliasExists, alias, b.ID) } if strings.TrimSpace(b.Metadata["alias"]) == alias { diff --git a/internal/session/names_test.go b/internal/session/names_test.go index d9ff0c8baa..f5ac908a25 100644 --- a/internal/session/names_test.go +++ b/internal/session/names_test.go @@ -1144,3 +1144,147 @@ func TestWithCitySessionLocks_EmptyCityPathSharesIdentifierNamespace(t *testing. } <-acquired } + +// An open, asleep, drained configured-named-session bead squats the canonical +// alias forever in front of the LIVE pool-managed session for the same +// identity. The session_name-match branch of ensureSessionAliasAvailable has +// no self-owner exception, unlike the agent_name branch below it, so it +// unconditionally blocks the live session's claim to its own canonical alias. +// This is the root diagnosed in #2885 ("singleton pool canonical alias +// squatted forever by asleep (non-closed) predecessor"), Fix Candidate A: +// skip a superseded, non-running predecessor for the SAME canonical identity +// when the requester is that identity's live holder. +func TestEnsureSessionAliasAvailable_DrainedNamedPredecessorBlocksLiveSelfOwnerClaim(t *testing.T) { + store := beads.NewMemStore() + + if _, err := store.Create(beads.Bead{ + Type: BeadType, + Labels: []string{LabelSession}, + Metadata: map[string]string{ + "session_name": "perrin", + "session_origin": "named", + "configured_named_session": "true", + "configured_named_identity": "perrin", + "state": "asleep", + "sleep_reason": "drained", + }, + }); err != nil { + t.Fatalf("Create(drained named holder): %v", err) + } + + live, err := store.Create(beads.Bead{ + Type: BeadType, + Labels: []string{LabelSession}, + Metadata: map[string]string{ + "session_name": "perrin-gc-live1", + "agent_name": "perrin", + "template": "perrin", + "pool_managed": "true", + "state": "awake", + }, + }) + if err != nil { + t.Fatalf("Create(live typed session): %v", err) + } + + // The live session, claiming its own canonical alias, is not blocked by + // its own drained predecessor. + if err := ensureSessionAliasAvailable(store, nil, "perrin", live.ID, "perrin"); err != nil { + t.Fatalf("ensureSessionAliasAvailable(live self-owner vs drained predecessor) = %v, want nil", err) + } + + // A third party (different selfOwner) must still be refused the alias: + // the drained bead still legitimately reserves the identity against + // anyone who is not that identity's own live holder. + if err := ensureSessionAliasAvailable(store, nil, "perrin", "gc-stranger", "siuan"); !errors.Is(err, ErrSessionAliasExists) { + t.Fatalf("ensureSessionAliasAvailable(different owner vs drained predecessor) = %v, want ErrSessionAliasExists", err) + } +} + +// The #2885 self-owner exception above is a three-part guard, and each part is +// load-bearing. These negatives pin all three in the refusing direction so a +// later loosening of the condition fails here rather than silently handing a +// canonical alias to a claimant that only asserted ownership. +// +// The mismatched-identity case is the one wasConfiguredNamedSession alone +// cannot catch: it is owner-AGNOSTIC, so the owner-scoped +// configuredNamedIdentitySignalsMatch (the recognizer name_claim_sweep.go +// adopted for the identical trap in review #3373) is what refuses it. +func TestEnsureSessionAliasAvailable_SelfOwnerExceptionRefusesUnqualifiedHolders(t *testing.T) { + cases := []struct { + name string + holder map[string]string + }{ + { + // Guard condition 3, owner-scoped half: a configured-named-session + // bead minted for a DIFFERENT identity that merely persisted + // "perrin" as its runtime session_name. No alias, agent_name, or + // template resolves to "perrin", so it is not perrin's predecessor + // and must keep blocking perrin's claim. + name: "mismatched configured identity", + holder: map[string]string{ + "session_name": "perrin", + "session_origin": "named", + "configured_named_session": "true", + "configured_named_identity": "egwene", + "state": "asleep", + "sleep_reason": "drained", + }, + }, + { + // Guard condition 2: same identity, but the holder is awake — a + // genuinely running session, not a superseded predecessor. + name: "same identity but awake", + holder: map[string]string{ + "session_name": "perrin", + "session_origin": "named", + "configured_named_session": "true", + "configured_named_identity": "perrin", + "state": "awake", + }, + }, + { + // Guard condition 3, recognition half: an asleep holder with no + // configured-named signals at all is an ordinary session squatting + // the name, not a configured-named predecessor. + name: "asleep but not a configured named session", + holder: map[string]string{ + "session_name": "perrin", + "state": "asleep", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + store := beads.NewMemStore() + + if _, err := store.Create(beads.Bead{ + Type: BeadType, + Labels: []string{LabelSession}, + Metadata: tc.holder, + }); err != nil { + t.Fatalf("Create(holder): %v", err) + } + + live, err := store.Create(beads.Bead{ + Type: BeadType, + Labels: []string{LabelSession}, + Metadata: map[string]string{ + "session_name": "perrin-gc-live1", + "agent_name": "perrin", + "template": "perrin", + "pool_managed": "true", + "state": "awake", + }, + }) + if err != nil { + t.Fatalf("Create(live typed session): %v", err) + } + + if err := ensureSessionAliasAvailable(store, nil, "perrin", live.ID, "perrin"); !errors.Is(err, ErrSessionAliasExists) { + t.Fatalf("ensureSessionAliasAvailable(self-owner vs %s) = %v, want ErrSessionAliasExists", tc.name, err) + } + }) + } +} diff --git a/internal/session/productmetrics_child_env_test.go b/internal/session/productmetrics_child_env_test.go index cd4f63697c..fb15372597 100644 --- a/internal/session/productmetrics_child_env_test.go +++ b/internal/session/productmetrics_child_env_test.go @@ -17,7 +17,10 @@ func TestProductMetricsDirectChildEnvSessionSubmitPoller(t *testing.T) { snapshot := filepath.Join(dir, "child.env") spy := filepath.Join(dir, "gc-child-spy") script := "#!/bin/sh\n" + - "printf '%s\\n' \"$GC_DISABLE_USAGE_METRICS\" \"$BD_DISABLE_METRICS\" \"$OTEL_SERVICE_NAME\" > \"$GC_TEST_PRODUCT_METRICS_CHILD_ENV_SPY\"\n" + "snapshot=\"$GC_TEST_PRODUCT_METRICS_CHILD_ENV_SPY\"\n" + + "tmp=\"${snapshot}.tmp.$$\"\n" + + "printf '%s\\n' \"$GC_DISABLE_USAGE_METRICS\" \"$BD_DISABLE_METRICS\" \"$OTEL_SERVICE_NAME\" > \"$tmp\"\n" + + "mv -f \"$tmp\" \"$snapshot\"\n" if err := os.WriteFile(spy, []byte(script), 0o700); err != nil { t.Fatalf("write child spy: %v", err) } diff --git a/internal/sling/sling_core.go b/internal/sling/sling_core.go index 0e0cb2c127..a9ce089c24 100644 --- a/internal/sling/sling_core.go +++ b/internal/sling/sling_core.go @@ -195,10 +195,17 @@ func resolveIdempotentShortCircuit(opts SlingOpts, a config.Agent, deps SlingDep // onto in-progress work), but say so explicitly: without this // warning the CLI prints only the generic "already routed" message, // giving no signal that the requested --on formula was never - // attached or that --force would override the skip. + // attached or that --force would override the skip. opts.OnFormula + // is empty when this was reached via the target's + // default_sling_formula rather than an explicit --on, so fall back + // to naming that instead of rendering an empty flag value. + skippedFormula := opts.OnFormula + if skippedFormula == "" { + skippedFormula = a.EffectiveDefaultSlingFormula() + } result.BeadWarnings = append(result.BeadWarnings, fmt.Sprintf( "bead %s is claimed by %s with no molecule attached; --on %s was skipped to avoid re-attaching onto in-progress work — rerun with --force to attach it anyway", - opts.BeadOrFormula, decision.Assignee, opts.OnFormula)) + opts.BeadOrFormula, decision.Assignee, skippedFormula)) } } if !check.Idempotent { @@ -295,7 +302,10 @@ type attachmentDecision struct { // fail-closed idempotent state rather than clear it and risk minting a // duplicate attachment. func onFormulaNeedsAttachment(opts SlingOpts, querier BeadQuerier, deps SlingDeps) (attachmentDecision, error) { - if opts.OnFormula == "" { + // Both formula-backed routes reach the same attach path, so the + // routed-raw override has to apply to a target's default_sling_formula + // as well as an explicit --on. + if !usesFormulaBackedRoute(opts) { return attachmentDecision{}, nil } hasMolecule, err := HasMoleculeChildren(querier, opts.BeadOrFormula, deps.Store) @@ -519,7 +529,13 @@ func attachFormulaToBead(opts SlingOpts, deps SlingDeps, querier BeadQuerier, be if rollbackErr := rollbackGraphV2ReplacementLaunch(deps.Store, mResult.RootID, replacedSnapshot); rollbackErr != nil { return wfResult, errors.Join(wfErr, rollbackErr) } + return wfResult, wfErr } + // The convoy-first branch deliberately passes an empty + // sourceBeadID (the source is tracked through the input convoy, + // not gc.source_bead_id), so doStartGraphWorkflow's own restamp + // never covers it. Stamp the work bead here instead. + restampWorkBeadRouting(deps, beadID, a, &wfResult) return wfResult, wfErr }) if lockedErr != nil { @@ -722,6 +738,36 @@ func validateBuiltInRouteStoreReachable(deps SlingDeps, beadID string, a config. } } +// restampWorkBeadRouting stamps gc.execution_routed_to on the work bead a +// graph workflow was attached to. A graph.v2 work bead must not get the +// claim-semantics gc.routed_to key once its workflow has started, because the +// pool's tier-3 claim query and the drain engine's own dispatch are two +// uncoordinated authorities -- neither checks the bead's Assignee/the other's +// lock field, so stamping gc.routed_to there is a structural double-dispatch +// hazard, not merely an observability fix. The existing ExecutionRoutedToKey +// (gc.execution_routed_to) is already read by the graphroute resolver, convoy +// dispatch, dashboard orders feed, and dispatch engine. Apply +// NormalizePoolRouteTarget to the computed target so slot-suffixed pool +// instances collapse to their base template name (the same pass every other +// gc.routed_to writer applies). Failures are reported as metadata errors +// rather than failing the launch: by this point the workflow is already +// running, and unwinding it over a routing restamp would be worse than a +// surfaced warning. +func restampWorkBeadRouting(deps SlingDeps, beadID string, a config.Agent, result *SlingResult) { + beadID = strings.TrimSpace(beadID) + if beadID == "" || deps.Store == nil || result == nil { + return + } + target := agentutil.NormalizePoolRouteTarget(deps.Cfg, strings.TrimSpace(agentutil.RoutedToIdentity(&a))) + if target == "" { + return + } + if err := deps.Store.SetMetadata(beadID, beadmeta.ExecutionRoutedToMetadataKey, target); err != nil { + result.MetadataErrors = append(result.MetadataErrors, + fmt.Sprintf("setting %s on %s: %v", beadmeta.ExecutionRoutedToMetadataKey, beadID, err)) + } +} + // doStartGraphWorkflow performs post-instantiation graph workflow setup. func doStartGraphWorkflow(rootID, sourceBeadID string, a config.Agent, method string, deps SlingDeps) (SlingResult, error) { var result SlingResult @@ -752,6 +798,7 @@ func doStartGraphWorkflow(rootID, sourceBeadID string, a config.Agent, method st if err := deps.Store.SetMetadata(sourceBeadID, "workflow_id", rootID); err != nil { return result, fmt.Errorf("setting workflow_id on %s: %w", sourceBeadID, err) } + restampWorkBeadRouting(deps, sourceBeadID, a, &result) } telemetry.RecordSling(context.Background(), a.QualifiedName(), TargetType(&a), method, nil) if deps.Notify != nil { diff --git a/internal/sling/sling_test.go b/internal/sling/sling_test.go index 003575a9bc..952ca27520 100644 --- a/internal/sling/sling_test.go +++ b/internal/sling/sling_test.go @@ -11,6 +11,7 @@ import ( "strings" "testing" + "github.com/gastownhall/gascity/internal/agentutil" "github.com/gastownhall/gascity/internal/beadmeta" "github.com/gastownhall/gascity/internal/beads" beadsexec "github.com/gastownhall/gascity/internal/beads/exec" @@ -1415,6 +1416,93 @@ func TestDoSlingIdempotent(t *testing.T) { } } +// TestOnFormulaNeedsAttachmentAppliesToDefaultSlingFormula guards the +// broadened usesFormulaBackedRoute check in onFormulaNeedsAttachment: a +// target's configured default_sling_formula must reach the same +// routed-raw-needs-attach decision as an explicit --on formula. Before this +// guard covered both routes, a bead slung with no --on flag onto a target +// with default_sling_formula set would be treated as a settled idempotent +// no-op forever, even though it was only ever routed raw and never fanned +// into a molecule. +func TestOnFormulaNeedsAttachmentAppliesToDefaultSlingFormula(t *testing.T) { + store := beads.NewMemStore() + bead, err := store.Create(beads.Bead{ + Title: "work", + Type: "task", + Status: "open", + Metadata: map[string]string{"gc.routed_to": "mayor"}, + }) + if err != nil { + t.Fatalf("store.Create: %v", err) + } + + a := config.Agent{Name: "mayor", DefaultSlingFormula: stringPtr("code-review")} + opts := SlingOpts{Target: a, BeadOrFormula: bead.ID} + deps := SlingDeps{Store: store} + + decision, err := onFormulaNeedsAttachment(opts, store, deps) + if err != nil { + t.Fatalf("onFormulaNeedsAttachment error: %v", err) + } + if !decision.NeedsAttach { + t.Fatalf("decision = %+v, want NeedsAttach=true via target's default_sling_formula (no explicit --on)", decision) + } +} + +// TestDoSlingSkippedForClaimWarningNamesDefaultFormula guards the +// SkippedForClaim warning text reached via a target's default_sling_formula +// (no explicit --on). The message interpolates opts.OnFormula, which is +// empty on this path — before this is fixed it renders "--on was skipped" +// (double space, no formula named) instead of naming the default formula +// that was actually skipped. +func TestDoSlingSkippedForClaimWarningNamesDefaultFormula(t *testing.T) { + runner := newFakeRunner() + sp := runtime.NewFake() + cfg := &config.City{Workspace: config.Workspace{Name: "test-city"}} + a := config.Agent{Name: "mayor", MaxActiveSessions: intPtr(1), DefaultSlingFormula: stringPtr("code-review")} + + store := beads.NewMemStore() + convoy, err := store.Create(beads.Bead{Title: "convoy", Type: "convoy", Status: "open"}) + if err != nil { + t.Fatalf("store.Create(convoy): %v", err) + } + bead, err := store.Create(beads.Bead{ + Title: "test", + ParentID: convoy.ID, + Assignee: "mayor", + Metadata: map[string]string{"gc.routed_to": "mayor"}, + }) + if err != nil { + t.Fatalf("store.Create(bead): %v", err) + } + + deps := testDeps(cfg, sp, runner.run) + deps.Store = store + result, err := DoSling(testOpts(a, bead.ID), deps, store) + if err != nil { + t.Fatalf("DoSling error: %v", err) + } + if !result.Idempotent { + t.Fatalf("expected Idempotent=true (claimed by target, no molecule attached: skip, not fail), got %+v", result) + } + if len(runner.calls) != 0 { + t.Error("runner should not have been called") + } + + var named bool + for _, w := range result.BeadWarnings { + if strings.Contains(w, "--on was skipped") { + t.Fatalf("BeadWarnings contains %q: still renders the empty explicit --on flag instead of the target's default_sling_formula name", w) + } + if strings.Contains(w, "code-review") { + named = true + } + } + if !named { + t.Fatalf("BeadWarnings = %v, want a warning naming the skipped default formula %q", result.BeadWarnings, "code-review") + } +} + func TestCheckBatchBurnOutputsWarn(t *testing.T) { store := beads.NewMemStoreFrom(0, []beads.Bead{ {ID: "BL-2", Type: "task", Status: "open"}, @@ -2512,6 +2600,64 @@ func TestSlingAttachGraphFormulaCreatesConvoyFirstRoot(t *testing.T) { if len(members) != 1 || members[0].ID != source.ID { t.Fatalf("members = %+v, want source %s", members, source.ID) } + // restampWorkBeadRouting stamps ExecutionRoutedTo (gc.execution_routed_to), + // not the claim-semantics gc.routed_to. Verify the correct key is set + // and the claim key is NOT set. + if got := sourceAfter.Metadata[beadmeta.ExecutionRoutedToMetadataKey]; got != "mayor" { + t.Fatalf("source gc.execution_routed_to = %q, want mayor", got) + } + if got := sourceAfter.Metadata[beadmeta.RoutedToMetadataKey]; got != "" { + t.Fatalf("source gc.routed_to = %q, want empty (must not be set on graph.v2 work bead)", got) + } +} + +// TestRestampWorkBeadRoutingCollapsesPoolInstanceResolvedViaResolveAgent +// guards the actual production resolution path for a pool-instance target. +// An agent obtained via agentutil.ResolveAgent -- as the real CLI/API +// dispatch paths do -- never has PoolName set on the returned copy: +// agentutil.DeepCopyAgent copies the base template's own (empty) PoolName +// rather than pointing the synthesized instance back at its template. A +// hand-constructed config.Agent{PoolName: "..."} literal masks this and +// would pass even without the NormalizePoolRouteTarget collapse in +// restampWorkBeadRouting, because RoutedToIdentity would already resolve +// correctly from the (test-only) pre-set PoolName. +func TestRestampWorkBeadRoutingCollapsesPoolInstanceResolvedViaResolveAgent(t *testing.T) { + cfg := &config.City{ + Rigs: []config.Rig{{Name: "myrig"}}, + Agents: []config.Agent{{Name: "polecat", Dir: "myrig", MaxActiveSessions: intPtr(4)}}, + } + target := "myrig/polecat-2" + a, ok := agentutil.ResolveAgent(cfg, target, agentutil.ResolveOpts{AllowPoolMembers: true}) + if !ok { + t.Fatalf("ResolveAgent(%q) failed to resolve", target) + } + if a.PoolName != "" { + t.Fatalf("fixture premise broken: resolved pool instance already has PoolName=%q; if DeepCopyAgent now sets it, this test no longer exercises the collapse path it targets", a.PoolName) + } + + store := beads.NewMemStore() + bead, err := store.Create(beads.Bead{Title: "work", Type: "task", Status: "open"}) + if err != nil { + t.Fatalf("store.Create: %v", err) + } + + deps := SlingDeps{Store: store, Cfg: cfg} + result := &SlingResult{} + restampWorkBeadRouting(deps, bead.ID, a, result) + + if len(result.MetadataErrors) != 0 { + t.Fatalf("MetadataErrors = %v, want none", result.MetadataErrors) + } + after, err := store.Get(bead.ID) + if err != nil { + t.Fatalf("store.Get: %v", err) + } + if got := after.Metadata[beadmeta.ExecutionRoutedToMetadataKey]; got != "myrig/polecat" { + t.Fatalf("gc.execution_routed_to = %q, want myrig/polecat (collapsed from slot-suffixed %s resolved via agentutil.ResolveAgent)", got, target) + } + if got := after.Metadata[beadmeta.RoutedToMetadataKey]; got != "" { + t.Fatalf("gc.routed_to = %q, want empty", got) + } } func TestSlingAttachGraphFormulaEmitsCurrentExecutionFacts(t *testing.T) { diff --git a/internal/supervisor/maintenance.go b/internal/supervisor/maintenance.go index c65e9f58e8..c1f5326fcc 100644 --- a/internal/supervisor/maintenance.go +++ b/internal/supervisor/maintenance.go @@ -397,16 +397,21 @@ func (m *StoreMaintenanceLoop) executeCycleLocked(ctx context.Context) Maintenan m.runStartedAt.Store(&started) defer m.runStartedAt.Store(nil) + if m.checkDiskPreflight() { + // Disk is critically low — skip both the snapshot and CALL DOLT_GC. + // Snapshotting the store needs roughly as much free space as the + // store itself, so a critically-low store would fail the backup and + // still leave no room for GC. Running the pre-flight before the + // snapshot means a CRITICAL disk skips both stages rather than + // attempting a doomed backup that only consumes the last of the disk. + // The StoreDiskCritical event informs operators; C1 + // (hold-on-store-unreachable) handles downstream safety. + return m.finishCycleLocked(started, "", nil) + } snapshotPath, err := m.runSnapshot(ctx) if err != nil { return m.finishCycleLocked(started, snapshotPath, err) } - if m.checkDiskPreflight() { - // Disk is critically low — skip CALL DOLT_GC to avoid growing the - // store further. The StoreDiskCritical event informs operators. - // C1 (hold-on-store-unreachable) handles downstream safety. - return m.finishCycleLocked(started, snapshotPath, nil) - } if err := m.runDoltGC(ctx); err != nil { return m.finishCycleLocked(started, snapshotPath, err) } @@ -484,9 +489,10 @@ func (m *StoreMaintenanceLoop) emitRunEvent(run MaintenanceRun) { } } -// checkDiskPreflight checks free space in cityPath's filesystem before a -// disk-growing operation (CALL DOLT_GC). Returns true when the GC should be -// skipped (CRITICAL), false when it may proceed. Side-effects: emits +// checkDiskPreflight checks free space in cityPath's filesystem before the +// disk-growing stages of a maintenance cycle (snapshot, then CALL DOLT_GC). +// Returns true when both stages should be skipped (CRITICAL), false when the +// cycle may proceed. Side-effects: emits // StoreDiskWarn or StoreDiskCritical events and logs to stderr. // Fails open: a probe error or a nil DiskFreeBytes always returns false. func (m *StoreMaintenanceLoop) checkDiskPreflight() bool { @@ -502,7 +508,7 @@ func (m *StoreMaintenanceLoop) checkDiskPreflight() bool { if free < m.diskMinFreeBytes { m.emitDiskEvent(events.StoreDiskCritical, free) fmt.Fprintf(m.stderr, //nolint:errcheck - "store-maintenance: disk CRITICAL — %.1f GiB free (floor %.1f GiB) on %s; skipping CALL DOLT_GC\n", + "store-maintenance: disk CRITICAL — %.1f GiB free (floor %.1f GiB) on %s; skipping snapshot and CALL DOLT_GC\n", float64(free)/gib, float64(m.diskMinFreeBytes)/gib, m.cityPath) return true } diff --git a/internal/supervisor/maintenance_trigger_test.go b/internal/supervisor/maintenance_trigger_test.go index ada4778483..c7e090a94c 100644 --- a/internal/supervisor/maintenance_trigger_test.go +++ b/internal/supervisor/maintenance_trigger_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/gastownhall/gascity/internal/config" + "github.com/gastownhall/gascity/internal/events" ) // TestTriggerNow_Success runs one synchronous maintenance cycle and verifies @@ -201,3 +202,61 @@ func (g *gatedDoltOps) SmokeCount(context.Context) (int, error) { func (g *gatedDoltOps) Close() error { return nil } + +// TestExecuteCycle_CriticalDiskSkipsSnapshotAndGC verifies that when the disk +// pre-flight detects CRITICAL free space, neither the snapshot runner nor the +// GC ops are invoked. The disk pre-flight must run BEFORE runSnapshot so a +// critically-low store cannot consume the remaining disk attempting a backup +// that will fail anyway. +func TestExecuteCycle_CriticalDiskSkipsSnapshotAndGC(t *testing.T) { + t.Parallel() + cfg := config.DoltMaintenance{Enabled: true, Interval: "1h", GCTimeout: "1s"} + now := time.Date(2026, 4, 22, 12, 0, 0, 0, time.UTC) + + var snapshotCalled, gcCalled bool + fake := events.NewFake() + + loop := NewStoreMaintenanceLoop(StoreMaintenanceLoopDeps{ + Cfg: cfg, + CityPath: t.TempDir(), + Clock: func() time.Time { return now }, + Rand: func() float64 { return 0.5 }, + Recorder: fake, + OpenDoltBackup: func(context.Context) (DoltBackupRunner, error) { + snapshotCalled = true + return nil, errors.New("should not be reached") + }, + OpenDoltOps: func(context.Context) (DoltOps, error) { + gcCalled = true + return nil, errors.New("should not be reached") + }, + // Report disk as critically below the floor. + DiskFreeBytes: func(string) (int64, error) { return 100, nil }, + DiskMinFreeBytes: 1 << 30, // 1 GiB floor; 100 bytes free → CRITICAL + }) + + run, err := loop.TriggerNow(context.Background()) + if err != nil { + t.Fatalf("TriggerNow = %v; want nil", err) + } + if run.Stage != "done" || run.Err != "" { + t.Fatalf("run Stage=%q Err=%q; want done with no error", run.Stage, run.Err) + } + if snapshotCalled { + t.Error("snapshot factory was called despite CRITICAL disk; disk pre-flight must run before snapshot") + } + if gcCalled { + t.Error("GC ops factory was called despite CRITICAL disk") + } + + // StoreDiskCritical event must have fired exactly once. + criticalEvents := 0 + for _, e := range fake.Events { + if e.Type == events.StoreDiskCritical { + criticalEvents++ + } + } + if criticalEvents != 1 { + t.Errorf("got %d StoreDiskCritical events; want 1", criticalEvents) + } +} diff --git a/internal/telemetry/telemetry_test.go b/internal/telemetry/telemetry_test.go index fb93b20094..a9a4313785 100644 --- a/internal/telemetry/telemetry_test.go +++ b/internal/telemetry/telemetry_test.go @@ -331,7 +331,7 @@ func TestNewResource_HonorsOTELResourceAttributes(t *testing.T) { attrs := make(map[string]string) for _, kv := range res.Attributes() { - attrs[string(kv.Key)] = kv.Value.Emit() + attrs[string(kv.Key)] = kv.Value.String() } if got := attrs["deployment.environment"]; got != "prod" { t.Errorf("deployment.environment = %q, want %q", got, "prod") @@ -361,7 +361,7 @@ func TestNewResource_OwnGCIdentityWinsOverInheritedEnv(t *testing.T) { attrs := make(map[string]string) for _, kv := range res.Attributes() { - attrs[string(kv.Key)] = kv.Value.Emit() + attrs[string(kv.Key)] = kv.Value.String() } if got := attrs["gc.agent"]; got != "b" { t.Errorf("gc.agent = %q, want own identity %q to win over inherited env", got, "b") @@ -381,7 +381,7 @@ func TestNewResource_ExplicitServiceIdentityWinsOverEnv(t *testing.T) { attrs := make(map[string]string) for _, kv := range res.Attributes() { - attrs[string(kv.Key)] = kv.Value.Emit() + attrs[string(kv.Key)] = kv.Value.String() } if got := attrs["service.name"]; got != "test-svc" { t.Errorf("service.name = %q, want explicit %q to win over env", got, "test-svc") @@ -401,8 +401,8 @@ func TestNewResource_ExplicitServiceNameWinsOverOTELServiceName(t *testing.T) { } for _, kv := range res.Attributes() { - if string(kv.Key) == "service.name" && kv.Value.Emit() != "test-svc" { - t.Errorf("service.name = %q, want explicit %q to win over OTEL_SERVICE_NAME", kv.Value.Emit(), "test-svc") + if string(kv.Key) == "service.name" && kv.Value.String() != "test-svc" { + t.Errorf("service.name = %q, want explicit %q to win over OTEL_SERVICE_NAME", kv.Value.String(), "test-svc") } } } @@ -423,7 +423,7 @@ func TestNewResource_ToleratesMalformedResourceAttributes(t *testing.T) { attrs := make(map[string]string) for _, kv := range res.Attributes() { - attrs[string(kv.Key)] = kv.Value.Emit() + attrs[string(kv.Key)] = kv.Value.String() } if got := attrs["deployment.environment"]; got != "prod" { t.Errorf("deployment.environment = %q, want %q", got, "prod") diff --git a/internal/testenv/testdata/gc_env_read_baseline.golden b/internal/testenv/testdata/gc_env_read_baseline.golden index 99bfd5e80b..0acd10960e 100644 --- a/internal/testenv/testdata/gc_env_read_baseline.golden +++ b/internal/testenv/testdata/gc_env_read_baseline.golden @@ -5,6 +5,7 @@ GC_AGENT GC_AGENT_SLICE GC_ALIAS GC_ALLOW_PROD_DOLT_PORT_IN_TESTS +GC_BACKUP_MAX_AGE_FOR_BULK_DELETE GC_BD_PROBE_TIMEOUT GC_BD_TRACE GC_BD_TRACE_JSON @@ -20,6 +21,7 @@ GC_BEADS_PROJECT_ID GC_BEADS_SCOPE_ROOT GC_BOOTSTRAP GC_BRANCH +GC_BULK_DELETE_CONFIRM_THRESHOLD GC_CAPABILITY_WORKSPACE_OK GC_CEILING_DIRECTORIES GC_CITY diff --git a/internal/testpolicy/resourcecensus/census.go b/internal/testpolicy/resourcecensus/census.go index bc35db4aaa..2290fc812d 100644 --- a/internal/testpolicy/resourcecensus/census.go +++ b/internal/testpolicy/resourcecensus/census.go @@ -123,7 +123,7 @@ var bootstrapPolicy = Ledger{ { Scope: ScopeAll, Resource: ResourceSubprocess, - BaselineCalls: 552, + BaselineCalls: 555, BaselineFiles: 168, ReportedCalls: 495, ReportedFiles: 135, @@ -136,8 +136,8 @@ var bootstrapPolicy = Ledger{ { Scope: ScopeAll, Resource: ResourceFixedSleep, - BaselineCalls: 432, - BaselineFiles: 160, + BaselineCalls: 437, + BaselineFiles: 161, ReportedCalls: 447, ReportedFiles: 157, OwnerBead: "ga-80po0c.2", @@ -164,7 +164,7 @@ var bootstrapPolicy = Ledger{ { Scope: ScopeUntagged, Resource: ResourceSubprocess, - BaselineCalls: 413, + BaselineCalls: 414, BaselineFiles: 117, ReportedCalls: 380, ReportedFiles: 98, @@ -453,7 +453,7 @@ var bootstrapPolicy = Ledger{ { Scope: ScopeUntagged, Resource: ResourceSubprocess, - BaselineCalls: 407, + BaselineCalls: 408, BaselineFiles: 114, ReportedCalls: 394, ReportedFiles: 105, diff --git a/internal/worker/builtin/profiles.go b/internal/worker/builtin/profiles.go index 5d53244afa..92cda0e62f 100644 --- a/internal/worker/builtin/profiles.go +++ b/internal/worker/builtin/profiles.go @@ -125,11 +125,13 @@ var builtinProviderSpecs = map[string]BuiltinProviderSpec{ ForkFlag: "--fork-session", PrintArgs: []string{"-p"}, TitleModel: "haiku", + // Config-facing names map to current CLI values: Claude Code rejects the + // legacy "auto-edit"/"full-auto" it used to accept (GH#4602). PermissionModes: map[string]string{ "unrestricted": "--dangerously-skip-permissions", "plan": "--permission-mode plan", - "auto-edit": "--permission-mode auto-edit", - "full-auto": "--permission-mode full-auto", + "auto-edit": "--permission-mode acceptEdits", + "full-auto": "--permission-mode dontAsk", }, OptionsSchema: []BuiltinProviderOption{ { @@ -138,8 +140,8 @@ var builtinProviderSpecs = map[string]BuiltinProviderSpec{ Type: "select", Default: "auto-edit", Choices: []BuiltinOptionChoice{ - {Value: "auto-edit", Label: "Edit automatically", FlagArgs: []string{"--permission-mode", "auto-edit"}}, - {Value: "full-auto", Label: "Full auto", FlagArgs: []string{"--permission-mode", "full-auto"}}, + {Value: "auto-edit", Label: "Edit automatically", FlagArgs: []string{"--permission-mode", "acceptEdits"}}, + {Value: "full-auto", Label: "Full auto", FlagArgs: []string{"--permission-mode", "dontAsk"}}, {Value: "plan", Label: "Plan mode", FlagArgs: []string{"--permission-mode", "plan"}}, {Value: "unrestricted", Label: "Bypass permissions", FlagArgs: []string{"--dangerously-skip-permissions"}}, }, diff --git a/internal/worker/builtin/profiles_test.go b/internal/worker/builtin/profiles_test.go index c7b28817ee..f700a3918a 100644 --- a/internal/worker/builtin/profiles_test.go +++ b/internal/worker/builtin/profiles_test.go @@ -175,3 +175,49 @@ func TestBuiltinCodexModelChoicesIncludeGPT56Variants(t *testing.T) { } } } + +// GH#4602: Claude Code >= 2.1.170 rejects --permission-mode auto-edit / full-auto. +// Config-facing values stay "auto-edit"/"full-auto"; CLI args must be modern modes. +func TestClaudePermissionModeMapsToAcceptedCLIValues(t *testing.T) { + providers := BuiltinProviders() + claude, ok := providers["claude"] + if !ok { + t.Fatal("BuiltinProviders() missing claude") + } + + if got := claude.PermissionModes["auto-edit"]; got != "--permission-mode acceptEdits" { + t.Errorf("PermissionModes[auto-edit] = %q, want --permission-mode acceptEdits", got) + } + if got := claude.PermissionModes["full-auto"]; got != "--permission-mode dontAsk" { + t.Errorf("PermissionModes[full-auto] = %q, want --permission-mode dontAsk", got) + } + + var permOpt BuiltinProviderOption + for _, option := range claude.OptionsSchema { + if option.Key == "permission_mode" { + permOpt = option + break + } + } + if permOpt.Key == "" { + t.Fatal("claude provider missing permission_mode option") + } + byValue := make(map[string]BuiltinOptionChoice, len(permOpt.Choices)) + for _, c := range permOpt.Choices { + byValue[c.Value] = c + } + autoEdit, ok := byValue["auto-edit"] + if !ok { + t.Fatal("claude permission_mode choices missing auto-edit") + } + if len(autoEdit.FlagArgs) != 2 || autoEdit.FlagArgs[0] != "--permission-mode" || autoEdit.FlagArgs[1] != "acceptEdits" { + t.Errorf("auto-edit FlagArgs = %v, want [--permission-mode acceptEdits]", autoEdit.FlagArgs) + } + fullAuto, ok := byValue["full-auto"] + if !ok { + t.Fatal("claude permission_mode choices missing full-auto") + } + if len(fullAuto.FlagArgs) != 2 || fullAuto.FlagArgs[0] != "--permission-mode" || fullAuto.FlagArgs[1] != "dontAsk" { + t.Errorf("full-auto FlagArgs = %v, want [--permission-mode dontAsk]", fullAuto.FlagArgs) + } +} diff --git a/internal/worker/invocation_telemetry.go b/internal/worker/invocation_telemetry.go index caa142c4c8..eb67be150a 100644 --- a/internal/worker/invocation_telemetry.go +++ b/internal/worker/invocation_telemetry.go @@ -517,6 +517,71 @@ func (f *Factory) SweepSessionModelUsage(ctx context.Context, id string, meta ma slog.String("session_id", id), slog.String("provider", family)) return 0, false, nil } + return f.sweepResolvedTranscript(ctx, family, id, meta, path, now) +} + +// DiscoverSweepTranscript resolves the transcript path for a model-usage +// sweep without reading it. It preserves the same bounded keyed and keyless +// discovery rules as SweepSessionModelUsage so callers can safely memoize a +// stable rollout path across repeated incremental sweeps. +// +// settled classifies a miss with the same meaning SweepSessionModelUsage gives +// it, so a caller that memoizes discovery can distinguish the two kinds: true +// means there is definitively nothing to find (an unregistered provider family, +// or a keyless codex session whose bounded workdir+window fallback came up empty +// on a CLEAN scan) and re-running discovery is pure waste; false means the miss +// is transient (a keyed rollout not flushed yet, or a keyless scan clouded by an +// I/O fault, which leaves both an empty result and a lone hit non-definitive) and +// a later attempt may resolve it. A found path is always settled. +func (f *Factory) DiscoverSweepTranscript(id string, meta map[string]string, now time.Time) (path string, settled bool) { + id = strings.TrimSpace(id) + if f == nil || id == "" || meta == nil { + return "", true + } + family := invocationUsageFamily(sessionpkg.ProviderFamilyFromMetadata(meta, "")) + if _, ok := invocationUsageSpecs[family]; !ok { + return "", true + } + path, scanClean := f.discoverSweepTranscript(family, id, meta, now) + keylessCodex := family == "codex" && strings.TrimSpace(meta["session_key"]) == "" + if keylessCodex && !scanClean { + return "", false + } + if path == "" { + return "", keylessCodex + } + return path, true +} + +// SweepSessionModelUsageAtPath performs the same cursor-guarded extraction, +// fact emission, metrics, and cursor persistence as SweepSessionModelUsage, +// using an already-resolved transcript path instead of repeating discovery. +// An empty path is a transient miss so callers can retry on a later tick. +func (f *Factory) SweepSessionModelUsageAtPath(ctx context.Context, id string, meta map[string]string, path string, now time.Time) (emitted int, settled bool, err error) { + id = strings.TrimSpace(id) + if f == nil || id == "" || meta == nil { + return 0, true, nil + } + sink := f.usageSink + if sink == nil || sink == usage.Discard { + return 0, true, nil + } + family := invocationUsageFamily(sessionpkg.ProviderFamilyFromMetadata(meta, "")) + if _, ok := invocationUsageSpecs[family]; !ok { + slog.Debug("model-usage sweep (at path): unregistered provider family; skipping", + slog.String("session_id", id), slog.String("provider", strings.TrimSpace(meta["provider"]))) + return 0, true, nil + } + if strings.TrimSpace(path) == "" { + return 0, false, nil + } + return f.sweepResolvedTranscript(ctx, family, id, meta, path, now) +} + +// sweepResolvedTranscript owns the post-discovery model-usage sweep shared by +// the discovery-driven and already-resolved entry points. +func (f *Factory) sweepResolvedTranscript(ctx context.Context, family, id string, meta map[string]string, path string, now time.Time) (emitted int, settled bool, err error) { + sink := f.usageSink usages, extractErr := f.Adapter().InvocationUsage(family, path) if extractErr != nil { // Transient: a torn mid-write tail can fail the parse; retry on a later tick. diff --git a/pkg/eventexport/golden_test.go b/pkg/eventexport/golden_test.go index 9c29ebe137..f83a35754e 100644 --- a/pkg/eventexport/golden_test.go +++ b/pkg/eventexport/golden_test.go @@ -88,7 +88,7 @@ func TestGoldenWireBytes(t *testing.T) { func slicePtr(values []string) *[]string { return &values } // TestBatchGoldenBytes pins the batch envelope shape: an opaque city_hash (never -// a cleartext city name) and schema_version 4. +// a cleartext city name) and schema_version 5. func TestBatchGoldenBytes(t *testing.T) { b := Batch{CityHash: "7f3a9c1e5b2d4068", SchemaVersion: SchemaVersion, Events: []Envelope{ {Seq: 1, Type: "convoy.closed", TS: "2026-06-21T10:03:27Z", ActorHash: "0123456789abcdef", Ref: "gcg-4216"}, @@ -97,7 +97,7 @@ func TestBatchGoldenBytes(t *testing.T) { if err != nil { t.Fatal(err) } - want := `{"city_hash":"7f3a9c1e5b2d4068","schema_version":4,"events":[{"seq":1,"type":"convoy.closed","ts":"2026-06-21T10:03:27Z","actor_hash":"0123456789abcdef","ref":"gcg-4216"}]}` + want := `{"city_hash":"7f3a9c1e5b2d4068","schema_version":5,"events":[{"seq":1,"type":"convoy.closed","ts":"2026-06-21T10:03:27Z","actor_hash":"0123456789abcdef","ref":"gcg-4216"}]}` if string(out) != want { t.Fatalf("batch golden:\n got %s\nwant %s", out, want) } @@ -111,7 +111,7 @@ func TestBatchGoldenBytes(t *testing.T) { func TestAllowlistPolicyGolden(t *testing.T) { wantAllowed := []string{ "bead.closed", "bead.created", "controller.started", "convoy.closed", - "events.rotated", "execution.step_defined", "execution.work_associated", + "events.rotated", "execution.step_completed", "execution.step_defined", "execution.step_started", "execution.work_associated", "gc.store.maintenance.done", "mail.sent", "order.completed", "order.failed", "order.fired", "project.identity.stamped", "session.drain_acked_with_assigned_work", @@ -121,7 +121,7 @@ func TestAllowlistPolicyGolden(t *testing.T) { if got := AllowedTypeList(); !reflect.DeepEqual(got, wantAllowed) { t.Fatalf("allowlist policy changed:\n got %v\n want %v\n-> update this golden AND bump SchemaVersion", got, wantAllowed) } - if got := sortedKeys(refTypes); !reflect.DeepEqual(got, []string{"bead.closed", "bead.created", "convoy.closed", "execution.step_defined", "execution.work_associated"}) { + if got := sortedKeys(refTypes); !reflect.DeepEqual(got, []string{"bead.closed", "bead.created", "convoy.closed", "execution.step_completed", "execution.step_defined", "execution.step_started", "execution.work_associated"}) { t.Fatalf("refTypes policy changed: got %v -> bump SchemaVersion", got) } if got := sortedKeys(mailReduced); !reflect.DeepEqual(got, []string{"mail.sent"}) { diff --git a/pkg/eventexport/project.go b/pkg/eventexport/project.go index 6558a9b1bb..e28119a72a 100644 --- a/pkg/eventexport/project.go +++ b/pkg/eventexport/project.go @@ -78,7 +78,7 @@ import ( // an operator-chosen city name no longer leaves the box. v3 adds native // execution-step dependencies to the envelope. v4 adds fail-closed execution // work-association and step-definition facts. -const SchemaVersion = 4 +const SchemaVersion = 5 // Profile selects the redaction profile. There is exactly one today; it is part // of the public API so Validate can stay profile-aware as profiles are added @@ -121,6 +121,8 @@ var allowedTypes = map[string]bool{ "controller.started": true, "events.rotated": true, "execution.step_defined": true, + "execution.step_started": true, + "execution.step_completed": true, "execution.work_associated": true, "session.drain_acked_with_assigned_work": true, "session.reset_stalled": true, @@ -144,6 +146,8 @@ var refTypes = map[string]bool{ "bead.closed": true, "convoy.closed": true, "execution.step_defined": true, + "execution.step_started": true, + "execution.step_completed": true, "execution.work_associated": true, } @@ -323,10 +327,12 @@ func ProjectEvent(te TaggedEvent, opt Options) (Envelope, bool) { var executionFactTypes = map[string]bool{ "execution.work_associated": true, "execution.step_defined": true, + "execution.step_started": true, + "execution.step_completed": true, } func projectExecutionFact(te TaggedEvent, opt Options) (Envelope, bool) { - if !opt.EmitCorrelation || !opt.ExportRef || te.SessionID != "" || te.Title != "" || te.Formula != "" { + if !opt.EmitCorrelation || !opt.ExportRef || te.Title != "" || te.Formula != "" { return Envelope{}, false } ref, runID := safeRef(te.Subject), safeRef(te.RunID) @@ -343,20 +349,31 @@ func projectExecutionFact(te TaggedEvent, opt Options) (Envelope, bool) { } switch te.Type { case "execution.work_associated": - if te.StepID != "" || te.DependsOnStepIDs != nil { + if te.SessionID != "" || te.StepID != "" || te.DependsOnStepIDs != nil { return Envelope{}, false } case "execution.step_defined": + if te.SessionID != "" { + return Envelope{}, false + } + fallthrough + case "execution.step_started", "execution.step_completed": stepID := validExecutionStepID(te.StepID) if stepID == "" { return Envelope{}, false } + if (te.Type == "execution.step_started" || te.Type == "execution.step_completed") && safeRef(te.SessionID) == "" { + return Envelope{}, false + } dependencies, ok := normalizeStepDependencies(stepID, te.DependsOnStepIDs) if !ok { return Envelope{}, false } env.StepID = stepID env.DependsOnStepIDs = dependencies + if te.Type == "execution.step_started" || te.Type == "execution.step_completed" { + env.SessionID = safeRef(te.SessionID) + } } return env, true } @@ -429,18 +446,22 @@ func validateExecutionFact(env Envelope) error { if env.Ref == "" || env.RunID == "" { return fmt.Errorf("eventexport: %q requires nonempty ref and run_id", env.Type) } - if env.SessionID != "" || env.Title != "" || env.Formula != "" { - return fmt.Errorf("eventexport: %q must not carry session_id or content", env.Type) + if env.Title != "" || env.Formula != "" { + return fmt.Errorf("eventexport: %q must not carry content", env.Type) } switch env.Type { case "execution.work_associated": - if env.StepID != "" || env.DependsOnStepIDs != nil { + if env.SessionID != "" || env.StepID != "" || env.DependsOnStepIDs != nil { return fmt.Errorf("eventexport: %q must not carry step topology", env.Type) } case "execution.step_defined": - if env.StepID == "" { + if env.SessionID != "" || env.StepID == "" { return fmt.Errorf("eventexport: %q requires step_id", env.Type) } + case "execution.step_started", "execution.step_completed": + if env.SessionID == "" || env.StepID == "" { + return fmt.Errorf("eventexport: %q requires session_id and step_id", env.Type) + } } return nil } diff --git a/pkg/eventexport/project_test.go b/pkg/eventexport/project_test.go index 87dfc9bca0..c91bc30288 100644 --- a/pkg/eventexport/project_test.go +++ b/pkg/eventexport/project_test.go @@ -246,6 +246,30 @@ func TestProjectEventExecutionFactsFailClosed(t *testing.T) { } } +func TestProjectEventExecutionLifecycleFactsRequireDurableIdentity(t *testing.T) { + on := Options{Salt: testSalt, ExportRef: true, EmitCorrelation: true} + deps := []string{"prepare"} + for _, typ := range []string{"execution.step_started", "execution.step_completed"} { + t.Run(typ, func(t *testing.T) { + event := TaggedEvent{Seq: 1, Type: typ, Ts: fixedTS, Actor: "worker", Subject: "gcg-attempt", RunID: "gcg-run", SessionID: "gcs-session", StepID: "build", DependsOnStepIDs: &deps} + got, ok := ProjectEvent(event, on) + if !ok || got.Ref != event.Subject || got.RunID != event.RunID || got.SessionID != event.SessionID || got.StepID != event.StepID || !reflect.DeepEqual(got.DependsOnStepIDs, &deps) { + t.Fatalf("ProjectEvent() = %#v, %v; want lifecycle fact", got, ok) + } + for _, remove := range []func(*TaggedEvent){ + func(e *TaggedEvent) { e.Subject = "" }, func(e *TaggedEvent) { e.RunID = "" }, + func(e *TaggedEvent) { e.SessionID = "" }, func(e *TaggedEvent) { e.StepID = "" }, + } { + bad := event + remove(&bad) + if _, ok := ProjectEvent(bad, on); ok { + t.Fatalf("ProjectEvent accepted incomplete lifecycle event %#v", bad) + } + } + }) + } +} + func TestProjectEventRejectsInvalidPresentNativeTopology(t *testing.T) { deps := []string{"step-a", "step-a"} if _, ok := ProjectEvent(TaggedEvent{ diff --git a/pkg/eventexport/validate_test.go b/pkg/eventexport/validate_test.go index 1361e90be0..10b7cb4ed7 100644 --- a/pkg/eventexport/validate_test.go +++ b/pkg/eventexport/validate_test.go @@ -44,6 +44,8 @@ func TestValidateEnvelopeExecutionFactsFailClosed(t *testing.T) { {Seq: 2, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", StepID: "root"}, {Seq: 3, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", StepID: "root", DependsOnStepIDs: &[]string{}}, {Seq: 4, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", StepID: "build", DependsOnStepIDs: &[]string{"root"}}, + {Seq: 5, Type: "execution.step_started", TS: rfc(t), Ref: "gcg-attempt", RunID: "gcg-root", SessionID: "gcs-session", StepID: "build", DependsOnStepIDs: &[]string{"root"}}, + {Seq: 6, Type: "execution.step_completed", TS: rfc(t), Ref: "gcg-attempt", RunID: "gcg-root", SessionID: "gcs-session", StepID: "build", DependsOnStepIDs: &[]string{"root"}}, } for _, env := range valid { if err := ValidateEnvelope(env); err != nil { @@ -52,17 +54,19 @@ func TestValidateEnvelopeExecutionFactsFailClosed(t *testing.T) { } for name, env := range map[string]Envelope{ - "work missing ref": {Seq: 5, Type: "execution.work_associated", TS: rfc(t), RunID: "gcg-root"}, - "work missing run": {Seq: 6, Type: "execution.work_associated", TS: rfc(t), Ref: "mc-work"}, - "work session": {Seq: 7, Type: "execution.work_associated", TS: rfc(t), Ref: "mc-work", RunID: "gcg-root", SessionID: "gcs-1"}, - "work step": {Seq: 8, Type: "execution.work_associated", TS: rfc(t), Ref: "mc-work", RunID: "gcg-root", StepID: "step"}, - "work topology": {Seq: 9, Type: "execution.work_associated", TS: rfc(t), Ref: "mc-work", RunID: "gcg-root", DependsOnStepIDs: &[]string{}}, - "step missing ref": {Seq: 10, Type: "execution.step_defined", TS: rfc(t), RunID: "gcg-root", StepID: "step"}, - "step missing run": {Seq: 11, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", StepID: "step"}, - "step missing id": {Seq: 12, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root"}, - "step session": {Seq: 13, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", SessionID: "gcs-1", StepID: "step"}, - "step title": {Seq: 14, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", StepID: "step", Title: "free form"}, - "step formula": {Seq: 15, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", StepID: "step", Formula: "free form"}, + "work missing ref": {Seq: 5, Type: "execution.work_associated", TS: rfc(t), RunID: "gcg-root"}, + "work missing run": {Seq: 6, Type: "execution.work_associated", TS: rfc(t), Ref: "mc-work"}, + "work session": {Seq: 7, Type: "execution.work_associated", TS: rfc(t), Ref: "mc-work", RunID: "gcg-root", SessionID: "gcs-1"}, + "work step": {Seq: 8, Type: "execution.work_associated", TS: rfc(t), Ref: "mc-work", RunID: "gcg-root", StepID: "step"}, + "work topology": {Seq: 9, Type: "execution.work_associated", TS: rfc(t), Ref: "mc-work", RunID: "gcg-root", DependsOnStepIDs: &[]string{}}, + "step missing ref": {Seq: 10, Type: "execution.step_defined", TS: rfc(t), RunID: "gcg-root", StepID: "step"}, + "step missing run": {Seq: 11, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", StepID: "step"}, + "step missing id": {Seq: 12, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root"}, + "step session": {Seq: 13, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", SessionID: "gcs-1", StepID: "step"}, + "step title": {Seq: 14, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", StepID: "step", Title: "free form"}, + "step formula": {Seq: 15, Type: "execution.step_defined", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", StepID: "step", Formula: "free form"}, + "started missing session": {Seq: 16, Type: "execution.step_started", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", StepID: "step"}, + "completed missing step": {Seq: 17, Type: "execution.step_completed", TS: rfc(t), Ref: "gcg-step", RunID: "gcg-root", SessionID: "gcs-session"}, } { t.Run(name, func(t *testing.T) { if err := ValidateEnvelope(env); err == nil { diff --git a/release-gates/ga-mwrstg-sling-formula-attach-routing-fix-gate.md b/release-gates/ga-mwrstg-sling-formula-attach-routing-fix-gate.md new file mode 100644 index 0000000000..d45b0e21ea --- /dev/null +++ b/release-gates/ga-mwrstg-sling-formula-attach-routing-fix-gate.md @@ -0,0 +1,42 @@ +# Release gate: sling formula-attach routing fix + +- **Deploy bead:** `ga-mwrstg` +- **Build bead:** `ga-f43t9b` +- **Review bead:** `ga-gr10vs` +- **Reviewed source:** `13362a5c4b42a30ee8cdcd3f5e8632e1911f0126` +- **Base checked:** `origin/main` at `ad4d0ab4a9e14f57faed3eaa20a658ef743e1c09` +- **Isolated gate branch:** `deploy/ga-mwrstg-gate` +**Verdict:** **PASS** + +`docs/PROJECT_MANIFEST.md` is absent from both the reviewed source and current +`origin/main`, so there are no additional repository-local release criteria to +apply beyond the seven deployer criteria below. + +## Gate criteria + +| # | Criterion | Result | Evidence | +|---|-----------|--------|----------| +| 1 | Review PASS present | PASS | Review bead `ga-gr10vs` records `REVIEWER VERDICT: PASS` for the feature at `23f6f1af7`, with all six acceptance items checked directly. The post-review gate repair at `13362a5c4` only removes the newly introduced legacy `formulatest` coupling; the deploy bead records that SHA as the repaired authoritative source. | +| 2 | Acceptance criteria met | PASS | Direct inspection confirms formula attachment writes `beadmeta.ExecutionRoutedToMetadataKey` after resolving and normalizing pool routes, preserves the default-formula idempotent warning, limits workflow-root dry-run disclosure to formulas v2, and leaves `gc.routed_to` unset on the source bead. Focused tests: `go test -json -count=1 ./internal/sling` = 232 PASS, 0 FAIL, 0 SKIP; `GC_FAST_UNIT=0 go test -json -count=1 ./cmd/gc -run 'TestDryRun\|Sling'` = 226 PASS, 0 FAIL, 0 SKIP. | +| 3 | Tests pass | PASS | Documented CI-equivalent coverage used `make test-local-full-parallel` with the pinned `bd` v1.1.0 release (`8e4e59d39`). Gate accounting after environment-corrected reruns: 38 jobs PASS, 0 feature FAIL, 2 justified SKIP. The two skipped tmux jobs use exact-key `list-keys` syntax that returns empty under host tmux 3.7b; the exact three-test comparison produces the same two failures on this head and current `origin/main`, while the hidden-client test passes. This is safe for a change limited to `cmd/gc/cmd_sling*` and `internal/sling/*`. Five corrected REST shards then passed with the real platform home and an isolated home only for the pinned `bd` process (90 top-level tests, 0 FAIL). The regression guard `GC_FAST_UNIT=0 go test -json -count=1 ./internal/testenv -run '^TestLegacyFormulaV2MechanismFrozen$'` = 1 PASS, 0 FAIL, 0 SKIP. | +| 4 | No high-severity review findings open | PASS | The review records zero unresolved HIGH findings, and no new high-severity finding was identified during gate inspection. | +| 5 | Final branch is clean | PASS | The isolated branch was clean at the reviewed source before this checklist was added. The checklist is the only gate-owned file and will be committed before push; the post-commit cleanliness check is required below. | +| 6 | Branch diverges cleanly from main | PASS | Evaluated first and refreshed after `origin/main` advanced. `git merge-base origin/main 13362a5c4` is `a585e07a9`; `git merge-tree --write-tree origin/main 13362a5c4` returned 0 against `ad4d0ab4a` and produced tree `3c52e0a15dc6dadb2d4df3cd47b1702ca8def514`. No bounded self-rebase was needed. The already-merged pre-flight found no base-repository commit or PR for the reviewed source. | +| 7 | Single feature theme | PASS | All four commits and all four changed files form one `sling` feature: formula-attachment route restamping, its idempotent messaging and formulas-v2 dry-run disclosure, plus direct regression coverage. | + +## Additional static evidence + +- `go vet ./...` — PASS. +- `LINT_CHANGED_SCOPE=tracked LINT_CHANGED_REF=a585e07a93782c24a629359cf635f9e95beded5d make lint-affected` — PASS, 0 issues. +- `LINT_CHANGED_SCOPE=tracked LINT_CHANGED_REF=a585e07a93782c24a629359cf635f9e95beded5d make fmt-check-changed` — PASS. +- `git diff --check a585e07a93782c24a629359cf635f9e95beded5d..HEAD` — PASS. +- `git config core.hooksPath` — `.githooks`. + +## Reviewed history + +```text +8038caf7a fix(sling): restamp gc.routed_to on formula-attach and disclose it in --dry-run +d1e958485 test(sling): red — regression coverage for #4763 fix plan (refs ga-f43t9b) +23f6f1af7 fix(sling): fix default-formula skip message and scope dry-run wisp-root disclosure to graph.v2 (refs ga-f43t9b) +13362a5c4 test(sling): drop legacy formulatest coupling from graph.v2 dry-run test (refs ga-mwrstg) +``` diff --git a/scripts/bd_version_pin_test.go b/scripts/bd_version_pin_test.go index 38c2907bf1..6510e9e3ef 100644 --- a/scripts/bd_version_pin_test.go +++ b/scripts/bd_version_pin_test.go @@ -57,7 +57,6 @@ func TestBDVersionPins(t *testing.T) { if !regexp.MustCompile(`^v?\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$`).MatchString(bdCurrent) { t.Fatalf("deps.env BD_CURRENT_VERSION = %q, want a semver token", bdCurrent) } - // Bridge-mode detection. The installable default is built from source when // deps.env carries BD_SOURCE_REF — the version/ref split that mirrors the // BD_CURRENT_VERSION/BD_CURRENT_REF pair above, so BD_VERSION can stay a real @@ -73,6 +72,34 @@ func TestBDVersionPins(t *testing.T) { } bdVersionIsCommit := bridgeRef != "" + // The unified-pin invariant (go.mod, the bleeding-edge contract-matrix + // cell, and the agent image all on ONE commit) is upstream's shape and + // only holds when no bridge is active. In bridge mode this fork + // deliberately splits them: go.mod and the image follow BD_SOURCE_REF + // (the lockstep checks below), while BD_CURRENT_REF may point at a newer + // beads commit so the contract matrix exercises gc against the schema the + // planned migration will move to (ga-zzcjs, ga-y1xxg). + if bridgeRef == "" { + // The native Go store, the bleeding-edge contract-matrix cell, and the + // source-built agent image must all use the same upstream commit. A drift + // here can pair one schema catalog with another version's write behavior. + goMod := readFile(t, root, "go.mod") + goModMatch := regexp.MustCompile(`(?m)^\s*github\.com/steveyegge/beads\s+v\S+-([0-9a-f]{12})\s*$`).FindStringSubmatch(goMod) + if goModMatch == nil { + t.Fatal("go.mod missing a pseudo-version pin for github.com/steveyegge/beads") + } + if got, want := goModMatch[1], bdCurrentRef[:12]; got != want { + t.Fatalf("go.mod beads pseudo-version commit = %q, want BD_CURRENT_REF prefix %q", got, want) + } + dockerfile := readFile(t, root, "contrib/k8s/Dockerfile.agent") + if !strings.Contains(dockerfile, "ARG BD_SOURCE_REF="+bdCurrentRef) { + t.Fatalf("contrib/k8s/Dockerfile.agent BD_SOURCE_REF must equal deps.env BD_CURRENT_REF (%s)", bdCurrentRef) + } + if !strings.Contains(dockerfile, "ARG BD_BUILD="+bdCurrentRef[:10]) { + t.Fatalf("contrib/k8s/Dockerfile.agent BD_BUILD must equal the first 10 characters of BD_CURRENT_REF (%s)", bdCurrentRef[:10]) + } + } + // Lockstep with the linked library. The bd binary CI installs and the beads // library gc links must carry the same schema-migration level: a go.mod // pseudo-version (untagged beads commit) alongside a released BD_VERSION — diff --git a/scripts/check-native-dependency-surface.sh b/scripts/check-native-dependency-surface.sh index 00be1345a0..19f2713ede 100644 --- a/scripts/check-native-dependency-surface.sh +++ b/scripts/check-native-dependency-surface.sh @@ -1,7 +1,12 @@ #!/usr/bin/env bash set -euo pipefail -max_modules="${GC_NATIVE_DEP_MAX_MODULES:-727}" +# 728 = upstream's 727 + 1 for the beads-bridge era: the fork's beads pin +# (deps.env BD_SOURCE_REF) keeps github.com/wk8/go-ordered-map/v2 in the graph +# while upstream's otel v1.44 bump adds go.opentelemetry.io/otel/metric/x, and +# each parent sat exactly at the cap with only one of the two. Drop back to +# upstream's value when the planned beads repin (ga-zzcjs) retires the bridge. +max_modules="${GC_NATIVE_DEP_MAX_MODULES:-728}" max_binary_bytes="${GC_NATIVE_DEP_MAX_BINARY_BYTES:-270000000}" max_aws_modules="${GC_NATIVE_DEP_MAX_AWS_MODULES:-25}" max_azure_modules="${GC_NATIVE_DEP_MAX_AZURE_MODULES:-9}" diff --git a/scripts/container_tool_security_test.go b/scripts/container_tool_security_test.go index e902f27e5d..89aedb3583 100644 --- a/scripts/container_tool_security_test.go +++ b/scripts/container_tool_security_test.go @@ -71,13 +71,14 @@ func TestContainerCLIToolsRebuildWithPatchedGRPC(t *testing.T) { func TestAgentImageRebuildsBDAndGCWithPatchedGRPC(t *testing.T) { const ( // FORK DIVERGENCE — TIME-BOXED BRIDGE (ADR-0026 C5, vp-kpoi, ga-kgluj). - // Upstream pins bd source at 8e4e59d39 / sha 63597b6b… / build 8e4e59d39. - // That commit tops out at schema migration 0053, but gc's linked beads - // library (go.mod v1.1.1-0.20260704062855-e97839a2e1c0) carries 0054, so - // an image built from upstream's ref ships a bd that skews from the linked - // lib. These three move together and revert together: when a bd release - // carries 0054, restore upstream's values here, set deps.env BD_VERSION to - // that tag, drop BD_SOURCE_REF/BD_SOURCE_SHA256, and repin go.mod. + // Upstream now pins bd source at bf97b73749 (2026-08-05, schema 0062); + // this fork deliberately stays on e97839a2 (schema 0054) because moving + // past 0054 migrates the fleet's live stores through irreversible + // migrations (0059/0061/0062 ship no down.sql) and is planned as a + // coordinated rehearsed cutover, not a resync side effect. These three + // values move together with go.mod and deps.env; the cutover replaces + // them with the fleet's Voxist/beads fork commit (ga-zzcjs) or, once a + // bd release >= 0054 exists, with that tag. // BD_VERSION itself is NOT diverged — the pinned commit declares 1.1.0. bdSourceRef = "e97839a2e1c0de305bf64a01b997f2f314591aa4" bdSourceSHA256 = "e40acdcbca7bdc08b986113692e11be7a533b9fced326c20e786f141c29996f1" @@ -153,7 +154,7 @@ func TestAgentImageRebuildsBDAndGCWithPatchedGRPC(t *testing.T) { } } -func TestMCPMailImagePinsPatchedGitPythonAndPillow(t *testing.T) { +func TestMCPMailImagePinsPatchedPythonDependencies(t *testing.T) { root := repoRoot(t) input := readFile(t, root, ".github/requirements/mcp-agent-mail.in") for _, want := range []string{ @@ -165,7 +166,6 @@ func TestMCPMailImagePinsPatchedGitPythonAndPillow(t *testing.T) { t.Errorf("mcp-agent-mail input requirements missing security floor %q", want) } } - // cryptography is capped by a transitive constraint, so its floor lives in // the overrides file rather than the input requirements. overrides := readFile(t, root, ".github/requirements/mcp-agent-mail.overrides.txt") diff --git a/scripts/lint_readonly_contract_test.go b/scripts/lint_readonly_contract_test.go new file mode 100644 index 0000000000..f49bd15fcf --- /dev/null +++ b/scripts/lint_readonly_contract_test.go @@ -0,0 +1,228 @@ +package scripts_test + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "gopkg.in/yaml.v3" +) + +func TestLintUsesReadonlyModuleDownloads(t *testing.T) { + configPath := filepath.Join(repoRoot(t), ".golangci.yml") + body, err := os.ReadFile(configPath) + if err != nil { + t.Fatalf("read %s: %v", configPath, err) + } + + var config struct { + Run struct { + ModulesDownloadMode string `yaml:"modules-download-mode"` + } `yaml:"run"` + } + if err := yaml.Unmarshal(body, &config); err != nil { + t.Fatalf("parse %s: %v", configPath, err) + } + if config.Run.ModulesDownloadMode != "readonly" { + t.Fatalf("run.modules-download-mode = %q, want readonly", config.Run.ModulesDownloadMode) + } + + makefile, err := os.ReadFile(filepath.Join(repoRoot(t), "Makefile")) + if err != nil { + t.Fatalf("read Makefile: %v", err) + } + const readonlyGOFlags = "QUALITY_GATE_GOFLAGS = $$(go env GOFLAGS | sed -E 's/(^|[[:space:]])-mod=[^[:space:]]+//g') -mod=readonly" + if !strings.Contains(string(makefile), readonlyGOFlags) { + t.Fatalf("Makefile must derive QUALITY_GATE_GOFLAGS from effective GOFLAGS") + } + for target, wantGOFLAGS := range map[string]string{ + "lint-full": `GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + "lint-new": `GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + "lint-changed": `export GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + "lint-affected": `GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + } { + t.Run(target, func(t *testing.T) { + body := makeTargetBody(t, string(makefile), target) + for _, override := range []string{"--config", "--no-config"} { + if strings.Contains(body, override) { + t.Fatalf("%s overrides shared lint configuration with %q", target, override) + } + } + if strings.Contains(body, "--modules-download-mode") { + t.Fatalf("%s must not rely on a lint CLI module-mode override", target) + } + if !strings.Contains(body, wantGOFLAGS) { + t.Fatalf("%s must scope QUALITY_GATE_GOFLAGS to its subprocess tree", target) + } + }) + } +} + +func TestQualityGateTargetsUseReadonlyModuleDownloads(t *testing.T) { + makefile, err := os.ReadFile(filepath.Join(repoRoot(t), "Makefile")) + if err != nil { + t.Fatalf("read Makefile: %v", err) + } + const readonlyGOFlags = "QUALITY_GATE_GOFLAGS = $$(go env GOFLAGS | sed -E 's/(^|[[:space:]])-mod=[^[:space:]]+//g') -mod=readonly" + if !strings.Contains(string(makefile), readonlyGOFlags) { + t.Fatalf("Makefile must normalize QUALITY_GATE_GOFLAGS from effective GOFLAGS") + } + + for target, wantGOFLAGS := range map[string]string{ + "fmt-check": `GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + "fmt-check-changed": `GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + "vet": `GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + "test": `$(TEST_ENV) GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + "test-fsys-darwin-compile": `$(TEST_ENV) GOFLAGS="$(QUALITY_GATE_GOFLAGS)"`, + } { + t.Run(target, func(t *testing.T) { + if body := makeTargetBody(t, string(makefile), target); !strings.Contains(body, wantGOFLAGS) { + t.Fatalf("%s must scope QUALITY_GATE_GOFLAGS to its subprocess tree", target) + } + }) + } +} + +func TestFmtCheckDoesNotModifyGoSumWithAmbientWritableModuleMode(t *testing.T) { + fixture := newPRStaticScopeFixture(t, map[string]string{ + "example.go": "package example\n\nfunc Value() int { return 1 }\n", + }) + goSumPath := filepath.Join(fixture.repoRoot, "go.sum") + writeTestFile(t, goSumPath, "example.com/dependency v1.0.0 h1:before\n") + + mutatingLint := filepath.Join(t.TempDir(), "golangci-lint") + writeExecutable(t, mutatingLint, `#!/bin/sh +set -eu +case "${GOFLAGS-}" in + *-tags=quality*) ;; + *) + echo "formatter lost non-module GOFLAGS" >&2 + exit 1 + ;; +esac +case "${GOFLAGS-}" in + *-mod=readonly*) exit 0 ;; +esac +printf '%s\n' 'unexpected writable formatter resolution' >> go.sum +`) + + cmd := makeCommand( + "--no-print-directory", + "-f", fixture.productionMakefile, + "GOLANGCI_LINT="+mutatingLint, + "fmt-check", + ) + cmd.Dir = fixture.repoRoot + env := fixture.commandEnv() + for index, entry := range env { + if strings.HasPrefix(entry, "GOFLAGS=") { + env[index] = "GOFLAGS=-tags=quality -mod=mod" + } + } + cmd.Env = env + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("fmt-check failed: %v\n%s", err, output) + } + + got, err := os.ReadFile(goSumPath) + if err != nil { + t.Fatalf("read go.sum after fmt-check: %v", err) + } + const want = "example.com/dependency v1.0.0 h1:before\n" + if string(got) != want { + t.Fatalf("fmt-check modified go.sum under ambient -mod=mod:\nwant: %q\n got: %q", want, got) + } +} + +func TestLintChangedFailsClosedWhenReadonlyMetadataIsStale(t *testing.T) { + fixture := newPRStaticScopeFixture(t, map[string]string{ + "alpha/alpha.go": "package alpha\n\nfunc Value() int { return 1 }\n", + }) + writeTestFile(t, filepath.Join(fixture.repoRoot, "go.sum"), "example.com/dependency v1.0.0 h1:before\n") + writeTestFile(t, filepath.Join(fixture.repoRoot, "alpha", "alpha.go"), "package alpha\n\nfunc Value() int { return 2 }\n") + + goTool := filepath.Join(t.TempDir(), "go") + writeExecutable(t, goTool, `#!/bin/sh +set -eu +case "${1-}" in + env) + if [ "${2-}" = "GOFLAGS" ]; then + printf '%s\n' "${GOFLAGS-}" + fi + exit 0 + ;; + list) + case "${GOFLAGS-}" in + *-mod=readonly*) + echo "go: updates to go.sum needed; disabled by -mod=readonly" >&2 + exit 1 + ;; + esac + echo "unexpected writable module resolution" >> go.sum + exit 0 + ;; +esac +echo "unexpected go invocation: $*" >&2 +exit 1 +`) + + before, err := os.ReadFile(filepath.Join(fixture.repoRoot, "go.sum")) + if err != nil { + t.Fatalf("read go.sum before lint: %v", err) + } + fixture.resetCalls(t) + cmd := makeCommand( + "--no-print-directory", + "-f", fixture.productionMakefile, + "GOLANGCI_LINT="+fixture.fakeLint, + "LINT_CHANGED_SCOPE=tracked", + "LINT_CHANGED_REF=HEAD", + "LINT_FLAGS=", + "lint-changed", + ) + cmd.Dir = fixture.repoRoot + env := fixture.commandEnv() + for index, entry := range env { + if strings.HasPrefix(entry, "GOFLAGS=") { + env[index] = "GOFLAGS=-mod=mod" + } + } + env = append(env, "PATH="+filepath.Dir(goTool)+string(os.PathListSeparator)+os.Getenv("PATH")) + cmd.Env = env + output, err := cmd.CombinedOutput() + if err == nil { + t.Fatalf("lint-changed succeeded with stale readonly metadata:\n%s", output) + } + if !strings.Contains(string(output), "updates to go.sum needed") { + t.Fatalf("lint-changed error did not preserve the module failure:\n%s", output) + } + after, err := os.ReadFile(filepath.Join(fixture.repoRoot, "go.sum")) + if err != nil { + t.Fatalf("read go.sum after lint: %v", err) + } + if string(after) != string(before) { + t.Fatalf("lint-changed modified go.sum under ambient -mod=mod:\nbefore: %q\nafter: %q", before, after) + } + fixture.requireNoCalls(t) +} + +func makeTargetBody(t *testing.T, makefile, target string) string { + t.Helper() + prefix := target + ":" + start := strings.Index(makefile, "\n"+prefix) + if start >= 0 { + start++ + } else if strings.HasPrefix(makefile, prefix) { + start = 0 + } + if start < 0 { + t.Fatalf("Makefile has no %s target", target) + } + body := makefile[start:] + if next := strings.Index(body, "\n## "); next >= 0 { + body = body[:next] + } + return body +} diff --git a/scripts/runtime-tmux-tests.manifest b/scripts/runtime-tmux-tests.manifest index c5572c7b46..82078c6f06 100644 --- a/scripts/runtime-tmux-tests.manifest +++ b/scripts/runtime-tmux-tests.manifest @@ -77,12 +77,17 @@ TestNudgeNowHiddenAttachedRecordsPoke TestNudgePokeRealTmux TestNudgeSessionConfirmsSubmitForClaude TestNudgeSessionReEntersUntilSubmittedForClaude +TestNudgeSessionReturnsUnconfirmedErrorWhenNeverBusyForClaude TestSubmitEnterAndConfirmReEntersWhileIdle TestSubmitEnterAndConfirmStopsWhenBusy TestSubmitEnterAndConfirmNoDoubleSubmitOnFastTurn TestSubmitEnterAndConfirmBestEffortWhenNeverBusy TestSubmitEnterAndConfirmClearsStaleSendError TestSubmitEnterAndConfirmReturnsSendError +TestSendNudgeSubmitSequenceSendsEachKeyInOrder +TestNudgeSessionUsesDeclaredSequenceForProviderFamily +TestNudgeSubmitKeySequenceForFamilyDefaultsToEnter +TestNudgeSubmitKeySequenceForFamilyHonorsTableEntry TestTmuxSeamsLifecycle TestNewSessionErrNoServerRefusesObservedLiveNamedSocket TestNewSessionErrNoServerObservedSafeAllowsCreation diff --git a/scripts/runtime_tmux_manifest_test.go b/scripts/runtime_tmux_manifest_test.go index bc05100425..e0f2610ef4 100644 --- a/scripts/runtime_tmux_manifest_test.go +++ b/scripts/runtime_tmux_manifest_test.go @@ -24,22 +24,22 @@ func TestRuntimeTmuxManifestMatchesCanonicalLinuxIntegrationInventory(t *testing if drift := runtimeTmuxManifestDrift(manifest, declared); len(drift) != 0 { t.Fatalf("runtime-tmux manifest drift:\n%s\nupdate %s", strings.Join(drift, "\n"), runtimeTmuxManifestRelativePath) } - if got, want := len(manifest), 341; got != want { + if got, want := len(manifest), 346; got != want { t.Fatalf("runtime-tmux manifest contains %d tests, want %d", got, want) } untagged := discoverRuntimeTmuxTests(t, dir, "linux", false) - if got, want := len(untagged), 230; got != want { + if got, want := len(untagged), 232; got != want { t.Fatalf("runtime-tmux untagged inventory contains %d tests, want %d", got, want) } - if got, want := len(declared)-len(untagged), 111; got != want { + if got, want := len(declared)-len(untagged), 114; got != want { t.Fatalf("runtime-tmux integration-only inventory contains %d tests, want %d", got, want) } } func TestRuntimeTmuxManifestSixShardsPartitionInventoryExactlyOnce(t *testing.T) { manifest := parseRuntimeTmuxManifest(t, filepath.Join(repoRoot(t), runtimeTmuxManifestRelativePath)) - wantShardCounts := []int{57, 57, 57, 57, 57, 56} + wantShardCounts := []int{58, 58, 58, 58, 57, 57} seen := make(map[string]int, len(manifest)) for shardIndex := 0; shardIndex < len(wantShardCounts); shardIndex++ { diff --git a/test/integration/bdstore_batch_delete_test.go b/test/integration/bdstore_batch_delete_test.go index cf82cca6f7..a4c6d19cf6 100644 --- a/test/integration/bdstore_batch_delete_test.go +++ b/test/integration/bdstore_batch_delete_test.go @@ -39,7 +39,7 @@ func TestBdStoreDeleteBatchOrphansExternalDependents(t *testing.T) { runBDInit(t, env, wsDir, "bd", serverPort) configureCustomTypes(t, env, wsDir, doctor.RequiredCustomTypes) - store := beads.NewBdStore(wsDir, beads.ExecCommandRunner()) + store := beads.NewBdStore(wsDir, pinnedBdStoreCommandRunner()) // Ownership closure: root + child (child is a parent-child descendant). root, err := store.Create(beads.Bead{Title: "closure root", Type: "task", Status: "closed"}) diff --git a/test/integration/bdstore_test.go b/test/integration/bdstore_test.go index 14fafc589c..f3b3c86fa4 100644 --- a/test/integration/bdstore_test.go +++ b/test/integration/bdstore_test.go @@ -79,7 +79,7 @@ func TestBdStoreConformance(t *testing.T) { configureCustomTypes(t, env, wsDir, doctor.RequiredCustomTypes) - return beads.NewBdStore(wsDir, beads.ExecCommandRunner()) + return beads.NewBdStore(wsDir, pinnedBdStoreCommandRunner()) } // Run conformance suite. We skip RunSequentialIDTests because BdStore @@ -200,7 +200,7 @@ func TestBdStoreMailWispInsert(t *testing.T) { runBDInit(t, env, wsDir, "mc", serverPort) configureCustomTypes(t, env, wsDir, doctor.RequiredCustomTypes) - store := beads.NewBdStore(wsDir, beads.ExecCommandRunner()) + store := beads.NewBdStore(wsDir, pinnedBdStoreCommandRunner()) // Create an ephemeral message bead — exercises bd create --ephemeral → // Dolt SQL INSERT INTO wisps + INSERT INTO wisp_events. diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 3f2185bf67..cb0d8f9444 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -201,14 +201,9 @@ func TestMain(m *testing.M) { realBDBinary = override } else { var err error - realBDBinary, err = exec.LookPath("bd") + realBDBinary, err = buildPinnedIntegrationBDBinary(tmpDir) if err != nil { - // bd not available — skip all integration tests. - _ = os.RemoveAll(tmpDir) - if tmuxSocketParent != "" { - _ = os.RemoveAll(tmuxSocketParent) - } - os.Exit(0) + panic("integration: building pinned bd binary: " + err.Error()) } } bdBinary = filepath.Join(integrationToolBinDir, "bd") @@ -391,6 +386,67 @@ func binaryOverride(envName string) (string, bool, error) { return path, true, nil } +// buildPinnedIntegrationBDBinary builds bd from the exact Beads module that +// the integration test binary and gc both import. Resolving PATH here lets an +// older host bd open the database after gc has migrated it, producing a schema +// skew that obscures the workflow under test. +func buildPinnedIntegrationBDBinary(tmpDir string) (string, error) { + version, err := pinnedIntegrationBeadsModuleVersion() + if err != nil { + return "", err + } + binDir := filepath.Join(tmpDir, "pinned-bd") + if err := os.MkdirAll(binDir, 0o755); err != nil { + return "", fmt.Errorf("create pinned bd directory: %w", err) + } + cmd := exec.Command("go", "install", "-tags", "gms_pure_go", "github.com/steveyegge/beads/cmd/bd@"+version) + cmd.Env = append(os.Environ(), "CGO_ENABLED=0", "GOBIN="+binDir) + if out, err := cmd.CombinedOutput(); err != nil { + return "", fmt.Errorf("go install github.com/steveyegge/beads/cmd/bd@%s: %w\n%s", version, err, out) + } + return filepath.Join(binDir, "bd"), nil +} + +// pinnedBdStoreCommandRunner keeps direct BdStore integration tests on the +// same bd shim used by their setup commands. The default runner resolves the +// ambient process PATH before its per-command environment applies, so using it +// directly could select a host bd whose schema knowledge predates the pinned +// Beads module that created the test database. +func pinnedBdStoreCommandRunner() beads.CommandRunner { + runner := beads.ExecCommandRunner() + return func(dir, name string, args ...string) ([]byte, error) { + if name == "bd" { + name = bdBinary + } + return runner(dir, name, args...) + } +} + +func pinnedIntegrationBeadsModuleVersion() (string, error) { + cmd := exec.Command("go", "list", "-m", "-f", "{{.Version}}", "github.com/steveyegge/beads") + cmd.Dir = findModuleRoot() + out, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("resolve github.com/steveyegge/beads module version: %w\n%s", err, out) + } + version := strings.TrimSpace(string(out)) + if version == "" { + return "", errors.New("github.com/steveyegge/beads module version is empty") + } + return version, nil +} + +func TestPinnedIntegrationBeadsModuleVersion(t *testing.T) { + version, err := pinnedIntegrationBeadsModuleVersion() + if err != nil { + t.Fatalf("pinnedIntegrationBeadsModuleVersion() error = %v", err) + } + const want = "v1.1.1-0.20260805093327-bf97b73749ac" + if version != want { + t.Errorf("pinnedIntegrationBeadsModuleVersion() = %q, want %q", version, want) + } +} + func writeExecShim(path, target string) error { script := "#!/bin/sh\nexec " + singleQuoteShell(target) + ` "$@"` + "\n" return os.WriteFile(path, []byte(script), 0o755) diff --git a/test/test-resources.toml b/test/test-resources.toml index 4d13d10dd0..b9d8853bce 100644 --- a/test/test-resources.toml +++ b/test/test-resources.toml @@ -10,7 +10,7 @@ version = 2 [[audit_baseline]] scope = "all" resource = "subprocess" -baseline_calls = 552 +baseline_calls = 555 baseline_files = 168 reported_calls = 495 reported_files = 135 @@ -23,8 +23,8 @@ expires = "2026-10-01" [[audit_baseline]] scope = "all" resource = "fixed_sleep" -baseline_calls = 432 -baseline_files = 160 +baseline_calls = 437 +baseline_files = 161 reported_calls = 447 reported_files = 157 owner_bead = "ga-80po0c.2" @@ -51,7 +51,7 @@ expires = "2026-10-01" [[debt]] scope = "untagged" resource = "subprocess" -baseline_calls = 413 +baseline_calls = 414 baseline_files = 117 reported_calls = 380 reported_files = 98 @@ -344,7 +344,7 @@ medium_reason = "package TestMain mutates process state" [[small_debt]] scope = "untagged" resource = "subprocess" -baseline_calls = 407 +baseline_calls = 408 baseline_files = 114 reported_calls = 394 reported_files = 105