From 73f80c9f540178e70d380027fb44400f67786feb Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 27 Oct 2026 03:02:07 -0600 Subject: [PATCH] fix: close agent boundaries and attempt lifecycle gaps --- README.md | 11 +- cmd/jig/cancellation_test.go | 31 +++++ cmd/jig/ci_repair_test.go | 5 + cmd/jig/worker.go | 29 ++-- internal/controlplane/http.go | 45 ++++-- internal/controlplane/http_host_test.go | 67 +++++++++ internal/controlplane/store_test.go | 3 + internal/controlplane/sweep.go | 3 + internal/engine/boundary.go | 72 +++++++--- internal/engine/boundary_test.go | 109 ++++++++++++++- internal/engine/parallel.go | 10 ++ internal/engine/parallel_test.go | 37 +++++ internal/engine/phase.go | 10 +- internal/engine/phase_test.go | 40 ++++++ web/dist/assets/index-CUNI1f9t.js | 177 ------------------------ web/dist/assets/index-Earanm8w.js | 177 ++++++++++++++++++++++++ web/dist/index.html | 2 +- web/src/polling.test.ts | 45 ++++++ web/src/polling.ts | 4 + 19 files changed, 650 insertions(+), 227 deletions(-) create mode 100644 cmd/jig/cancellation_test.go create mode 100644 internal/controlplane/http_host_test.go delete mode 100644 web/dist/assets/index-CUNI1f9t.js create mode 100644 web/dist/assets/index-Earanm8w.js create mode 100644 web/src/polling.test.ts diff --git a/README.md b/README.md index 4c8e0aa..4acfca9 100644 --- a/README.md +++ b/README.md @@ -494,6 +494,11 @@ modifications, renames are decomposed into literal paths, and gitignored files, the `.git` directory, and hook paths are all watched, because a planted hook would execute during jig's own later git commands. +Comparison and file rollback use the pre-phase commit, so committing an edit +does not hide it. A read-only role that moves `HEAD` aborts even if it later +reverts the edit. Jig retains that history for inspection rather than +rewriting it; a crashed phase that moved `HEAD` is not retried. + What follows from that: **the `writes` allowlist is the security control you actually configure.** `writes: ["**"]` (the stock builders' default, so the examples work anywhere) is the weakest boundary jig can enforce. Narrow it. @@ -546,7 +551,11 @@ wrapper script wrong. `jig serve` binds `127.0.0.1` and refuses a non-loopback address without `--allow-non-loopback`. There is no authentication and no TLS: the control -plane assumes one trusted operator on one machine. State-changing routes also +plane assumes one trusted operator on one machine. Read routes reject untrusted +Host headers even without an Origin header, preventing DNS-rebound names from +reading local data. An explicitly enabled non-loopback listener accepts its own +IP address; reverse proxies must rewrite Host to the listener's authority or +present the UI token. State-changing routes also reject requests whose `Origin` is not the server's own, which is what stops a web page you happen to be visiting from driving your control plane through your browser. diff --git a/cmd/jig/cancellation_test.go b/cmd/jig/cancellation_test.go new file mode 100644 index 0000000..843ec5c --- /dev/null +++ b/cmd/jig/cancellation_test.go @@ -0,0 +1,31 @@ +package main + +import ( + "testing" + "time" +) + +func TestCancellationMergeStopsOnCompletionOrEitherInput(t *testing.T) { + for _, cause := range []string{"completion", "signal", "job"} { + t.Run(cause, func(t *testing.T) { + signal, job := make(chan struct{}), make(chan struct{}) + cancelled, stop := anyClosed(signal, job) + defer stop() + switch cause { + case "completion": + stop() + case "signal": + close(signal) + case "job": + close(job) + } + select { + case <-cancelled: + case <-time.After(time.Second): + t.Fatal("cancellation waiters did not stop") + } + // stop waits for all helpers, including the input that never closed. + stop() + }) + } +} diff --git a/cmd/jig/ci_repair_test.go b/cmd/jig/ci_repair_test.go index dfcf257..36981ab 100644 --- a/cmd/jig/ci_repair_test.go +++ b/cmd/jig/ci_repair_test.go @@ -287,6 +287,11 @@ func TestReleasingTheRepairContinuationDrainsTheTraceBeforeTheAttemptCompletes(t t.Fatal(err) } gate := &ingestGate{proxy: httputil.NewSingleHostReverseProxy(target)} + director := gate.proxy.Director + gate.proxy.Director = func(request *http.Request) { + director(request) + request.Host = target.Host + } proxy := httptest.NewServer(gate) defer proxy.Close() diff --git a/cmd/jig/worker.go b/cmd/jig/worker.go index 2fdef74..9441d75 100644 --- a/cmd/jig/worker.go +++ b/cmd/jig/worker.go @@ -322,15 +322,22 @@ func workerAttemptRunner( // (which rides the heartbeat response) and the operator's Ctrl-C. The // engine watches one channel, so they are merged rather than the // second one being dropped. + cancelled, stopCancellation := anyClosed(signalCtx.Done(), prepared.Cancelled()) + defer func() { + if !kept { + stopCancellation() + } + }() outcome := runner.Execute(context.WithoutCancel(ctx), engine.Attempt{ Claim: prepared.Claim, WorktreePath: prepared.WorktreePath, Branch: prepared.Branch, BaseSHA: prepared.BaseSHA, - Cancelled: anyClosed(signalCtx.Done(), prepared.Cancelled()), + Cancelled: cancelled, FreshenLease: prepared.FreshenLease, }) kept = worker.DeferToContinuation(&outcome, func() { + stopCancellation() closeTrace() removeScratch() }) @@ -339,24 +346,28 @@ func workerAttemptRunner( } // anyClosed merges cancellation channels: the result closes as soon as any -// input does. It never blocks the caller and never leaks past the first -// close, which is all the engine's one-shot cancellation signal needs. -func anyClosed(channels ...<-chan struct{}) <-chan struct{} { - merged := make(chan struct{}) - var once sync.Once +// input does. The owner stops its waiters after normal completion too (R5). +func anyClosed(channels ...<-chan struct{}) (<-chan struct{}, func()) { + ctx, cancel := context.WithCancel(context.Background()) + var waiters sync.WaitGroup for _, channel := range channels { if channel == nil { continue } + waiters.Add(1) go func(c <-chan struct{}) { + defer waiters.Done() select { case <-c: - once.Do(func() { close(merged) }) - case <-merged: + cancel() + case <-ctx.Done(): } }(channel) } - return merged + return ctx.Done(), func() { + cancel() + waiters.Wait() + } } // printReconcileReport is the operator's startup picture: identity, probed diff --git a/internal/controlplane/http.go b/internal/controlplane/http.go index 014fd3d..4c15d8c 100644 --- a/internal/controlplane/http.go +++ b/internal/controlplane/http.go @@ -1,14 +1,13 @@ // http.go — the control plane's HTTP surface (U2). JSON in, JSON out, // bounded request bodies, and browser-origin fencing on every state-changing // route (R20): a request carrying an Origin header must first present a -// trustworthy Host authority (loopback, never a resolved name — see -// hostAuthorityIsTrusted, which closes the DNS-rebinding hole where an +// trustworthy Host authority (loopback or the listener's IP, never a resolved +// name — see hostAuthorityIsTrusted, which closes the DNS-rebinding hole where an // attacker's domain resolves to 127.0.0.1 and Origin/Host agree with each // other but not with reality), then either the server's own origin or the -// per-process UI token. Requests without an Origin header (the worker, -// curl) pass — the check exists to stop foreign web pages from driving a -// loopback control plane through the operator's browser, not to -// authenticate local clients. +// per-process UI token. Reads require a trusted Host even without Origin. +// Originless mutations (the worker, curl) pass — the check stops foreign web +// pages from driving the control plane, not to authenticate local clients. package controlplane import ( @@ -70,7 +69,17 @@ func NewHandler(store *Store, uiToken string, logger *slog.Logger) http.Handler api.registerTriggerRoutes(mux) api.registerIngestRoutes(mux) api.registerReportRoutes(mux) - return mux + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Read routes also need Host fencing: DNS rebinding can read same-origin + // data without sending an Origin header (R20). + if (r.Method == http.MethodGet || r.Method == http.MethodHead) && + !api.uiTokenPresented(r) && !hostAuthorityIsTrusted(r) { + writeError(w, &ServiceError{Code: "untrusted_host_authority", + Message: "requests must target a trusted listener host", Status: 403}) + return + } + mux.ServeHTTP(w, r) + }) } func (a *API) health(w http.ResponseWriter, r *http.Request) { @@ -354,7 +363,7 @@ func (a *API) prepareMutation(w http.ResponseWriter, r *http.Request) bool { // trusting any comparison against it. if !hostAuthorityIsTrusted(r) { writeError(w, &ServiceError{Code: "untrusted_host_authority", - Message: "state-changing requests must target a loopback host", Status: 403}) + Message: "state-changing requests must target a trusted listener host", Status: 403}) return false } parsed, err := url.Parse(origin) @@ -378,10 +387,10 @@ func sameAuthority(left, right string) bool { return strings.EqualFold(strings.TrimSuffix(left, "."), strings.TrimSuffix(right, ".")) } -// hostAuthorityIsTrusted reports whether r.Host names loopback rather than -// an attacker's DNS-rebound domain (R20). The hostname must be a loopback -// IP literal (127.0.0.0/8, ::1) or "localhost" — never resolved, so a -// rebound name can never satisfy it by any DNS trick. When Host carries a +// hostAuthorityIsTrusted reports whether r.Host names loopback or the +// listener's own IP rather than an attacker's DNS-rebound domain (R20). +// Hostnames are never resolved, so a rebound name cannot pass by a DNS trick. +// When Host carries a // port and the server's own listener port is known from the connection // (net/http sets LocalAddrContextKey per accepted connection; direct // ServeHTTP calls in tests do not), that port must match too, closing the @@ -390,7 +399,17 @@ func sameAuthority(left, right string) bool { func hostAuthorityIsTrusted(r *http.Request) bool { host, port, hasPort := splitHostAuthority(r.Host) if !isLoopbackHostname(host) { - return false + // An explicitly enabled non-loopback listener accepts its own IP, + // never an arbitrary DNS name that could rebind to it (R20). + addr, ok := r.Context().Value(http.LocalAddrContextKey).(net.Addr) + if !ok { + return false + } + localHost, _, err := net.SplitHostPort(addr.String()) + ip := net.ParseIP(host) + if err != nil || ip == nil || !ip.Equal(net.ParseIP(localHost)) { + return false + } } if !hasPort { return true diff --git a/internal/controlplane/http_host_test.go b/internal/controlplane/http_host_test.go new file mode 100644 index 0000000..790bfb8 --- /dev/null +++ b/internal/controlplane/http_host_test.go @@ -0,0 +1,67 @@ +package controlplane + +import ( + "context" + "net" + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestReadRoutesFenceReboundHostsWithoutRequiringOrigin(t *testing.T) { + store, _ := newTestStore(t) + handler := NewHandler(store, "test-ui-token", nil) + for _, method := range []string{http.MethodGet, http.MethodHead} { + for _, origin := range []string{"", "http://evil.test:8383"} { + for _, path := range []string{"/api/definitions", "/api/runs", "/api/workers", "/api/health"} { + request := httptest.NewRequest(method, "http://evil.test:8383"+path, nil) + request.Header.Set("Origin", origin) + response := httptest.NewRecorder() + handler.ServeHTTP(response, request) + if response.Code != http.StatusForbidden || !strings.Contains(response.Body.String(), "untrusted_host_authority") { + t.Fatalf("%s %s origin=%q: %d %s", method, path, origin, response.Code, response.Body.String()) + } + } + } + } + for _, host := range []string{"127.0.0.1:8383", "localhost:8383", "[::1]:8383"} { + request := httptest.NewRequest(http.MethodGet, "http://"+host+"/api/health", nil) + response := httptest.NewRecorder() + handler.ServeHTTP(response, request) + if response.Code != http.StatusOK { + t.Fatalf("trusted Host %s: %d", host, response.Code) + } + } + request := httptest.NewRequest(http.MethodGet, "http://evil.test/api/health", nil) + request.Header.Set("X-Jig-UI-Token", "test-ui-token") + response := httptest.NewRecorder() + handler.ServeHTTP(response, request) + if response.Code != http.StatusOK { + t.Fatalf("explicit UI token: %d", response.Code) + } +} + +func TestReadHostMustMatchListenerPortAndExplicitNonLoopbackIP(t *testing.T) { + store, _ := newTestStore(t) + handler := NewHandler(store, "", nil) + for _, test := range []struct { + host string + want int + }{ + {"127.0.0.1:8383", http.StatusOK}, + {"127.0.0.1:9000", http.StatusForbidden}, + {"192.0.2.10:8383", http.StatusOK}, + {"192.0.2.11:8383", http.StatusForbidden}, + {"evil.test:8383", http.StatusForbidden}, + } { + request := httptest.NewRequest(http.MethodGet, "http://"+test.host+"/api/health", nil) + request = request.WithContext(context.WithValue(request.Context(), http.LocalAddrContextKey, + &net.TCPAddr{IP: net.ParseIP("192.0.2.10"), Port: 8383})) + response := httptest.NewRecorder() + handler.ServeHTTP(response, request) + if response.Code != test.want { + t.Fatalf("host %s: %d, want %d", test.host, response.Code, test.want) + } + } +} diff --git a/internal/controlplane/store_test.go b/internal/controlplane/store_test.go index 9b45129..9b50a93 100644 --- a/internal/controlplane/store_test.go +++ b/internal/controlplane/store_test.go @@ -477,6 +477,9 @@ func TestNMissedHeartbeatsSweepTheAttemptToLostAndAStaleCompletionIsRejected(t * if job.State != protocol.JobFailed { t.Fatalf("job state = %q, want failed after sweep", job.State) } + if got := runState(t, store, claim.Job.RunID); got != protocol.RunFailed { + t.Fatalf("run state = %q, want failed after sweep", got) + } // The zombie wakes and tries to complete with its stale token. _, err = store.CompleteAttempt(ctx, claim.Attempt.ID, protocol.CompleteAttemptRequest{ LeaseToken: tokenA, State: protocol.AttemptAccepted, Result: "zombie work", diff --git a/internal/controlplane/sweep.go b/internal/controlplane/sweep.go index 3ff9ac0..f9b9d62 100644 --- a/internal/controlplane/sweep.go +++ b/internal/controlplane/sweep.go @@ -179,6 +179,9 @@ func (s *Store) sweepAttempt(ctx context.Context, attemptID string, nowMillis in `, nowMillis, value.JobID); err != nil { return value, false, unavailable(err) } + if err := applyRunAggregationForJob(ctx, tx, value.JobID, nowMillis); err != nil { + return value, false, err + } if err := tx.Commit(); err != nil { return value, false, unavailable(err) } diff --git a/internal/engine/boundary.go b/internal/engine/boundary.go index 8f1442c..259e009 100644 --- a/internal/engine/boundary.go +++ b/internal/engine/boundary.go @@ -78,6 +78,8 @@ type fingerprint map[string]string // worktree entirely) and must never be confusable with a repository path an // allowlist pattern could match. type treeSnapshot struct { + // head pins comparison and rollback before an agent can move HEAD (R10). + head string // paths is worktree content keyed by repo-relative path: tracked files // differing from HEAD, untracked files, and ignored-but-present paths. paths fingerprint @@ -95,14 +97,27 @@ type treeSnapshot struct { // HEAD, every untracked or ignored path present in it, and the repository // metadata that can make jig's own git commands execute code. func snapshotTree(ctx context.Context, dir string) (treeSnapshot, error) { + return snapshotTreeAt(ctx, dir, "") +} + +func snapshotTreeAt(ctx context.Context, dir, base string) (treeSnapshot, error) { + head, err := runGit(ctx, dir, "rev-parse", "--verify", "HEAD^{commit}") + if err != nil { + return treeSnapshot{}, fmt.Errorf("pin boundary HEAD: %w", err) + } + head = strings.TrimSpace(head) + if base == "" { + base = head + } snapshot := treeSnapshot{ - paths: make(fingerprint), gitMeta: make(fingerprint), ignored: make(map[string]bool), + head: head, paths: make(fingerprint), gitMeta: make(fingerprint), ignored: make(map[string]bool), } - // Tracked paths differing from HEAD. `--no-renames` so a rename is a - // delete plus an add — two literal paths — and `-z` so a path containing + // Compare against the pre-phase commit even after an agent commits (R10). + // `--no-renames` makes a rename a delete plus an add — two literal paths — + // and `-z` so a path containing // a space, quote, or newline arrives verbatim. - tracked, err := runGit(ctx, dir, "diff", "HEAD", "--name-only", "-z", "--no-renames") + tracked, err := runGit(ctx, dir, "diff", base, "--name-only", "-z", "--no-renames") if err != nil { return treeSnapshot{}, fmt.Errorf("fingerprint worktree: %w", err) } @@ -396,10 +411,9 @@ type breach struct { // `a*b.txt` or `:weird` is a path, never a pattern, and never a magic prefix. func literalPathspec(path string) string { return ":(literal)" + path } -// existsInHEAD reports whether HEAD knows the path — the question that -// decides whether rolling back means "restore" or "remove". -func existsInHEAD(ctx context.Context, dir, path string) bool { - _, err := runGit(ctx, dir, "cat-file", "-e", "HEAD:"+path) +// existsAtCommit asks whether rollback means "restore" or "remove" (R10). +func existsAtCommit(ctx context.Context, dir, commit, path string) bool { + _, err := runGit(ctx, dir, "cat-file", "-e", commit+":"+path) return err == nil } @@ -417,17 +431,16 @@ func stagedInIndex(ctx context.Context, dir, path string) bool { // an operator's uncommitted work to tidy up would be the same harm this file // exists to prevent. A pre-dirty path the agent reverted is named loudly; // the content is not ours to reconstruct. -func rollBackPath(ctx context.Context, dir, path string, before, after fingerprint) string { +func rollBackPath(ctx context.Context, dir, path, base string, before, after fingerprint) string { if _, wasDirty := before[path]; wasDirty { if _, stillDirty := after[path]; !stillDirty { return "reverted-by-agent (uncommitted work lost, cannot restore)" } return "left as-is (was already modified)" } - // Restore from HEAD, never from the index: `git checkout -- path` would - // happily restore a breach the agent had staged. - if existsInHEAD(ctx, dir, path) { - if _, err := runGit(ctx, dir, "checkout", "HEAD", "--", literalPathspec(path)); err != nil { + // Restore from the saved commit, never an agent-moved HEAD or index (R10). + if existsAtCommit(ctx, dir, base, path) { + if _, err := runGit(ctx, dir, "checkout", base, "--", literalPathspec(path)); err != nil { return "could not roll back: " + err.Error() } return "rolled back" @@ -461,10 +474,10 @@ func rollBackGitMeta(path string, before fingerprint) string { return "deleted" } -// headPaths is the set of every path tracked in HEAD, read once per +// headPaths is the set of every path tracked in a commit, read once per // enforcement rather than one `cat-file` per changed path. -func headPaths(ctx context.Context, dir string) (map[string]bool, error) { - listing, err := runGit(ctx, dir, "ls-tree", "-r", "-z", "--name-only", "HEAD") +func headPaths(ctx context.Context, dir, head string) (map[string]bool, error) { + listing, err := runGit(ctx, dir, "ls-tree", "-r", "-z", "--name-only", head) if err != nil { return nil, fmt.Errorf("list HEAD paths: %w", err) } @@ -527,16 +540,25 @@ func trackedInHEAD(path string, head map[string]bool) bool { func enforceBoundary( ctx context.Context, dir string, before treeSnapshot, writes, buildOutputs []string, ) (touched, outputs []string, breaches []breach, err error) { - after, err := snapshotTree(ctx, dir) + after, err := snapshotTreeAt(ctx, dir, before.head) if err != nil { return nil, nil, nil, err } var head map[string]bool ignored := make(map[string]bool, len(before.ignored)+len(after.ignored)) if len(buildOutputs) > 0 { - if head, err = headPaths(ctx, dir); err != nil { + if head, err = headPaths(ctx, dir, before.head); err != nil { return nil, nil, nil, err } + if before.head != after.head { + current, err := headPaths(ctx, dir, after.head) + if err != nil { + return nil, nil, nil, err + } + for path := range current { + head[path] = true + } + } for path := range before.ignored { ignored[path] = true } @@ -556,7 +578,7 @@ func enforceBoundary( touched = append(touched, path) continue } - outcome := rollBackPath(ctx, dir, path, before.paths, after.paths) + outcome := rollBackPath(ctx, dir, path, before.head, before.paths, after.paths) // A grant only covers gitignored paths; for an untracked one it // missed, say so, because the operator's fix is a .gitignore line, // not a wider allowlist. A tracked path is never an output at all. @@ -566,6 +588,11 @@ func enforceBoundary( } breaches = append(breaches, breach{Path: path, Outcome: outcome}) } + if writes != nil && len(writes) == 0 && before.head != after.head { + // Even an empty commit or a commit followed by a revert changes history. + breaches = append(breaches, breach{Path: "HEAD", + Outcome: "read-only role moved HEAD (history retained for inspection)"}) + } // Repository metadata is outside every allowlist by construction: // `writes` names repository CONTENT, and no definition may hand a role // the ability to install a hook or re-point the gitdir — not even @@ -586,13 +613,16 @@ func enforceBoundary( // tracked file — is left as-is in its post-agent state SILENTLY: only // `could not…` and `reverted-by-agent` outcomes are returned as failures. func restoreSnapshot(ctx context.Context, dir string, before treeSnapshot) error { - after, err := snapshotTree(ctx, dir) + after, err := snapshotTreeAt(ctx, dir, before.head) if err != nil { return err } var failures []string + if before.head != after.head { + failures = append(failures, "HEAD changed (history retained for inspection)") + } for _, path := range changedPaths(before.paths, after.paths) { - outcome := rollBackPath(ctx, dir, path, before.paths, after.paths) + outcome := rollBackPath(ctx, dir, path, before.head, before.paths, after.paths) if strings.HasPrefix(outcome, "could not") || strings.HasPrefix(outcome, "reverted-by-agent") { failures = append(failures, path+": "+outcome) } diff --git a/internal/engine/boundary_test.go b/internal/engine/boundary_test.go index 6a824eb..c69cda9 100644 --- a/internal/engine/boundary_test.go +++ b/internal/engine/boundary_test.go @@ -7,6 +7,7 @@ package engine import ( "context" + "fmt" "os" "os/exec" "path/filepath" @@ -191,6 +192,112 @@ func TestRestoreSnapshotUndoesACrashedPhase(t *testing.T) { } } +func TestReadOnlyBoundaryDetectsCommittedChanges(t *testing.T) { + for _, change := range []string{"modify", "add", "delete", "empty", "revert"} { + t.Run(change, func(t *testing.T) { + ctx := context.Background() + dir := initBoundaryRepo(t) + before := snapshotOrFail(t, ctx, dir) + switch change { + case "modify", "revert": + write(t, dir, "tracked.txt", "agent edit\n") + case "add": + write(t, dir, "new.txt", "agent file\n") + case "delete": + if err := os.Remove(filepath.Join(dir, "tracked.txt")); err != nil { + t.Fatal(err) + } + } + gitIn(t, dir, "add", "-A") + gitIn(t, dir, "-c", "commit.gpgsign=false", "commit", "--quiet", "--allow-empty", "-m", "agent commit") + if change == "revert" { + gitIn(t, dir, "-c", "commit.gpgsign=false", "revert", "--no-edit", "HEAD") + } + _, _, breaches, err := enforceBoundary(ctx, dir, before, []string{}, nil) + if err != nil { + t.Fatal(err) + } + if !contains(breachPaths(breaches), "HEAD") { + t.Fatalf("committed %s escaped read-only enforcement: %v", change, breaches) + } + body, err := os.ReadFile(filepath.Join(dir, "tracked.txt")) + if err != nil || string(body) != "original\n" { + t.Fatalf("saved content not restored: %q, %v", body, err) + } + if _, err := os.Stat(filepath.Join(dir, "new.txt")); !os.IsNotExist(err) { + t.Fatalf("committed addition survived: %v", err) + } + }) + } +} + +func TestBoundaryAllowsCommittedWritesOnlyInsideAllowlist(t *testing.T) { + ctx := context.Background() + dir := initBoundaryRepo(t) + write(t, dir, "docs/guide.md", "previous draft\n") + before := snapshotOrFail(t, ctx, dir) + write(t, dir, "src/ok.go", "package ok\n") + write(t, dir, "tracked.txt", "forbidden edit\n") + gitIn(t, dir, "add", "-A") + gitIn(t, dir, "-c", "commit.gpgsign=false", "commit", "--quiet", "-m", "agent commit") + touched, _, breaches, err := enforceBoundary(ctx, dir, before, []string{"src/"}, nil) + if err != nil { + t.Fatal(err) + } + if len(touched) != 1 || touched[0] != "src/ok.go" || len(breaches) != 1 || breaches[0].Path != "tracked.txt" { + t.Fatalf("touched=%v breaches=%v", touched, breaches) + } + if body, err := os.ReadFile(filepath.Join(dir, "docs/guide.md")); err != nil || string(body) != "previous draft\n" { + t.Fatalf("previous draft changed: %q, %v", body, err) + } +} + +func TestCrashRollbackUsesSavedCommitAndReportsMovedHistory(t *testing.T) { + ctx := context.Background() + dir := initBoundaryRepo(t) + before := snapshotOrFail(t, ctx, dir) + write(t, dir, "tracked.txt", "crashed agent edit\n") + gitIn(t, dir, "add", "tracked.txt") + gitIn(t, dir, "-c", "commit.gpgsign=false", "commit", "--quiet", "-m", "agent commit") + if err := restoreSnapshot(ctx, dir, before); err == nil || !strings.Contains(err.Error(), "HEAD changed") { + t.Fatalf("moved history must prevent a clean retry: %v", err) + } + if body, err := os.ReadFile(filepath.Join(dir, "tracked.txt")); err != nil || string(body) != "original\n" { + t.Fatalf("rollback restored agent HEAD instead of saved commit: %q, %v", body, err) + } +} + +func TestBuildOutputsExcludePathsTrackedBeforeOrAfterAnAgentCommit(t *testing.T) { + for _, trackedBefore := range []bool{false, true} { + t.Run(fmt.Sprintf("trackedBefore=%t", trackedBefore), func(t *testing.T) { + ctx := context.Background() + dir := initBoundaryRepo(t) + write(t, dir, ".gitignore", "bin/\n") + write(t, dir, "bin/output.txt", "before\n") + gitIn(t, dir, "add", ".gitignore") + if trackedBefore { + gitIn(t, dir, "add", "-f", "bin/output.txt") + } + gitIn(t, dir, "-c", "commit.gpgsign=false", "commit", "--quiet", "-m", "fixture") + before := snapshotOrFail(t, ctx, dir) + if trackedBefore { + gitIn(t, dir, "rm", "bin/output.txt") + } else { + gitIn(t, dir, "add", "-f", "bin/output.txt") + } + gitIn(t, dir, "-c", "commit.gpgsign=false", "commit", "--quiet", "-m", "agent commit") + write(t, dir, "bin/output.txt", "after\n") + _, outputs, breaches, err := enforceBoundary(ctx, dir, before, []string{}, []string{"bin/**"}) + if err != nil { + t.Fatal(err) + } + if len(outputs) != 0 || !contains(breachPaths(breaches), "HEAD") { + t.Fatalf("tracked content exempted: outputs=%v breaches=%v", outputs, breaches) + } + }) + } +} + // ---- renames (finding 2) --------------------------------------------------- // A rename is two literal paths, never git's `{a => b}/f` description. The @@ -748,7 +855,7 @@ func TestRestoreSnapshotRemovesNewBuildOutputsAndReportsOnlyReverts(t *testing.T write(t, dir, "docs/guide.md", "guide\n") // reverts the operator's draft after := snapshotOrFail(t, ctx, dir) - if outcome := rollBackPath(ctx, dir, "bin/", before.paths, after.paths); !strings.HasPrefix(outcome, "left as-is") { + if outcome := rollBackPath(ctx, dir, "bin/", before.head, before.paths, after.paths); !strings.HasPrefix(outcome, "left as-is") { t.Fatalf("pre-existing bin/ outcome = %q, want left as-is", outcome) } err := restoreSnapshot(ctx, dir, before) diff --git a/internal/engine/parallel.go b/internal/engine/parallel.go index fc556ce..e6493ab 100644 --- a/internal/engine/parallel.go +++ b/internal/engine/parallel.go @@ -294,6 +294,16 @@ func (e *execution) runMembers( if panicked || len(terminals) > 0 { break } + if len(next) > 0 { + // A read-only group cannot retry against agent-moved history (R10/R11). + head, err := runGit(context.WithoutCancel(ctx), e.attempt.WorktreePath, "rev-parse", "--verify", "HEAD^{commit}") + if err != nil { + return e.groupInfra(names, "check HEAD before member retry: "+err.Error()) + } + if strings.TrimSpace(head) != before.head { + break // the group's enforcement below reports and rolls back the breach + } + } pending = next } diff --git a/internal/engine/parallel_test.go b/internal/engine/parallel_test.go index 075d89c..6d57003 100644 --- a/internal/engine/parallel_test.go +++ b/internal/engine/parallel_test.go @@ -8,6 +8,7 @@ import ( "context" "encoding/json" "os" + "os/exec" "path/filepath" "reflect" "regexp" @@ -468,6 +469,42 @@ func TestADeadMembersLeftoverWriteIsABreach(t *testing.T) { } } +func TestAParallelMemberThatCommitsAndCrashesIsNotRetried(t *testing.T) { + for _, changed := range []bool{false, true} { + name := "empty commit" + if changed { + name = "committed edit" + } + t.Run(name, func(t *testing.T) { + f := newRepairFixture(t, panelSnapshot(nil, panelGroup), nil) + f.fake.Route(buildRole, writes(map[string]string{"src/app.txt": "app"}, "built")) + f.fake.Route(correctnessRole, enginetest.Step{Crash: true, Do: func(enginetest.Call) { + if changed { + if err := os.WriteFile(filepath.Join(f.repo, "README.md"), []byte("reviewer edit\n"), 0o644); err != nil { + t.Error(err) + return + } + } + command := exec.Command("git", "-c", "gc.auto=0", "-c", "maintenance.auto=false", "-c", "commit.gpgsign=false", + "commit", "--quiet", "--allow-empty", "-am", "reviewer commit") + command.Dir = f.repo + if output, err := command.CombinedOutput(); err != nil { + t.Errorf("reviewer commit: %v: %s", err, output) + } + }}, approve("must not retry", nil)) + f.fake.Route(securityRole, approve("secure", nil)) + f.fake.Route(maintainabilityRole, approve("maintainable", nil)) + outcome := executeWithin(t, f, 20*time.Second) + if outcome.State != protocol.AttemptFailed || !strings.Contains(outcome.Error, "HEAD") { + t.Fatalf("outcome = %s (%s), want a HEAD breach", outcome.State, outcome.Error) + } + if got := len(callsFor(f.fake, correctnessRole)); got != 1 { + t.Fatalf("reviewer invoked %d times, want one before abort", got) + } + }) + } +} + func eventSeq(t *testing.T, sink *recordingSink, eventType, phase string, match func(protocol.Event) bool) int64 { t.Helper() for _, event := range sink.all() { diff --git a/internal/engine/phase.go b/internal/engine/phase.go index 7576cf8..da65cbe 100644 --- a/internal/engine/phase.go +++ b/internal/engine/phase.go @@ -1213,16 +1213,18 @@ func (e *execution) runAgentPhaseAttempt( e.emit.emit(protocol.EventPhaseDeath, phase.Name, phase.Owner, map[string]any{ "phase_attempt": entry, "error": detail, }) + e.recordResult(protocol.PhaseResult{ + Phase: phase.Name, Kind: phase.Kind, Status: protocol.EnvelopeFail, + PhaseAttempt: entry, Error: detail, StartedAt: &started, + }) if !e.grouped { if rollbackErr := restoreSnapshot(ctx, e.attempt.WorktreePath, before); rollbackErr != nil { e.emit.emit(protocol.EventError, phase.Name, "rollback_failed", map[string]string{"error": rollbackErr.Error()}) + return phaseRun{outcome: phaseAborted, + failure: detail + " — rollback failed: " + rollbackErr.Error()}, false } } - e.recordResult(protocol.PhaseResult{ - Phase: phase.Name, Kind: phase.Kind, Status: protocol.EnvelopeFail, - PhaseAttempt: entry, Error: detail, StartedAt: &started, - }) return phaseRun{outcome: phaseFailed, failure: detail}, true } // A phase that fails on parse exhaustion, gate-budget exhaustion, or a diff --git a/internal/engine/phase_test.go b/internal/engine/phase_test.go index ceb2b7a..1e50fcf 100644 --- a/internal/engine/phase_test.go +++ b/internal/engine/phase_test.go @@ -698,6 +698,46 @@ acceptance: [all_phases_passed] } } +func TestCommittedReadOnlyEditAbortsWithoutRetryOnSuccessOrCrash(t *testing.T) { + for _, crash := range []bool{false, true} { + t.Run(fmt.Sprintf("crash=%t", crash), func(t *testing.T) { + repo := initRepo(t) + fake := enginetest.New(enginetest.Step{ + Crash: crash, + Text: envelope(map[string]any{"status": "success"}), + Do: func(call enginetest.Call) { + if err := os.WriteFile(filepath.Join(call.Options.WorkDir, "README.md"), []byte("agent edit\n"), 0o644); err != nil { + t.Fatal(err) + } + for _, args := range [][]string{{"add", "README.md"}, {"-c", "commit.gpgsign=false", "commit", "--quiet", "-m", "agent commit"}} { + command := exec.Command("git", args...) + command.Dir = call.Options.WorkDir + if output, err := command.CombinedOutput(); err != nil { + t.Fatalf("git %v: %v: %s", args, err, output) + } + } + }, + }) + sink := &recordingSink{} + runner := newTestRunner(t, fake, sink, nil) + snapshot := `name: readonly +roster: + reader: {model: test, system_prompt: Read., user_prompt: Read., writes: []} +phases: + - {name: read, kind: agent, owner: reader} +acceptance: [all_phases_passed] +` + outcome := runner.Execute(context.Background(), testAttempt(snapshot, nil, repo)) + if outcome.State != protocol.AttemptFailed || len(fake.Calls()) != 1 { + t.Fatalf("state=%s calls=%d error=%s", outcome.State, len(fake.Calls()), outcome.Error) + } + if !sink.has(protocol.EventError, "write_boundary_breach") && !sink.has(protocol.EventError, "rollback_failed") { + t.Fatalf("no boundary or rollback diagnostic: %s", outcome.Error) + } + }) + } +} + func TestAttemptExceedingItsCeilingTerminatesWithItsOwnTerminalEvent(t *testing.T) { repo := initRepo(t) fake := enginetest.New(enginetest.Step{Hang: true}) diff --git a/web/dist/assets/index-CUNI1f9t.js b/web/dist/assets/index-CUNI1f9t.js deleted file mode 100644 index 0c2550f..0000000 --- a/web/dist/assets/index-CUNI1f9t.js +++ /dev/null @@ -1,177 +0,0 @@ -(function(){const d=document.createElement("link").relList;if(d&&d.supports&&d.supports("modulepreload"))return;for(const S of document.querySelectorAll('link[rel="modulepreload"]'))r(S);new MutationObserver(S=>{for(const O of S)if(O.type==="childList")for(const x of O.addedNodes)x.tagName==="LINK"&&x.rel==="modulepreload"&&r(x)}).observe(document,{childList:!0,subtree:!0});function m(S){const O={};return S.integrity&&(O.integrity=S.integrity),S.referrerPolicy&&(O.referrerPolicy=S.referrerPolicy),S.crossOrigin==="use-credentials"?O.credentials="include":S.crossOrigin==="anonymous"?O.credentials="omit":O.credentials="same-origin",O}function r(S){if(S.ep)return;S.ep=!0;const O=m(S);fetch(S.href,O)}})();var xs={exports:{}},Cn={};var Bd;function Ny(){if(Bd)return Cn;Bd=1;var s=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function m(r,S,O){var x=null;if(O!==void 0&&(x=""+O),S.key!==void 0&&(x=""+S.key),"key"in S){O={};for(var D in S)D!=="key"&&(O[D]=S[D])}else O=S;return S=O.ref,{$$typeof:s,type:r,key:x,ref:S!==void 0?S:null,props:O}}return Cn.Fragment=d,Cn.jsx=m,Cn.jsxs=m,Cn}var Gd;function Ay(){return Gd||(Gd=1,xs.exports=Ny()),xs.exports}var i=Ay(),_s={exports:{}},F={};var wd;function My(){if(wd)return F;wd=1;var s=Symbol.for("react.transitional.element"),d=Symbol.for("react.portal"),m=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),S=Symbol.for("react.profiler"),O=Symbol.for("react.consumer"),x=Symbol.for("react.context"),D=Symbol.for("react.forward_ref"),N=Symbol.for("react.suspense"),_=Symbol.for("react.memo"),Y=Symbol.for("react.lazy"),C=Symbol.for("react.activity"),$=Symbol.iterator;function U(y){return y===null||typeof y!="object"?null:(y=$&&y[$]||y["@@iterator"],typeof y=="function"?y:null)}var R={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},X=Object.assign,Q={};function K(y,M,H){this.props=y,this.context=M,this.refs=Q,this.updater=H||R}K.prototype.isReactComponent={},K.prototype.setState=function(y,M){if(typeof y!="object"&&typeof y!="function"&&y!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,y,M,"setState")},K.prototype.forceUpdate=function(y){this.updater.enqueueForceUpdate(this,y,"forceUpdate")};function ee(){}ee.prototype=K.prototype;function fe(y,M,H){this.props=y,this.context=M,this.refs=Q,this.updater=H||R}var k=fe.prototype=new ee;k.constructor=fe,X(k,K.prototype),k.isPureReactComponent=!0;var Fe=Array.isArray;function we(){}var te={H:null,A:null,T:null,S:null},xe=Object.prototype.hasOwnProperty;function De(y,M,H){var G=H.ref;return{$$typeof:s,type:y,key:M,ref:G!==void 0?G:null,props:H}}function nl(y,M){return De(y.type,M,y.props)}function gt(y){return typeof y=="object"&&y!==null&&y.$$typeof===s}function W(y){var M={"=":"=0",":":"=2"};return"$"+y.replace(/[=:]/g,function(H){return M[H]})}var Ue=/\/+/g;function Ot(y,M){return typeof y=="object"&&y!==null&&y.key!=null?W(""+y.key):M.toString(36)}function ct(y){switch(y.status){case"fulfilled":return y.value;case"rejected":throw y.reason;default:switch(typeof y.status=="string"?y.then(we,we):(y.status="pending",y.then(function(M){y.status==="pending"&&(y.status="fulfilled",y.value=M)},function(M){y.status==="pending"&&(y.status="rejected",y.reason=M)})),y.status){case"fulfilled":return y.value;case"rejected":throw y.reason}}throw y}function E(y,M,H,G,I){var ae=typeof y;(ae==="undefined"||ae==="boolean")&&(y=null);var he=!1;if(y===null)he=!0;else switch(ae){case"bigint":case"string":case"number":he=!0;break;case"object":switch(y.$$typeof){case s:case d:he=!0;break;case Y:return he=y._init,E(he(y._payload),M,H,G,I)}}if(he)return I=I(y),he=G===""?"."+Ot(y,0):G,Fe(I)?(H="",he!=null&&(H=he.replace(Ue,"$&/")+"/"),E(I,M,H,"",function(wa){return wa})):I!=null&&(gt(I)&&(I=nl(I,H+(I.key==null||y&&y.key===I.key?"":(""+I.key).replace(Ue,"$&/")+"/")+he)),M.push(I)),1;he=0;var Ie=G===""?".":G+":";if(Fe(y))for(var Re=0;Re>>1,je=E[ve];if(0>>1;veS(H,J))GS(I,H)?(E[ve]=I,E[G]=J,ve=G):(E[ve]=H,E[M]=J,ve=M);else if(GS(I,J))E[ve]=I,E[G]=J,ve=G;else break e}}return q}function S(E,q){var J=E.sortIndex-q.sortIndex;return J!==0?J:E.id-q.id}if(s.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var O=performance;s.unstable_now=function(){return O.now()}}else{var x=Date,D=x.now();s.unstable_now=function(){return x.now()-D}}var N=[],_=[],Y=1,C=null,$=3,U=!1,R=!1,X=!1,Q=!1,K=typeof setTimeout=="function"?setTimeout:null,ee=typeof clearTimeout=="function"?clearTimeout:null,fe=typeof setImmediate<"u"?setImmediate:null;function k(E){for(var q=m(_);q!==null;){if(q.callback===null)r(_);else if(q.startTime<=E)r(_),q.sortIndex=q.expirationTime,d(N,q);else break;q=m(_)}}function Fe(E){if(X=!1,k(E),!R)if(m(N)!==null)R=!0,we||(we=!0,W());else{var q=m(_);q!==null&&ct(Fe,q.startTime-E)}}var we=!1,te=-1,xe=5,De=-1;function nl(){return Q?!0:!(s.unstable_now()-DeE&&nl());){var ve=C.callback;if(typeof ve=="function"){C.callback=null,$=C.priorityLevel;var je=ve(C.expirationTime<=E);if(E=s.unstable_now(),typeof je=="function"){C.callback=je,k(E),q=!0;break t}C===m(N)&&r(N),k(E)}else r(N);C=m(N)}if(C!==null)q=!0;else{var y=m(_);y!==null&&ct(Fe,y.startTime-E),q=!1}}break e}finally{C=null,$=J,U=!1}q=void 0}}finally{q?W():we=!1}}}var W;if(typeof fe=="function")W=function(){fe(gt)};else if(typeof MessageChannel<"u"){var Ue=new MessageChannel,Ot=Ue.port2;Ue.port1.onmessage=gt,W=function(){Ot.postMessage(null)}}else W=function(){K(gt,0)};function ct(E,q){te=K(function(){E(s.unstable_now())},q)}s.unstable_IdlePriority=5,s.unstable_ImmediatePriority=1,s.unstable_LowPriority=4,s.unstable_NormalPriority=3,s.unstable_Profiling=null,s.unstable_UserBlockingPriority=2,s.unstable_cancelCallback=function(E){E.callback=null},s.unstable_forceFrameRate=function(E){0>E||125ve?(E.sortIndex=J,d(_,E),m(N)===null&&E===m(_)&&(X?(ee(te),te=-1):X=!0,ct(Fe,J-ve))):(E.sortIndex=je,d(N,E),R||U||(R=!0,we||(we=!0,W()))),E},s.unstable_shouldYield=nl,s.unstable_wrapCallback=function(E){var q=$;return function(){var J=$;$=q;try{return E.apply(this,arguments)}finally{$=J}}}})(zs)),zs}var kd;function Dy(){return kd||(kd=1,Es.exports=Oy()),Es.exports}var Ns={exports:{}},$e={};var Ld;function Uy(){if(Ld)return $e;Ld=1;var s=Os();function d(N){var _="https://react.dev/errors/"+N;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(d){console.error(d)}}return s(),Ns.exports=Uy(),Ns.exports}var Vd;function Cy(){if(Vd)return qn;Vd=1;var s=Dy(),d=Os(),m=Ry();function r(e){var t="https://react.dev/errors/"+e;if(1je||(e.current=ve[je],ve[je]=null,je--)}function H(e,t){je++,ve[je]=e.current,e.current=t}var G=y(null),I=y(null),ae=y(null),he=y(null);function Ie(e,t){switch(H(ae,t),H(I,e),H(G,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?cd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=cd(t),e=sd(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}M(G),H(G,e)}function Re(){M(G),M(I),M(ae)}function wa(e){e.memoizedState!==null&&H(he,e);var t=G.current,l=sd(t,e.type);t!==l&&(H(I,e),H(G,l))}function Bn(e){I.current===e&&(M(G),M(I)),he.current===e&&(M(he),On._currentValue=J)}var ni,qs;function Dl(e){if(ni===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);ni=t&&t[1]||"",qs=-1)":-1n||o[a]!==g[n]){var T=` -`+o[a].replace(" at new "," at ");return e.displayName&&T.includes("")&&(T=T.replace("",e.displayName)),T}while(1<=a&&0<=n);break}}}finally{ui=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Dl(l):""}function nh(e,t){switch(e.tag){case 26:case 27:case 5:return Dl(e.type);case 16:return Dl("Lazy");case 13:return e.child!==t&&t!==null?Dl("Suspense Fallback"):Dl("Suspense");case 19:return Dl("SuspenseList");case 0:case 15:return ii(e.type,!1);case 11:return ii(e.type.render,!1);case 1:return ii(e.type,!0);case 31:return Dl("Activity");default:return""}}function Hs(e){try{var t="",l=null;do t+=nh(e,l),l=e,e=e.return;while(e);return t}catch(a){return` -Error generating stack: `+a.message+` -`+a.stack}}var ci=Object.prototype.hasOwnProperty,si=s.unstable_scheduleCallback,fi=s.unstable_cancelCallback,uh=s.unstable_shouldYield,ih=s.unstable_requestPaint,st=s.unstable_now,ch=s.unstable_getCurrentPriorityLevel,Ys=s.unstable_ImmediatePriority,Bs=s.unstable_UserBlockingPriority,Gn=s.unstable_NormalPriority,sh=s.unstable_LowPriority,Gs=s.unstable_IdlePriority,fh=s.log,rh=s.unstable_setDisableYieldValue,Qa=null,ft=null;function ul(e){if(typeof fh=="function"&&rh(e),ft&&typeof ft.setStrictMode=="function")try{ft.setStrictMode(Qa,e)}catch{}}var rt=Math.clz32?Math.clz32:hh,oh=Math.log,dh=Math.LN2;function hh(e){return e>>>=0,e===0?32:31-(oh(e)/dh|0)|0}var wn=256,Qn=262144,Xn=4194304;function Ul(e){var t=e&42;if(t!==0)return t;switch(e&-e){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:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function kn(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var n=0,u=e.suspendedLanes,c=e.pingedLanes;e=e.warmLanes;var f=a&134217727;return f!==0?(a=f&~u,a!==0?n=Ul(a):(c&=f,c!==0?n=Ul(c):l||(l=f&~e,l!==0&&(n=Ul(l))))):(f=a&~u,f!==0?n=Ul(f):c!==0?n=Ul(c):l||(l=a&~e,l!==0&&(n=Ul(l)))),n===0?0:t!==0&&t!==n&&(t&u)===0&&(u=n&-n,l=t&-t,u>=l||u===32&&(l&4194048)!==0)?t:n}function Xa(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function mh(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32: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 t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ws(){var e=Xn;return Xn<<=1,(Xn&62914560)===0&&(Xn=4194304),e}function ri(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function ka(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function yh(e,t,l,a,n,u){var c=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var f=e.entanglements,o=e.expirationTimes,g=e.hiddenUpdates;for(l=c&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var Sh=/[\n"\\]/g;function jt(e){return e.replace(Sh,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function vi(e,t,l,a,n,u,c,f){e.name="",c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?e.type=c:e.removeAttribute("type"),t!=null?c==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+bt(t)):e.value!==""+bt(t)&&(e.value=""+bt(t)):c!=="submit"&&c!=="reset"||e.removeAttribute("value"),t!=null?pi(e,c,bt(t)):l!=null?pi(e,c,bt(l)):a!=null&&e.removeAttribute("value"),n==null&&u!=null&&(e.defaultChecked=!!u),n!=null&&(e.checked=n&&typeof n!="function"&&typeof n!="symbol"),f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"?e.name=""+bt(f):e.removeAttribute("name")}function Ps(e,t,l,a,n,u,c,f){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||l!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){yi(e);return}l=l!=null?""+bt(l):"",t=t!=null?""+bt(t):l,f||t===e.value||(e.value=t),e.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=f?e.checked:!!a,e.defaultChecked=!!a,c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(e.name=c),yi(e)}function pi(e,t,l){t==="number"&&Vn(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function la(e,t,l,a){if(e=e.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),xi=!1;if(Qt)try{var Ka={};Object.defineProperty(Ka,"passive",{get:function(){xi=!0}}),window.addEventListener("test",Ka,Ka),window.removeEventListener("test",Ka,Ka)}catch{xi=!1}var cl=null,_i=null,Jn=null;function cf(){if(Jn)return Jn;var e,t=_i,l=t.length,a,n="value"in cl?cl.value:cl.textContent,u=n.length;for(e=0;e=Wa),hf=" ",mf=!1;function yf(e,t){switch(e){case"keyup":return $h.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function vf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ia=!1;function Fh(e,t){switch(e){case"compositionend":return vf(t);case"keypress":return t.which!==32?null:(mf=!0,hf);case"textInput":return e=t.data,e===hf&&mf?null:e;default:return null}}function Ih(e,t){if(ia)return e==="compositionend"||!Ai&&yf(e,t)?(e=cf(),Jn=_i=cl=null,ia=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Tf(l)}}function zf(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?zf(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Nf(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Vn(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=Vn(e.document)}return t}function Di(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var im=Qt&&"documentMode"in document&&11>=document.documentMode,ca=null,Ui=null,en=null,Ri=!1;function Af(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Ri||ca==null||ca!==Vn(a)||(a=ca,"selectionStart"in a&&Di(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),en&&Pa(en,a)||(en=a,a=Qu(Ui,"onSelect"),0>=c,n-=c,Ct=1<<32-rt(t)+n|l<le?(ce=w,w=null):ce=w.sibling;var oe=b(v,w,p[le],z);if(oe===null){w===null&&(w=ce);break}e&&w&&oe.alternate===null&&t(v,w),h=u(oe,h,le),re===null?L=oe:re.sibling=oe,re=oe,w=ce}if(le===p.length)return l(v,w),se&&kt(v,le),L;if(w===null){for(;lele?(ce=w,w=null):ce=w.sibling;var Ml=b(v,w,oe.value,z);if(Ml===null){w===null&&(w=ce);break}e&&w&&Ml.alternate===null&&t(v,w),h=u(Ml,h,le),re===null?L=Ml:re.sibling=Ml,re=Ml,w=ce}if(oe.done)return l(v,w),se&&kt(v,le),L;if(w===null){for(;!oe.done;le++,oe=p.next())oe=A(v,oe.value,z),oe!==null&&(h=u(oe,h,le),re===null?L=oe:re.sibling=oe,re=oe);return se&&kt(v,le),L}for(w=a(w);!oe.done;le++,oe=p.next())oe=j(w,v,le,oe.value,z),oe!==null&&(e&&oe.alternate!==null&&w.delete(oe.key===null?le:oe.key),h=u(oe,h,le),re===null?L=oe:re.sibling=oe,re=oe);return e&&w.forEach(function(zy){return t(v,zy)}),se&&kt(v,le),L}function be(v,h,p,z){if(typeof p=="object"&&p!==null&&p.type===X&&p.key===null&&(p=p.props.children),typeof p=="object"&&p!==null){switch(p.$$typeof){case U:e:{for(var L=p.key;h!==null;){if(h.key===L){if(L=p.type,L===X){if(h.tag===7){l(v,h.sibling),z=n(h,p.props.children),z.return=v,v=z;break e}}else if(h.elementType===L||typeof L=="object"&&L!==null&&L.$$typeof===xe&&kl(L)===h.type){l(v,h.sibling),z=n(h,p.props),cn(z,p),z.return=v,v=z;break e}l(v,h);break}else t(v,h);h=h.sibling}p.type===X?(z=Bl(p.props.children,v.mode,z,p.key),z.return=v,v=z):(z=nu(p.type,p.key,p.props,null,v.mode,z),cn(z,p),z.return=v,v=z)}return c(v);case R:e:{for(L=p.key;h!==null;){if(h.key===L)if(h.tag===4&&h.stateNode.containerInfo===p.containerInfo&&h.stateNode.implementation===p.implementation){l(v,h.sibling),z=n(h,p.children||[]),z.return=v,v=z;break e}else{l(v,h);break}else t(v,h);h=h.sibling}z=wi(p,v.mode,z),z.return=v,v=z}return c(v);case xe:return p=kl(p),be(v,h,p,z)}if(ct(p))return B(v,h,p,z);if(W(p)){if(L=W(p),typeof L!="function")throw Error(r(150));return p=L.call(p),V(v,h,p,z)}if(typeof p.then=="function")return be(v,h,ou(p),z);if(p.$$typeof===fe)return be(v,h,cu(v,p),z);du(v,p)}return typeof p=="string"&&p!==""||typeof p=="number"||typeof p=="bigint"?(p=""+p,h!==null&&h.tag===6?(l(v,h.sibling),z=n(h,p),z.return=v,v=z):(l(v,h),z=Gi(p,v.mode,z),z.return=v,v=z),c(v)):l(v,h)}return function(v,h,p,z){try{un=0;var L=be(v,h,p,z);return ga=null,L}catch(w){if(w===pa||w===fu)throw w;var re=dt(29,w,null,v.mode);return re.lanes=z,re.return=v,re}}}var Zl=Ff(!0),If=Ff(!1),dl=!1;function Ii(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Pi(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function hl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function ml(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(de&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=au(e),qf(e,null,l),t}return lu(e,a,t,l),au(e)}function sn(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Xs(e,l)}}function ec(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var c={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=c:u=u.next=c,l=l.next}while(l!==null);u===null?n=u=t:u=u.next=t}else n=u=t;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var tc=!1;function fn(){if(tc){var e=va;if(e!==null)throw e}}function rn(e,t,l,a){tc=!1;var n=e.updateQueue;dl=!1;var u=n.firstBaseUpdate,c=n.lastBaseUpdate,f=n.shared.pending;if(f!==null){n.shared.pending=null;var o=f,g=o.next;o.next=null,c===null?u=g:c.next=g,c=o;var T=e.alternate;T!==null&&(T=T.updateQueue,f=T.lastBaseUpdate,f!==c&&(f===null?T.firstBaseUpdate=g:f.next=g,T.lastBaseUpdate=o))}if(u!==null){var A=n.baseState;c=0,T=g=o=null,f=u;do{var b=f.lane&-536870913,j=b!==f.lane;if(j?(ie&b)===b:(a&b)===b){b!==0&&b===ya&&(tc=!0),T!==null&&(T=T.next={lane:0,tag:f.tag,payload:f.payload,callback:null,next:null});e:{var B=e,V=f;b=t;var be=l;switch(V.tag){case 1:if(B=V.payload,typeof B=="function"){A=B.call(be,A,b);break e}A=B;break e;case 3:B.flags=B.flags&-65537|128;case 0:if(B=V.payload,b=typeof B=="function"?B.call(be,A,b):B,b==null)break e;A=C({},A,b);break e;case 2:dl=!0}}b=f.callback,b!==null&&(e.flags|=64,j&&(e.flags|=8192),j=n.callbacks,j===null?n.callbacks=[b]:j.push(b))}else j={lane:b,tag:f.tag,payload:f.payload,callback:f.callback,next:null},T===null?(g=T=j,o=A):T=T.next=j,c|=b;if(f=f.next,f===null){if(f=n.shared.pending,f===null)break;j=f,f=j.next,j.next=null,n.lastBaseUpdate=j,n.shared.pending=null}}while(!0);T===null&&(o=A),n.baseState=o,n.firstBaseUpdate=g,n.lastBaseUpdate=T,u===null&&(n.shared.lanes=0),bl|=c,e.lanes=c,e.memoizedState=A}}function Pf(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function er(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;eu?u:8;var c=E.T,f={};E.T=f,jc(e,!1,t,l);try{var o=n(),g=E.S;if(g!==null&&g(f,o),o!==null&&typeof o=="object"&&typeof o.then=="function"){var T=ym(o,a);hn(e,t,T,pt(e))}else hn(e,t,a,pt(e))}catch(A){hn(e,t,{then:function(){},status:"rejected",reason:A},pt())}finally{q.p=u,c!==null&&f.types!==null&&(c.types=f.types),E.T=c}}function Sm(){}function gc(e,t,l,a){if(e.tag!==5)throw Error(r(476));var n=Ur(e).queue;Dr(e,n,t,J,l===null?Sm:function(){return Rr(e),l(a)})}function Ur(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:J,baseState:J,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Kt,lastRenderedState:J},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Kt,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Rr(e){var t=Ur(e);t.next===null&&(t=e.alternate.memoizedState),hn(e,t.next.queue,{},pt())}function bc(){return Ve(On)}function Cr(){return qe().memoizedState}function qr(){return qe().memoizedState}function xm(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=pt();e=hl(l);var a=ml(t,e,l);a!==null&&(it(a,t,l),sn(a,t,l)),t={cache:Ji()},e.payload=t;return}t=t.return}}function _m(e,t,l){var a=pt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},xu(e)?Yr(t,l):(l=Yi(e,t,l,a),l!==null&&(it(l,e,a),Br(l,t,a)))}function Hr(e,t,l){var a=pt();hn(e,t,l,a)}function hn(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(xu(e))Yr(t,n);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var c=t.lastRenderedState,f=u(c,l);if(n.hasEagerState=!0,n.eagerState=f,ot(f,c))return lu(e,t,n,0),Se===null&&tu(),!1}catch{}if(l=Yi(e,t,n,a),l!==null)return it(l,e,a),Br(l,t,a),!0}return!1}function jc(e,t,l,a){if(a={lane:2,revertLane:Ic(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},xu(e)){if(t)throw Error(r(479))}else t=Yi(e,l,a,2),t!==null&&it(t,e,2)}function xu(e){var t=e.alternate;return e===P||t!==null&&t===P}function Yr(e,t){ja=yu=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Br(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Xs(e,l)}}var mn={readContext:Ve,use:gu,useCallback:ze,useContext:ze,useEffect:ze,useImperativeHandle:ze,useLayoutEffect:ze,useInsertionEffect:ze,useMemo:ze,useReducer:ze,useRef:ze,useState:ze,useDebugValue:ze,useDeferredValue:ze,useTransition:ze,useSyncExternalStore:ze,useId:ze,useHostTransitionStatus:ze,useFormState:ze,useActionState:ze,useOptimistic:ze,useMemoCache:ze,useCacheRefresh:ze};mn.useEffectEvent=ze;var Gr={readContext:Ve,use:gu,useCallback:function(e,t){return Pe().memoizedState=[e,t===void 0?null:t],e},useContext:Ve,useEffect:xr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,ju(4194308,4,zr.bind(null,t,e),l)},useLayoutEffect:function(e,t){return ju(4194308,4,e,t)},useInsertionEffect:function(e,t){ju(4,2,e,t)},useMemo:function(e,t){var l=Pe();t=t===void 0?null:t;var a=e();if(Vl){ul(!0);try{e()}finally{ul(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=Pe();if(l!==void 0){var n=l(t);if(Vl){ul(!0);try{l(t)}finally{ul(!1)}}}else n=t;return a.memoizedState=a.baseState=n,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},a.queue=e,e=e.dispatch=_m.bind(null,P,e),[a.memoizedState,e]},useRef:function(e){var t=Pe();return e={current:e},t.memoizedState=e},useState:function(e){e=hc(e);var t=e.queue,l=Hr.bind(null,P,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:vc,useDeferredValue:function(e,t){var l=Pe();return pc(l,e,t)},useTransition:function(){var e=hc(!1);return e=Dr.bind(null,P,e.queue,!0,!1),Pe().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=P,n=Pe();if(se){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),Se===null)throw Error(r(349));(ie&127)!==0||ir(a,t,l)}n.memoizedState=l;var u={value:l,getSnapshot:t};return n.queue=u,xr(sr.bind(null,a,u,e),[e]),a.flags|=2048,xa(9,{destroy:void 0},cr.bind(null,a,u,l,t),null),l},useId:function(){var e=Pe(),t=Se.identifierPrefix;if(se){var l=qt,a=Ct;l=(a&~(1<<32-rt(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=vu++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?c.createElement("select",{is:a.is}):c.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?c.createElement(n,{is:a.is}):c.createElement(n)}}u[Le]=t,u[et]=a;e:for(c=t.child;c!==null;){if(c.tag===5||c.tag===6)u.appendChild(c.stateNode);else if(c.tag!==4&&c.tag!==27&&c.child!==null){c.child.return=c,c=c.child;continue}if(c===t)break e;for(;c.sibling===null;){if(c.return===null||c.return===t)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}t.stateNode=u;e:switch(Je(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&$t(t)}}return Te(t),Cc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&$t(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=ae.current,ha(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=Ze,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[Le]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||ud(e.nodeValue,l)),e||rl(t,!0)}else e=Xu(e).createTextNode(a),e[Le]=t,t.stateNode=e}return Te(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=ha(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[Le]=t}else Gl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Te(t),e=!1}else l=Li(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(mt(t),t):(mt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Te(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=ha(t),a!==null&&a.dehydrated!==null){if(e===null){if(!n)throw Error(r(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(r(317));n[Le]=t}else Gl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Te(t),n=!1}else n=Li(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(mt(t),t):(mt(t),null)}return mt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Nu(t,t.updateQueue),Te(t),null);case 4:return Re(),e===null&&ls(t.stateNode.containerInfo),Te(t),null;case 10:return Zt(t.type),Te(t),null;case 19:if(M(Ce),a=t.memoizedState,a===null)return Te(t),null;if(n=(t.flags&128)!==0,u=a.rendering,u===null)if(n)vn(a,!1);else{if(Ne!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=mu(e),u!==null){for(t.flags|=128,vn(a,!1),e=u.updateQueue,t.updateQueue=e,Nu(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Hf(l,e),l=l.sibling;return H(Ce,Ce.current&1|2),se&&kt(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&st()>Uu&&(t.flags|=128,n=!0,vn(a,!1),t.lanes=4194304)}else{if(!n)if(e=mu(u),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,Nu(t,e),vn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!u.alternate&&!se)return Te(t),null}else 2*st()-a.renderingStartTime>Uu&&l!==536870912&&(t.flags|=128,n=!0,vn(a,!1),t.lanes=4194304);a.isBackwards?(u.sibling=t.child,t.child=u):(e=a.last,e!==null?e.sibling=u:t.child=u,a.last=u)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=st(),e.sibling=null,l=Ce.current,H(Ce,n?l&1|2:l&1),se&&kt(t,a.treeForkCount),e):(Te(t),null);case 22:case 23:return mt(t),ac(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(Te(t),t.subtreeFlags&6&&(t.flags|=8192)):Te(t),l=t.updateQueue,l!==null&&Nu(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&M(Xl),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),Zt(He),Te(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Am(e,t){switch(Xi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Zt(He),Re(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Bn(t),null;case 31:if(t.memoizedState!==null){if(mt(t),t.alternate===null)throw Error(r(340));Gl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(mt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));Gl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return M(Ce),null;case 4:return Re(),null;case 10:return Zt(t.type),null;case 22:case 23:return mt(t),ac(),e!==null&&M(Xl),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Zt(He),null;case 25:return null;default:return null}}function fo(e,t){switch(Xi(t),t.tag){case 3:Zt(He),Re();break;case 26:case 27:case 5:Bn(t);break;case 4:Re();break;case 31:t.memoizedState!==null&&mt(t);break;case 13:mt(t);break;case 19:M(Ce);break;case 10:Zt(t.type);break;case 22:case 23:mt(t),ac(),e!==null&&M(Xl);break;case 24:Zt(He)}}function pn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&e)===e){a=void 0;var u=l.create,c=l.inst;a=u(),c.destroy=a}l=l.next}while(l!==n)}}catch(f){ye(t,t.return,f)}}function pl(e,t,l){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&e)===e){var c=a.inst,f=c.destroy;if(f!==void 0){c.destroy=void 0,n=t;var o=l,g=f;try{g()}catch(T){ye(n,o,T)}}}a=a.next}while(a!==u)}}catch(T){ye(t,t.return,T)}}function ro(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{er(t,l)}catch(a){ye(e,e.return,a)}}}function oo(e,t,l){l.props=Kl(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){ye(e,t,a)}}function gn(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(n){ye(e,t,n)}}function Ht(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){ye(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){ye(e,t,n)}else l.current=null}function ho(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(n){ye(e,e.return,n)}}function qc(e,t,l){try{var a=e.stateNode;Wm(a,e.type,l,t),a[et]=t}catch(n){ye(e,e.return,n)}}function mo(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Tl(e.type)||e.tag===4}function Hc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||mo(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Tl(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Yc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=wt));else if(a!==4&&(a===27&&Tl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Yc(e,t,l),e=e.sibling;e!==null;)Yc(e,t,l),e=e.sibling}function Au(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&Tl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Au(e,t,l),e=e.sibling;e!==null;)Au(e,t,l),e=e.sibling}function yo(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);Je(t,a,l),t[Le]=e,t[et]=l}catch(u){ye(e,e.return,u)}}var Wt=!1,Ge=!1,Bc=!1,vo=typeof WeakSet=="function"?WeakSet:Set,ke=null;function Mm(e,t){if(e=e.containerInfo,us=$u,e=Nf(e),Di(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var n=a.anchorOffset,u=a.focusNode;a=a.focusOffset;try{l.nodeType,u.nodeType}catch{l=null;break e}var c=0,f=-1,o=-1,g=0,T=0,A=e,b=null;t:for(;;){for(var j;A!==l||n!==0&&A.nodeType!==3||(f=c+n),A!==u||a!==0&&A.nodeType!==3||(o=c+a),A.nodeType===3&&(c+=A.nodeValue.length),(j=A.firstChild)!==null;)b=A,A=j;for(;;){if(A===e)break t;if(b===l&&++g===n&&(f=c),b===u&&++T===a&&(o=c),(j=A.nextSibling)!==null)break;A=b,b=A.parentNode}A=j}l=f===-1||o===-1?null:{start:f,end:o}}else l=null}l=l||{start:0,end:0}}else l=null;for(is={focusedElem:e,selectionRange:l},$u=!1,ke=t;ke!==null;)if(t=ke,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,ke=e;else for(;ke!==null;){switch(t=ke,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),Je(u,a,l),u[Le]=e,Xe(u),a=u;break e;case"link":var c=xd("link","href",n).get(a+(l.href||""));if(c){for(var f=0;fbe&&(c=be,be=V,V=c);var v=Ef(f,V),h=Ef(f,be);if(v&&h&&(j.rangeCount!==1||j.anchorNode!==v.node||j.anchorOffset!==v.offset||j.focusNode!==h.node||j.focusOffset!==h.offset)){var p=A.createRange();p.setStart(v.node,v.offset),j.removeAllRanges(),V>be?(j.addRange(p),j.extend(h.node,h.offset)):(p.setEnd(h.node,h.offset),j.addRange(p))}}}}for(A=[],j=f;j=j.parentNode;)j.nodeType===1&&A.push({element:j,left:j.scrollLeft,top:j.scrollTop});for(typeof f.focus=="function"&&f.focus(),f=0;fl?32:l,E.T=null,l=Zc,Zc=null;var u=Sl,c=tl;if(Qe=0,Na=Sl=null,tl=0,(de&6)!==0)throw Error(r(331));var f=de;if(de|=4,No(u.current),To(u,u.current,c,l),de=f,Tn(0,!1),ft&&typeof ft.onPostCommitFiberRoot=="function")try{ft.onPostCommitFiberRoot(Qa,u)}catch{}return!0}finally{q.p=n,E.T=a,Zo(e,t)}}function Ko(e,t,l){t=xt(l,t),t=Tc(e.stateNode,t,2),e=ml(e,t,2),e!==null&&(ka(e,2),Yt(e))}function ye(e,t,l){if(e.tag===3)Ko(e,e,l);else for(;t!==null;){if(t.tag===3){Ko(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(jl===null||!jl.has(a))){e=xt(l,e),l=Kr(2),a=ml(t,l,2),a!==null&&(Jr(l,a,t,e),ka(a,2),Yt(a));break}}t=t.return}}function $c(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Um;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(l)||(Qc=!0,n.add(l),e=Ym.bind(null,e,t,l),t.then(e,e))}function Ym(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Se===e&&(ie&l)===l&&(Ne===4||Ne===3&&(ie&62914560)===ie&&300>st()-Du?(de&2)===0&&Aa(e,0):Xc|=l,za===ie&&(za=0)),Yt(e)}function Jo(e,t){t===0&&(t=ws()),e=Yl(e,t),e!==null&&(ka(e,t),Yt(e))}function Bm(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),Jo(e,l)}function Gm(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,n=e.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),Jo(e,l)}function wm(e,t){return si(e,t)}var Bu=null,Oa=null,Wc=!1,Gu=!1,Fc=!1,_l=0;function Yt(e){e!==Oa&&e.next===null&&(Oa===null?Bu=Oa=e:Oa=Oa.next=e),Gu=!0,Wc||(Wc=!0,Xm())}function Tn(e,t){if(!Fc&&Gu){Fc=!0;do for(var l=!1,a=Bu;a!==null;){if(e!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var c=a.suspendedLanes,f=a.pingedLanes;u=(1<<31-rt(42|e)+1)-1,u&=n&~(c&~f),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,Io(a,u))}else u=ie,u=kn(a,a===Se?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||Xa(a,u)||(l=!0,Io(a,u));a=a.next}while(l);Fc=!1}}function Qm(){$o()}function $o(){Gu=Wc=!1;var e=0;_l!==0&&Im()&&(e=_l);for(var t=st(),l=null,a=Bu;a!==null;){var n=a.next,u=Wo(a,t);u===0?(a.next=null,l===null?Bu=n:l.next=n,n===null&&(Oa=l)):(l=a,(e!==0||(u&3)!==0)&&(Gu=!0)),a=n}Qe!==0&&Qe!==5||Tn(e),_l!==0&&(_l=0)}function Wo(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,n=e.expirationTimes,u=e.pendingLanes&-62914561;0f)break;var T=o.transferSize,A=o.initiatorType;T&&id(A)&&(o=o.responseEnd,c+=T*(o"u"?null:document;function gd(e,t,l){var a=Da;if(a&&typeof t=="string"&&t){var n=jt(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),pd.has(n)||(pd.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),Je(t,"link",e),Xe(t),a.head.appendChild(t)))}}function cy(e){ll.D(e),gd("dns-prefetch",e,null)}function sy(e,t){ll.C(e,t),gd("preconnect",e,t)}function fy(e,t,l){ll.L(e,t,l);var a=Da;if(a&&e&&t){var n='link[rel="preload"][as="'+jt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+jt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+jt(l.imageSizes)+'"]')):n+='[href="'+jt(e)+'"]';var u=n;switch(t){case"style":u=Ua(e);break;case"script":u=Ra(e)}At.has(u)||(e=C({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),At.set(u,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(An(u))||t==="script"&&a.querySelector(Mn(u))||(t=a.createElement("link"),Je(t,"link",e),Xe(t),a.head.appendChild(t)))}}function ry(e,t){ll.m(e,t);var l=Da;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+jt(a)+'"][href="'+jt(e)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ra(e)}if(!At.has(u)&&(e=C({rel:"modulepreload",href:e},t),At.set(u,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(Mn(u)))return}a=l.createElement("link"),Je(a,"link",e),Xe(a),l.head.appendChild(a)}}}function oy(e,t,l){ll.S(e,t,l);var a=Da;if(a&&e){var n=ea(a).hoistableStyles,u=Ua(e);t=t||"default";var c=n.get(u);if(!c){var f={loading:0,preload:null};if(c=a.querySelector(An(u)))f.loading=5;else{e=C({rel:"stylesheet",href:e,"data-precedence":t},l),(l=At.get(u))&&hs(e,l);var o=c=a.createElement("link");Xe(o),Je(o,"link",e),o._p=new Promise(function(g,T){o.onload=g,o.onerror=T}),o.addEventListener("load",function(){f.loading|=1}),o.addEventListener("error",function(){f.loading|=2}),f.loading|=4,Lu(c,t,a)}c={type:"stylesheet",instance:c,count:1,state:f},n.set(u,c)}}}function dy(e,t){ll.X(e,t);var l=Da;if(l&&e){var a=ea(l).hoistableScripts,n=Ra(e),u=a.get(n);u||(u=l.querySelector(Mn(n)),u||(e=C({src:e,async:!0},t),(t=At.get(n))&&ms(e,t),u=l.createElement("script"),Xe(u),Je(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function hy(e,t){ll.M(e,t);var l=Da;if(l&&e){var a=ea(l).hoistableScripts,n=Ra(e),u=a.get(n);u||(u=l.querySelector(Mn(n)),u||(e=C({src:e,async:!0,type:"module"},t),(t=At.get(n))&&ms(e,t),u=l.createElement("script"),Xe(u),Je(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function bd(e,t,l,a){var n=(n=ae.current)?ku(n):null;if(!n)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=Ua(l.href),l=ea(n).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=Ua(l.href);var u=ea(n).hoistableStyles,c=u.get(e);if(c||(n=n.ownerDocument||n,c={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,c),(u=n.querySelector(An(e)))&&!u._p&&(c.instance=u,c.state.loading=5),At.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},At.set(e,l),u||my(n,e,l,c.state))),t&&a===null)throw Error(r(528,""));return c}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Ra(l),l=ea(n).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function Ua(e){return'href="'+jt(e)+'"'}function An(e){return'link[rel="stylesheet"]['+e+"]"}function jd(e){return C({},e,{"data-precedence":e.precedence,precedence:null})}function my(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),Je(t,"link",l),Xe(t),e.head.appendChild(t))}function Ra(e){return'[src="'+jt(e)+'"]'}function Mn(e){return"script[async]"+e}function Sd(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+jt(l.href)+'"]');if(a)return t.instance=a,Xe(a),a;var n=C({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),Xe(a),Je(a,"style",n),Lu(a,l.precedence,e),t.instance=a;case"stylesheet":n=Ua(l.href);var u=e.querySelector(An(n));if(u)return t.state.loading|=4,t.instance=u,Xe(u),u;a=jd(l),(n=At.get(n))&&hs(a,n),u=(e.ownerDocument||e).createElement("link"),Xe(u);var c=u;return c._p=new Promise(function(f,o){c.onload=f,c.onerror=o}),Je(u,"link",a),t.state.loading|=4,Lu(u,l.precedence,e),t.instance=u;case"script":return u=Ra(l.src),(n=e.querySelector(Mn(u)))?(t.instance=n,Xe(n),n):(a=l,(n=At.get(u))&&(a=C({},l),ms(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),Xe(n),Je(n,"link",a),e.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,Lu(a,l.precedence,e));return t.instance}function Lu(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,c=0;c title"):null)}function yy(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Td(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function vy(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=Ua(a.href),u=t.querySelector(An(n));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=Vu.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=u,Xe(u);return}u=t.ownerDocument||t,a=jd(a),(n=At.get(n))&&hs(a,n),u=u.createElement("link"),Xe(u);var c=u;c._p=new Promise(function(f,o){c.onload=f,c.onerror=o}),Je(u,"link",a),l.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=Vu.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var ys=0;function py(e,t){return e.stylesheets&&e.count===0&&Ju(e,e.stylesheets),0ys?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Vu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Ju(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Ku=null;function Ju(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Ku=new Map,t.forEach(gy,e),Ku=null,Vu.call(e))}function gy(e,t){if(!(t.state.loading&4)){var l=Ku.get(e);if(l)var a=l.get(null);else{l=new Map,Ku.set(e,l);for(var n=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(d){console.error(d)}}return s(),Ts.exports=Cy(),Ts.exports}var Hy=qy();class Ds extends Error{constructor(d,m,r){super(m),this.code=d,this.status=r,this.name="APIError"}code;status}async function We(s,d){const m=await fetch(s,{...d,headers:d?.body?{"Content-Type":"application/json",...d.headers}:d?.headers});if(!m.ok){let r;try{r=await m.json()}catch{}throw new Ds(r?.error?.code??"request_failed",r?.error?.message??`Request failed with status ${m.status}`,m.status)}if(m.status!==204)return await m.json()}const Me={definitions:()=>We("/api/definitions"),createDefinition:s=>We("/api/definitions",{method:"POST",body:JSON.stringify({source:s})}),startTask:(s,d,m,r,{delivery:S="local",context:O,ref:x,continues:D}={})=>We("/api/runs",{method:"POST",body:JSON.stringify({definition_id:s,instructions:m,parameters:{task_title:m,task_mode:r,task_delivery:S,...D?{task_continues:D}:{}},...O?.length?{context:O}:{},targets:[{repository:d,...x?{ref:x}:{}}]})}),queue:()=>We("/api/queue"),runs:()=>We("/api/runs").then(s=>s??[]),run:s=>We(`/api/runs/${encodeURIComponent(s)}`),job:s=>We(`/api/jobs/${encodeURIComponent(s)}`),attempt:s=>We(`/api/attempts/${encodeURIComponent(s)}`),attemptEvents:(s,d,m=200)=>We(`/api/attempts/${encodeURIComponent(s)}/events?after=${d}&limit=${m}`),attemptGates:s=>We(`/api/attempts/${encodeURIComponent(s)}/gates`).then(d=>d??[]),attemptEnvelopes:s=>We(`/api/attempts/${encodeURIComponent(s)}/envelopes`).then(d=>d??[]),fleet:()=>We("/api/workers"),worktrees:()=>We("/api/worktrees").then(s=>s??[]),releaseWorktree:s=>We(`/api/worktrees/${encodeURIComponent(s)}/release`,{method:"POST",body:JSON.stringify({confirm:!0})}),retryJob:s=>We(`/api/jobs/${encodeURIComponent(s)}/retry`,{method:"POST"}),cancelJob:s=>We(`/api/jobs/${encodeURIComponent(s)}/cancel`,{method:"POST"})};async function Yy(s){const d=(await Me.definitions()).find(m=>m.source===s);if(d)return d;try{return await Me.createDefinition(s)}catch(m){if(!(m instanceof Ds)||m.code!=="definition_exists")throw m;const r=(await Me.definitions()).find(S=>S.source===s);if(!r)throw m;return r}}function Yn(s){if(!s)return null;try{const d=JSON.parse(s);return typeof d!="object"||d===null||Array.isArray(d)||d.phases!=null&&(!Array.isArray(d.phases)||d.phases.some(r=>!r||typeof r!="object"||typeof r.phase!="string"||typeof r.status!="string"))||[d.acceptance?.checks,...(d.phases??[]).map(r=>r.gates?.checks)].some(r=>r!=null&&(!Array.isArray(r)||r.some(S=>!S||typeof S!="object"||typeof S.item!="string"||typeof S.ok!="boolean")))?null:d}catch{return null}}function Ha(s){return s.parameters?.task_title??s.parameters?.prompt?.replace(/^Trusted instructions:\s*/,"").split(` - -Untrusted context:`)[0].trim()??"Previous task"}function Hn(s){return s.replace(/\/$/,"").split("/").pop()||s}function Fd(s){return s.parameters?.task_delivery==="publish"?"publish":"local"}function li(s){return s.state==="mixed"&&s.targets.length===1&&Fd(s)==="local"&&s.snapshot.includes('hold_when: "jig_ui_delivery != publish"')?s.parameters?.task_mode==="ask"?"complete":"ready":s.state}function Ol(s){if(!s)return null;const d=Date.parse(s);return Number.isNaN(d)?null:d}function Wl(s){if(!Number.isFinite(s)||s<0)return"—";if(s<1e3)return`${Math.round(s)}ms`;const d=s/1e3;if(d<60)return`${d.toFixed(d<10?1:0)}s`;const m=Math.floor(d/60),r=Math.round(d-m*60);if(m<60)return`${m}m ${r}s`;const S=Math.floor(m/60);return`${S}h ${m-S*60}m`}function Ya(s){const d=Ol(s);return d===null?"—":new Date(d).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit"})}function As(s){return s.length>12?`${s.slice(0,8)}…`:s}function ai(s){const d=Ol(s);return d===null?"—":new Date(d).toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"numeric",minute:"2-digit"})}const By=new Set(["accepted","accepted_unpublished","failed","cancelled","lost"]);function al(s){return By.has(s)}function Gy(s){return{accepted:"Accepted",accepted_unpublished:"Accepted · not published",mixed:"Mixed results",live:"Online",stale:"Offline",active:"In progress",ready:"Ready to review",complete:"Complete"}[s]??s.replace(/_/g," ")}function Us(){const[s,d]=Z.useState(()=>typeof document>"u"||document.visibilityState!=="hidden");return Z.useEffect(()=>{const m=()=>d(document.visibilityState!=="hidden");return document.addEventListener("visibilitychange",m),()=>document.removeEventListener("visibilitychange",m)},[]),s}function Id(s=1e3){const[d,m]=Z.useState(()=>Date.now()),r=Us();return Z.useEffect(()=>{if(!r||s<=0)return;const S=setInterval(()=>m(Date.now()),s);return()=>clearInterval(S)},[s,r]),d}function Mt(s,d,m){const[r,S]=Z.useState(null),[O,x]=Z.useState(null),[D,N]=Z.useState(!0),[_,Y]=Z.useState(0),C=Us(),$=Z.useRef(s);$.current=s,Z.useEffect(()=>{S(null),N(!0),x(null)},[m]),Z.useEffect(()=>{let R=!1;const X=async()=>{try{const K=await $.current();if(R)return;S(K),x(null)}catch(K){R||x(K)}finally{R||N(!1)}};if(X(),!C||d<=0)return()=>{R=!0};const Q=setInterval(X,d);return()=>{R=!0,clearInterval(Q)}},[m,d,C,_]);const U=Z.useCallback(()=>Y(R=>R+1),[]);return{data:r,error:O,loading:D,refresh:U}}function wy(s,d,m=1e3){const[r,S]=Z.useState([]),[O,x]=Z.useState(null),D=Z.useRef(0),N=Z.useRef(0),[_,Y]=Z.useState(0),C=Us(),$=al(d);return Z.useEffect(()=>{D.current=0,N.current=0,Y(0),S([]),x(null)},[s]),Z.useEffect(()=>{let U=!1,R=null;const X=async()=>{try{const Q=await Me.attemptEvents(s,D.current);if(U)return;const K=Q.events??[];if(x(null),K.length===0){N.current+=1,$&&N.current>=2&&R&&(clearInterval(R),R=null);return}N.current=0;const ee=Math.max(D.current,Q.next_cursor);D.current=ee,Y(ee),S(fe=>Qy(fe,K))}catch(Q){U||x(Q)}};return X(),C&&m>0&&(R=setInterval(()=>{X()},m)),()=>{U=!0,R&&clearInterval(R)}},[s,$,m,C]),{events:r,cursor:_,error:O}}function Qy(s,d){if(d.length===0)return s;const m=new Map;for(const r of s)m.set(r.seq,r);for(const r of d)m.has(r.seq)||m.set(r.seq,r);return[...m.values()].sort((r,S)=>r.seq-S.seq)}function Xy(s){const d=s.split("/").filter(Boolean);return d.length===0?{name:"tasks"}:d[0]==="queue"&&d.length===1?{name:"queue"}:d[0]==="runs"&&d.length===1?{name:"runs"}:d[0]==="runs"&&d.length===2?{name:"run",id:decodeURIComponent(d[1])}:d[0]==="jobs"&&d.length===2?{name:"job",id:decodeURIComponent(d[1])}:d[0]==="worktrees"&&d.length===1?{name:"worktrees"}:d[0]==="fleet"&&d.length===1?{name:"fleet"}:{name:"unknown",path:s}}function Pd(s){window.history.pushState({},"",s),window.dispatchEvent(new PopStateEvent("popstate"))}function ky(){const[s,d]=Z.useState(()=>window.location.pathname);return Z.useEffect(()=>{const m=()=>d(window.location.pathname);return window.addEventListener("popstate",m),()=>window.removeEventListener("popstate",m)},[]),Xy(s)}function Bt({state:s}){return i.jsxs("span",{className:`badge badge-${s}`,children:[i.jsx("span",{className:"dot"}),Gy(s)]})}function Ae({href:s,children:d,current:m=!1}){return i.jsx("a",{href:s,"aria-current":m?"page":void 0,onClick:r=>{r.metaKey||r.ctrlKey||r.shiftKey||(r.preventDefault(),Pd(s))},children:d})}function Oe({error:s}){if(!s)return null;const d=s instanceof Ds?s.code:"request_failed";return i.jsxs("div",{className:"error-banner",role:"alert",children:[i.jsx("strong",{children:d})," ",s.message]})}function Ba({title:s,detail:d}){return i.jsxs("div",{className:"empty",children:[i.jsx("h2",{children:s}),i.jsx("p",{children:d})]})}function Ga({label:s}){return i.jsx("div",{className:"loading",role:"status",children:s})}function Ly(s,d){const m=Ol(d),r=Ol(s.last_heartbeat);return m===null||r===null?"—":`${Wl(Math.max(m-r,0))} ago`}function Zy(s){const d=s.runtimes??[];return d.length===0?"—":d.map(m=>`${m.name} ${m.version}`).join(", ")}function Vy(){const s=Z.useCallback(()=>Me.fleet(),[]),{data:d,error:m,loading:r}=Mt(s,3e3,"fleet");if(r&&!d)return i.jsx(Ga,{label:"Loading fleet…"});if(!d)return i.jsx(Oe,{error:m});const S=d.workers??[],O=S.filter(x=>!x.live).reduce((x,D)=>x+D.active_count,0);return i.jsxs("div",{className:"view",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:"Workers"}),i.jsx("p",{className:"subtle",children:"Online workers execute queued jobs. Offline workers are saved records of previous sessions."}),i.jsxs("p",{className:"subtle",children:["Observed ",Ya(d.observed_at)]})]}),i.jsxs("div",{className:"counters",children:[i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.live_count}),i.jsx("span",{className:"counter-label",children:"online"})]}),i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.stale_count}),i.jsx("span",{className:"counter-label",children:"offline"})]}),i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.available_slots}),i.jsx("span",{className:"counter-label",children:"free slots"})]})]})]}),i.jsx(Oe,{error:m}),S.length===0?i.jsx(Ba,{title:"No workers registered",detail:"Nothing can claim queued work until a worker registers. Start one with `jig worker`."}):i.jsxs(i.Fragment,{children:[i.jsxs("table",{className:"table",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"Worker"}),i.jsx("th",{children:"State"}),i.jsx("th",{children:"Runtime"}),i.jsx("th",{children:"Slots"}),i.jsx("th",{children:"Env"}),i.jsx("th",{children:"Last heartbeat"})]})}),i.jsx("tbody",{children:S.map(x=>i.jsxs("tr",{children:[i.jsxs("td",{children:[x.name,i.jsxs("p",{className:"subtle",children:[i.jsx("code",{children:x.id})," · ",x.worker_version]})]}),i.jsx("td",{children:i.jsx(Bt,{state:x.live?"live":"stale"})}),i.jsx("td",{children:Zy(x)}),i.jsxs("td",{children:[x.active_count," / ",x.capacity]}),i.jsxs("td",{title:(x.env_names??[]).join(" "),children:[(x.env_names??[]).length," names"]}),i.jsx("td",{children:Ly(x,d.observed_at)})]},x.id))})]}),O>0&&i.jsxs("p",{className:"subtle",children:[O," attempt",O===1?" is":"s are"," leased to a worker that stopped heartbeating. The sweeper marks them lost after three missed beats of server uptime, and their jobs are then retryable."]})]})]})}const Ky=[{id:"waiting",label:"Waiting"},{id:"running",label:"Running"},{id:"review",label:"Needs review"},{id:"done",label:"Done"},{id:"stopped",label:"Stopped"}];function Jy(s,d){if(s.state==="active")return d?.length&&d.every(m=>m==="queued")?"waiting":"running";switch(li(s)){case"accepted":case"complete":return"done";case"failed":case"cancelled":return"stopped";default:return"review"}}function $y(s,d){const m=new Map;for(const O of d??[]){const x=m.get(O.run_id);x?x.push(O.state):m.set(O.run_id,[O.state])}const r=Ky.map(O=>({...O,runs:[]})),S=new Map(r.map(O=>[O.id,O]));for(const O of s)S.get(Jy(O,m.get(O.id))).runs.push(O);return r}const Jd=12e3;function $d(s){return s.length<=Jd?s:`${s.slice(0,Jd)} -[truncated]`}function Wy(s){if(!s||typeof s!="object")return"";const{summary:d,notes_for_next_agent:m}=s;return[typeof d=="string"?d:"",typeof m=="string"?m:""].filter(Boolean).join(` - -`)}function Fy(s,d){const m=(d.attempts??[]).at(-1),r=Yn(m?.result),O=[...(r?.phases??[]).map(D=>({phase:D.phase,text:Wy(D.envelope)})).filter(D=>D.text).map(D=>`## ${D.phase} -${D.text}`),r?.changed_paths?.length?`## Changed files -${r.changed_paths.join(` -`)}`:""].filter(Boolean).join(` - -`),x=(d.publish??[]).find(D=>D.step==="push"&&D.branch);return{runID:s.id,repository:d.job.repository,title:Ha(s),context:[{label:"Previous task",body:$d(Ha(s))},...O?[{label:"Previous result",body:$d(O)}]:[]],ref:x?.branch,keptLocal:Fd(s)==="local"&&!x}}async function Iy(s){const d=await Me.run(s),m=d.jobs[0];if(!m)throw new Error("The earlier task has no job to continue from.");return Fy(d.run,await Me.job(m.id))}const Py=`# smoke.yaml — the install check (U11): one genuinely read-only agent phase -# that validates and passes on any repository. -# -# jig run --def examples/definitions/smoke.yaml . "what is this repo?" -# -# Read-only is enforced, not requested: the scout's write allowlist is -# empty, so any repository write rolls back and aborts the attempt (R10). -# The report travels in the envelope alone — no file artifacts, so no file -# gates; the verdict_consistent gate checks the envelope against ITSELF -# (an approval shipping blocking items, or a rejection naming no problem, -# is refuted without reading the repo), which makes it repo-independent. -name: smoke -roster: - scout: - model: haiku - system_prompt: | - You are a read-only scout examining a git repository. You never - create, modify, or delete any file in the repository — you only read, - and you report exclusively through your final JSON envelope. - user_prompt: | - Task: {{prompt}} - - Explore this repository (its layout, languages, build files, and - purpose) and answer the task in your report's "summary" field, in a - few sentences. - - Your final JSON must also include: - - "approved": true if you were able to read the repository and - complete the task, false otherwise - - "blocking": a list of strings naming anything that prevented you - (an empty list when nothing did) - env: [PATH] - writes: [] -phases: - - name: scout - kind: agent - owner: scout - gates: - - {name: verdict_consistent} -acceptance: [all_phases_passed, verdict_consistent] -`,ev=`# plan-build-test.yaml — the code-phase repair edge (U9, KTD2). Plan the -# change, build it, then run the repository's own test command; a failing -# test suite routes its adapter envelope back to the planner, runs the -# builder with the revised plan, and re-runs the suite, budget bounded. -# -# jig run --def examples/definitions/plan-build-test.yaml "add a --version flag" -# -# The repair edge is the whole point. A code phase's failure is nonzero exit -# (R8), and the adapter envelope that carries the exit status and output tail -# enters the repair loop through exactly the same door an agent's failing -# report would — so "the tests broke" is a workflow state, not an incident. -# \`budget: 3\` bounds it and \`exhausted: fail-job\` means a suite that is still -# red after three repair rounds fails the job rather than shipping. -# -# TWO THINGS TO EDIT before using this on your own repository: -# -# 1. The test phase's command. It detects the common entry points, and -# fails loudly when it finds none — an undetected test command must -# never look like a green run. Replace it with your repository's real -# command. -# 2. The builder's \`writes\` allowlist. \`**\` permits every path in the -# worktree, which is the honest default for an open-ended build but the -# weakest write boundary jig can enforce (R10). Narrow it to the -# directories the work belongs in. -# -# THE ROSTER. The builder writes the code, so it runs on \`opus\`; the planner -# only reads and plans, on \`sonnet\`. \`effort: medium\` sets how much the -# builder thinks and verifies while building to a plan — the test phase is -# its check. Leave \`effort\` out to take the CLI's default for the model. -name: plan-build-test -roster: - planner: - model: sonnet - system_prompt: | - You are a read-only planner working in a git repository. You never - create, modify, or delete any file; you produce a plan the builder - will execute, and you report exclusively through your final JSON - envelope. - user_prompt: | - Task: {{prompt}} - - Read enough of this repository to plan the change: which files to - touch, in what order, and how the result will be verified by the - repository's own test command. - - If the previous report contains failed tests, diagnose that failure - and revise the plan before the builder runs again. Pass the failure - evidence and a concrete repair directive in notes_for_next_agent. - Preserve the user's scope. Never weaken tests to make them pass. - - Your final JSON must also include: - - "notes_for_next_agent": the plan itself, concrete enough to - execute without re-deriving it - env: [PATH] - writes: [] - builder: - model: opus - effort: medium - system_prompt: | - You are a builder working in a git repository. You execute the plan - you are handed, you write only what the task requires, and you report - honestly: claim only files you actually created or modified. - - When you are handed a failing test result, fix the cause the failure - names. Do not weaken, skip, or delete a test to make it pass. - user_prompt: | - Task: {{prompt}} - - The plan and any previous phase's report are above. Make the change, - then stop — the test suite runs as its own phase. - On repairs, report all paths changed relative to the original commit, - including changes already present from the previous build. - - Your final JSON must also include: - - "changed_files": the repo-relative paths of every file you - created or modified - - "artifacts": the same paths, for existence verification - env: [PATH] - writes: ["**"] -phases: - - name: plan - kind: agent - owner: planner - - name: build - kind: agent - owner: builder - gates: - - {name: artifacts_exist} - - {name: diff_matches_claims} - - name: test - kind: code - owner: builder - command: > - if [ -f Justfile ] || [ -f justfile ]; then just test; - elif [ -f Makefile ]; then make test; - elif [ -f go.mod ]; then go test ./...; - elif [ -f package.json ]; then npm test --silent; - else echo "plan-build-test: no test command detected — edit the test phase"; exit 1; fi - on_fail: {run: plan, then: rerun-chain, budget: 3, exhausted: fail-job} -acceptance: [all_phases_passed, artifacts_exist, diff_matches_claims] -`,eh="Inspect this project, choose one useful improvement supported by the code, write a concrete directive and implementation plan, build it, and verify it with the existing tests. Keep the change focused. Do not add paid services or change deployment, authentication, secrets, or security policy. Do not weaken tests. Report the chosen improvement, changes, and verification.",tv="gpt-6.1-sol",lv={ask:["scout"],build:["plan","build","test"],auto:["plan","build","test"]};function av(s){return/^(https:\/\/)?github\.com\/[^/\s]+\/[^/\s]+/.test(s.trim())}async function nv(s,d,m="",r="local"){let S=(s==="ask"?Py:ev).replace(/^(\s*)model: .+$/gm,(D,N)=>`${N}model: ${JSON.stringify(d.trim())}`);s==="auto"&&(S=S.replace(" Task: {{prompt}}",` Goal or limits: {{prompt}} - - Inspect the project and choose one focused, useful improvement that - fits this goal. You own the directive: do not ask the user to write it. - Put the chosen directive in summary, and the concrete implementation - plan and failure evidence in notes_for_next_agent. The builder will - execute your plan automatically. Avoid paid services and changes to - deployment, authentication, secrets, or security policy.`)),s!=="ask"&&m.trim()&&(S=S.replace(/ command: >\n(?: .*\n)+/,()=>` command: ${JSON.stringify(m.trim())} -`));const O=s==="ask"?"local":r,x=O==="publish"?"deliver":"keep-local";return S=S.replace(/^acceptance:/m,` - name: ${x} - kind: code - reports_fields: true - command: "printf '%s\\n' '{\\"jig_ui_delivery\\":\\"${O}\\"}'" -acceptance:`),S+=` -publish: - hold_when: "jig_ui_delivery != publish" -`,S=S.replace(/^name: .+$/m,D=>`${D} -runtime: codex`),S.replace(/^name: .+$/m,`name: jig-task-${s}-${await uv(S)}`)}async function uv(s){return Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(s)))).map(d=>d.toString(16).padStart(2,"0")).join("").slice(0,16)}function iv(){try{return localStorage.getItem("jig-project")}catch{return null}}function cv(){const s=Z.useCallback(()=>Me.runs(),[]),d=Mt(s,3e3,"tasks"),m=Z.useCallback(()=>Me.fleet(),[]),r=Mt(m,3e3,"task-workers"),[S,O]=Z.useState(()=>new URLSearchParams(window.location.search).get("project")??iv()??""),[x,D]=Z.useState(""),[N,_]=Z.useState(()=>{const W=new URLSearchParams(window.location.search).get("mode");return W==="ask"||W==="build"?W:"auto"}),[Y,C]=Z.useState(tv),[$,U]=Z.useState(""),[R,X]=Z.useState("local"),[Q]=Z.useState(()=>new URLSearchParams(window.location.search).get("continue")),[K,ee]=Z.useState(null),[fe,k]=Z.useState(!1),[Fe,we]=Z.useState(null),te=N!=="ask"&&av(S),xe=te&&R==="publish";Z.useEffect(()=>{if(!Q)return;let W=!0;return Iy(Q).then(Ue=>{W&&(ee(Ue),O(Ue.repository))},Ue=>{W&&we(Ue)}),()=>{W=!1}},[Q]);const De=(r.data?.workers??[]).some(W=>W.live&&W.runtimes?.some(Ue=>Ue.name==="codex")),nl=[...new Set((d.data??[]).flatMap(W=>W.targets.map(Ue=>Ue.repository)))],gt=async W=>{if(W.preventDefault(),!(fe||!S.trim()||N!=="auto"&&!x.trim()||!Y.trim()||!De||r.error||Q&&!K)){k(!0),we(null);try{const Ue=xe?"publish":"local",Ot=await Yy(await nv(N,Y,$,Ue)),ct=await Me.startTask(Ot.id,S.trim(),x.trim()||eh,N,{delivery:Ue,context:K?.context,ref:K?.ref,continues:K?.runID});try{localStorage.setItem("jig-project",S.trim())}catch{}Pd(`/runs/${ct.run.id}`)}catch(Ue){we(Ue)}finally{k(!1)}}};return i.jsxs("div",{className:"view workspace",children:[i.jsxs("header",{className:"view-header workspace-hero",children:[i.jsxs("div",{children:[i.jsx("span",{className:"eyebrow",children:"IDEA IN. WORKING SOFTWARE OUT."}),i.jsxs("h1",{children:["Make your ",i.jsx("span",{children:"next move."})]}),i.jsx("p",{className:"subtle",children:"Give agents a project. They find the work, build it, and prove it."})]}),i.jsxs("div",{className:"runtime-status",children:[i.jsx(Bt,{state:De&&!r.error?"live":"stale"}),i.jsx("span",{children:"Codex connection"})]})]}),i.jsxs("div",{className:"workspace-grid",children:[i.jsxs("form",{className:"panel task-form",onSubmit:W=>{gt(W)},children:[i.jsxs("div",{className:"composer-heading",children:[i.jsx("span",{className:"eyebrow",children:"THE WORKBENCH"}),i.jsx("h2",{children:"Let’s build something."}),i.jsx("span",{className:"composer-mark","aria-hidden":"true",children:"↗"})]}),i.jsxs("fieldset",{disabled:fe,children:[i.jsx("label",{htmlFor:"project",children:"1. Project"}),i.jsx("input",{id:"project",list:"projects",placeholder:"Paste a local folder path or GitHub repository",required:!0,value:S,onChange:W=>O(W.target.value)}),i.jsx("datalist",{id:"projects",children:nl.map(W=>i.jsx("option",{value:W,children:Hn(W)},W))}),i.jsx("p",{className:"subtle",children:"Use a Git project. Work starts from its latest commit; uncommitted edits are not included."}),i.jsxs("fieldset",{className:"mode-choice",children:[i.jsx("legend",{children:"2. What result do you want?"}),i.jsxs("label",{className:N==="auto"?"selected":"",children:[i.jsx("input",{type:"radio",name:"mode",value:"auto",checked:N==="auto",onChange:()=>_("auto")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Let agents improve it"}),i.jsx("small",{children:"Agents choose the directive, plan, build, and test. No task-writing required."})]})]}),i.jsxs("label",{className:N==="ask"?"selected":"",children:[i.jsx("input",{type:"radio",name:"mode",value:"ask",checked:N==="ask",onChange:()=>_("ask")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Get an answer"}),i.jsx("small",{children:"Research and recommendations. No files changed."})]})]}),i.jsxs("label",{className:N==="build"?"selected":"",children:[i.jsx("input",{type:"radio",name:"mode",value:"build",checked:N==="build",onChange:()=>_("build")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Make changes"}),i.jsx("small",{children:"Edit files, run tests, and prepare work for review."})]})]})]}),i.jsx("p",{className:"subtle",children:N==="ask"?"Read-only. Codex reads the project and gives you an answer.":"Plan → build → test. Failed tests restart the loop automatically, up to three repair rounds."}),N!=="ask"&&i.jsxs("fieldset",{className:"mode-choice delivery-choice",children:[i.jsx("legend",{children:"When the checks pass"}),i.jsxs("label",{className:xe?"":"selected",children:[i.jsx("input",{type:"radio",name:"delivery",value:"local",checked:!xe,onChange:()=>X("local")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Keep it local"}),i.jsx("small",{children:"Changes stay in a saved working folder on this Mac. Nothing is pushed to GitHub."})]})]}),i.jsxs("label",{className:xe?"selected":"",children:[i.jsx("input",{type:"radio",name:"delivery",value:"publish",disabled:!te,checked:xe,onChange:()=>X("publish")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Open a pull request"}),i.jsx("small",{children:te?"Jig commits the changes, pushes a branch, and opens a pull request with your GitHub login.":"Needs a GitHub project, such as github.com/owner/repo. A local folder can only keep changes local."})]})]})]}),Q&&i.jsx("div",{className:"notice continuation",role:"status",children:K?i.jsxs(i.Fragment,{children:[i.jsx("strong",{children:"Continuing:"})," ",K.title.split(` -`)[0],i.jsx("p",{className:"subtle",children:K.ref?`Starts from the earlier task's branch ${K.ref}, so its changes are included.`:K.keptLocal?"The earlier changes were kept local and never pushed, so this task starts from the project's latest commit without them. The earlier directive and result are passed along as context.":"This task starts from the project's latest commit. The earlier directive and result are passed along as context."})]}):"Loading the earlier task…"}),i.jsxs("details",{className:"goal-options",open:N!=="auto",children:[i.jsx("summary",{children:N==="auto"?"Add a goal or limits (optional)":"Your directive"}),i.jsx("label",{htmlFor:"task",children:N==="auto"?"3. Goal or limits (optional)":"3. What should Codex do?"}),i.jsx("textarea",{id:"task",required:N!=="auto",rows:5,maxLength:2e4,placeholder:N==="auto"?"Leave blank: agents inspect the project and choose one useful improvement. Or give a goal, such as make installation easier.":N==="ask"?"Explain what this project does and how I can use it.":"Describe the change you want and what a working result looks like.",value:x,onChange:W=>D(W.target.value)})]}),i.jsxs("details",{className:"evidence",children:[i.jsx("summary",{children:"Options"}),i.jsx("label",{htmlFor:"model",children:"Codex model"}),i.jsx("input",{id:"model",required:!0,value:Y,onChange:W=>C(W.target.value)}),N!=="ask"&&i.jsxs(i.Fragment,{children:[i.jsx("label",{htmlFor:"test-command",children:"Test command"}),i.jsx("input",{id:"test-command",placeholder:"Leave blank to detect the project's test command",value:$,onChange:W=>U(W.target.value)})]})]}),i.jsx(Oe,{error:Fe}),i.jsx(Oe,{error:r.error}),i.jsxs("div",{className:"start-row",children:[i.jsx("button",{className:"primary",type:"submit",disabled:fe||!De||!!r.error||!S.trim()||N!=="auto"&&!x.trim()||!Y.trim()||!!(Q&&!K),children:fe?"Starting…":"Start task"}),i.jsx("span",{className:"subtle",children:De?`Uses your signed-in Codex. ${xe?"Passing work becomes a pull request.":"Results stay local."}`:r.loading?"Checking Codex…":"Codex is offline. Check Workers before starting."})]}),i.jsxs("p",{className:"task-intent",children:[i.jsx("strong",{children:N==="ask"?"This task will return an answer.":"This task will change files in a separate working folder."})," ",N==="ask"?"Choose Make changes if you want Codex to implement something.":xe?"Your original project stays untouched; review and merge the pull request on GitHub.":"Your original project stays untouched. Nothing reaches GitHub unless you choose Open a pull request."]})]})]}),i.jsxs("aside",{className:"recent-work","aria-label":"Recent work",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("span",{className:"eyebrow",children:"IN THE FACTORY"}),i.jsx("h2",{children:"Recent tasks"})]}),i.jsx(Ae,{href:"/runs",children:"View all →"})]}),i.jsx(Oe,{error:d.error}),i.jsx("div",{className:"task-cards",children:(d.data??[]).slice(0,6).map(W=>i.jsx(Rs,{run:W},W.id))}),!d.loading&&d.data?.length===0&&i.jsx("p",{className:"subtle",children:"Your first task will appear here when you press Start."}),i.jsxs("div",{className:"loop-guide",children:[i.jsx("span",{className:"eyebrow",children:"THE AGENT LOOP"}),i.jsxs("div",{children:[i.jsx("span",{children:"01"}),i.jsx("strong",{children:"Plan"}),i.jsx("p",{children:"Find a useful change. Write the directive."})]}),i.jsxs("div",{children:[i.jsx("span",{children:"02"}),i.jsx("strong",{children:"Build"}),i.jsx("p",{children:"Turn the plan into working code."})]}),i.jsxs("div",{children:[i.jsx("span",{children:"03"}),i.jsx("strong",{children:"Verify"}),i.jsx("p",{children:"Run tests. Replan and repair if they fail."})]}),i.jsx("p",{className:"subtle",children:"Up to three repair rounds. You choose whether passing work stays local or becomes a pull request."})]})]})]})]})}function Rs({run:s}){const d=Ha(s)===eh?"Agent-led improvement":Ha(s).split(` -`)[0].replace(/^>\s*/,"");return i.jsxs("article",{className:`panel task-card task-card-${li(s)}`,children:[i.jsxs("div",{className:"task-card-meta",children:[i.jsx("span",{className:"task-project",children:s.targets.map(m=>Hn(m.repository)).join(", ")}),i.jsx(Bt,{state:li(s)})]}),i.jsx("h3",{children:i.jsx(Ae,{href:`/runs/${s.id}`,children:d})}),i.jsx("p",{className:"subtle",children:ai(s.created_at)}),i.jsx(Ae,{href:`/runs/${s.id}`,children:"Open task →"})]})}function sv({runs:s}){const d=Z.useCallback(()=>Me.queue(),[]),m=Mt(d,2e3,"board-queue"),r=$y(s,m.data?m.data.entries??[]:null);return i.jsxs(i.Fragment,{children:[i.jsx(Oe,{error:m.error}),i.jsx("div",{className:"board",children:r.map(S=>i.jsxs("section",{className:`board-column board-column-${S.id}`,"aria-labelledby":`board-${S.id}`,children:[i.jsxs("h2",{id:`board-${S.id}`,children:[S.label," ",i.jsx("span",{className:"board-count",children:S.runs.length})]}),S.runs.length===0?i.jsx("p",{className:"subtle board-empty",children:"Nothing here."}):S.runs.map(O=>i.jsx(Rs,{run:O},O.id))]},S.id))})]})}function fv(){const s=Z.useCallback(()=>Me.queue(),[]),{data:d,error:m,loading:r}=Mt(s,2e3,"queue"),S=Z.useCallback(()=>Me.fleet(),[]),O=Mt(S,3e3,"queue-workers");if(r&&!d)return i.jsx(Ga,{label:"Loading queue…"});if(!d)return i.jsx(Oe,{error:m});const x=d.entries??[];return i.jsxs("div",{className:"view",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:"Work queue"}),i.jsx("p",{className:"subtle",children:"Live work appears here. Completed and older runs are in Run history."}),i.jsxs("p",{className:"subtle",children:["Observed ",Ya(d.observed_at)]})]}),i.jsxs("div",{className:"counters",children:[i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.depth}),i.jsx("span",{className:"counter-label",children:"queued"})]}),i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.active_count}),i.jsx("span",{className:"counter-label",children:"running"})]})]})]}),i.jsx(Oe,{error:m}),i.jsxs("section",{className:"panel readiness","aria-label":"Worker readiness",children:[i.jsx("h2",{children:O.data?`${O.data.live_count} worker${O.data.live_count===1?"":"s"} online`:"Checking workers…"}),i.jsx("p",{children:O.data?.live_count?`Ready runtimes: ${(O.data.workers??[]).filter(D=>D.live).flatMap(D=>(D.runtimes??[]).map(N=>N.name)).join(", ")}. Jobs start when a compatible worker has a free slot.`:"Jobs need an online worker before they can start."}),i.jsx(Ae,{href:"/fleet",children:"View workers →"}),i.jsx(Oe,{error:O.error})]}),x.length===0?i.jsxs("section",{className:"panel",children:[i.jsx("h2",{children:"No work is running"}),i.jsx("p",{children:"The queue is empty. Opening an old run does not restart it."}),i.jsx("p",{children:i.jsx(Ae,{href:"/",children:"Start a new task →"})}),i.jsx(Ae,{href:"/runs",children:"Browse previous results →"})]}):i.jsxs("table",{className:"table",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"#"}),i.jsx("th",{children:"Repository"}),i.jsx("th",{children:"Definition"}),i.jsx("th",{children:"State"}),i.jsx("th",{children:"Attempt"}),i.jsx("th",{children:"Enqueued"})]})}),i.jsx("tbody",{children:x.map(D=>i.jsxs("tr",{children:[i.jsx("td",{children:D.position??"—"}),i.jsx("td",{children:i.jsx(Ae,{href:`/jobs/${D.job_id}`,children:D.repository})}),i.jsx("td",{children:D.definition??"—"}),i.jsx("td",{children:i.jsx(Bt,{state:D.state})}),i.jsx("td",{children:D.attempt?i.jsxs(i.Fragment,{children:["#",D.attempt.attempt_number," ",i.jsx(Bt,{state:D.attempt.state})]}):"—"}),i.jsx("td",{children:Ya(D.enqueued_at)})]},D.job_id))})]})]})}function rv(){try{return localStorage.getItem("jig-tasks-layout")==="board"?"board":"list"}catch{return"list"}}function ov(){const s=Z.useCallback(()=>Me.runs(),[]),{data:d,error:m,loading:r}=Mt(s,4e3,"runs"),[S,O]=Z.useState(rv),x=D=>{O(D);try{localStorage.setItem("jig-tasks-layout",D)}catch{}};return r&&!d?i.jsx(Ga,{label:"Loading runs…"}):d?i.jsxs("div",{className:"view",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:"My tasks"}),i.jsx("p",{className:"subtle",children:"Open a task to follow its progress or read the result."})]}),i.jsxs("div",{className:"layout-switch",role:"group","aria-label":"Layout",children:[i.jsx("button",{type:"button","aria-pressed":S==="list",onClick:()=>x("list"),children:"List"}),i.jsx("button",{type:"button","aria-pressed":S==="board",onClick:()=>x("board"),children:"Board"})]})]}),i.jsx(Oe,{error:m}),d.length===0?i.jsx(Ba,{title:"No tasks yet",detail:"Start a task from the New task page."}):S==="board"?i.jsx(sv,{runs:d}):i.jsx("div",{className:"task-cards",children:d.map(D=>i.jsx(Rs,{run:D},D.id))})]}):i.jsx(Oe,{error:m})}function Wd(s,d){return Ol(s.started_at)??d}function qa(s,d){const m=s.payload;if(!m||typeof m!="object")return;const r=m[d];return typeof r=="string"?r:void 0}function dv(s,d){const m=[...d].sort((R,X)=>R.seq-X.seq),r=Ol(s.started_at)??Ol(s.created_at)??0,S=m.length?Wd(m[0],r):r,O=Math.min(r||S,S),x=[],D=[],N=[],_=new Map;let Y=null,C=O;const $=R=>{Y&&Y.endMs===null&&(Y.endMs=Math.max(R,Y.startMs)),Y=null};for(const R of m){const X=Wd(R,C);C=Math.max(C,X);const Q=R.phase??"";switch(Y&&(Y.phase===Q||R.type==="phase_end")&&$(X),R.type){case"phase_start":{const K={key:`phase-${R.seq}`,label:Q,phase:Q,startMs:X,endMs:null,kind:"phase"};x.push(K),_.set(Q,K);break}case"phase_end":case"phase_death":{const K=_.get(Q);K&&(K.endMs=X,K.status=R.type==="phase_death"?"death":qa(R,"status")??"unknown",_.delete(Q)),R.type==="phase_death"&&N.push({key:`mark-${R.seq}`,label:"phase death",phase:Q,atMs:X,kind:"error",detail:qa(R,"cause")??qa(R,"error")});break}case"tool_call":{const K={key:`tool-${R.seq}`,label:R.name??"tool",phase:Q,startMs:X,endMs:null,kind:"tool"};D.push(K),Y=K;break}case"gate_pass":case"gate_fail":N.push({key:`mark-${R.seq}`,label:R.name??"gate",phase:Q,atMs:X,kind:R.type});break;case"handoff":N.push({key:`mark-${R.seq}`,label:"handoff",phase:Q,atMs:X,kind:"handoff",detail:qa(R,"summary")});break;case"error":N.push({key:`mark-${R.seq}`,label:R.name??"error",phase:Q,atMs:X,kind:"error",detail:qa(R,"error")??qa(R,"reason")});break}}const U=Ol(s.completed_at);if(U!==null){const R=Yn(s.result)?.phases?.slice().reverse()??[];$(Math.max(U,C));for(const X of _.values())X.endMs===null&&(X.endMs=Math.max(U,C)),X.status=R.find(Q=>Q.phase===X.phase)?.status??"stopped"}return{attemptId:s.id,attemptNumber:s.attempt_number,state:s.state,startMs:O,endMs:U,phases:x,tools:D,marks:N,eventCount:m.length}}function hv(s,d){if(s.endMs!==null)return Math.max(s.endMs,s.startMs+1);const m=Math.max(s.startMs,...s.phases.map(r=>r.endMs??r.startMs),...s.tools.map(r=>r.endMs??r.startMs),...s.marks.map(r=>r.atMs));return Math.max(d,m,s.startMs+1)}function Cs(s,d){return Math.max(0,(s.endMs??d)-s.startMs)}function th(s,d,m){const r=Math.max(1,m-d);return Math.min(100,Math.max(0,(s.startMs-d)/r*100))}function lh(s,d,m,r){const S=Math.max(1,m-d),O=Cs(s,r)/S*100;return Math.min(100,Math.max(1.5,O))}function Ms(s){const d=Yn(s.result),m=d?.publish,r=m&&typeof m=="object"?m.code:void 0;if(s.state==="queued")return{title:"Waiting for a worker",detail:"This attempt has not started.",next:"Check Workers for an online worker with the workflow's runtime and a free slot."};if(s.state==="preparing")return{title:"Preparing the repository",detail:"The worker is setting up an isolated worktree.",next:"Wait for the first phase to start; the page updates automatically."};if(s.state==="running")return{title:"Work is running",detail:"The worker is executing the workflow and its checks.",next:"Follow the current phase below. Failed checks can trigger the workflow's bounded repair loop."};if(s.state==="accepted")return{title:"Work accepted",detail:"This attempt passed Jig's acceptance checks.",next:"Review the agent's result and any published pull request below."};if(s.state==="accepted_unpublished")return d?.publish_hold?.startsWith('publish.hold_when "jig_ui_delivery != publish" held')&&(m==="held"||typeof m=="object"&&m?.state==="held")?{title:"Task complete · kept local",detail:"The task passed its checks. Any changes remain in the separate working folder on this Mac; nothing was pushed to GitHub.",next:"Read the result below. For a build task, review the saved changes before applying them, or start the task again with Open a pull request."}:r==="publish_empty_changeset"||s.error?.includes("(publish_empty_changeset)")?{title:"Checks passed · nothing to publish",detail:"The workflow passed its acceptance checks, but the worktree had no new commit to publish. Read-only assessments can legitimately produce no changes.",next:"Read the assessment below. If the task required edits, review why the builder produced no changes; retrying publication alone will not fix that."}:m==="held"||typeof m=="object"&&m?.state==="held"?{title:"Checks passed · awaiting review",detail:"The workflow deliberately held publication for human review.",next:"Review the result and retained worktree before releasing the publication hold."}:m==="not_attempted"&&!s.error?{title:"Checks passed · publication not attempted",detail:"The recorded result does not include a completed publication step.",next:"Read the result below; a direct run does not publish a branch or pull request."}:{title:"Checks passed · publication incomplete",detail:"The coding workflow passed, but delivery did not finish. The diagnostic below records where it stopped.",next:"Resolve the publication or CI problem before retrying publication; rerunning the coding workflow is a separate action."};if(s.state==="cancelled")return{title:"Work cancelled",detail:"This attempt stopped without an accepted result.",next:"Inspect the recorded work before submitting a new task."};if(s.state==="lost")return{title:"Worker connection lost",detail:"Jig stopped receiving the worker's heartbeat.",next:"Check Workers and the retained worktree. Retry the failed job once the worker is available."};if(s.error?.includes("outside its write allowlist"))return{title:"Stopped at the write boundary",detail:"The agent modified a path the workflow did not allow. Jig stopped the attempt; the diagnostic records its rollback result.",next:"For a read-only task, remove commands that write caches or files. For an editing task, check the permitted paths before submitting a revised workflow."};const S=d?.phases?.slice().reverse().find(O=>O.status==="fail");return{title:S?`Stopped in ${S.phase}`:"Work did not pass",detail:"The attempt did not meet Jig's acceptance requirements. Inspect the diagnostic and failed checks below.",next:"Fix the cause before retrying. A retry uses the same frozen workflow; prompt, model, or workflow changes require a new run."}}function mv({lane:s,nowMs:d,onSelectPhase:m}){const r=hv(s,d),S=Math.max(1,r-s.startMs),O=s.endMs===null;return i.jsxs("section",{className:"lane","aria-label":`attempt ${s.attemptNumber} swim lane`,children:[i.jsxs("header",{className:"lane-header",children:[i.jsxs("h3",{children:["Attempt ",s.attemptNumber]}),i.jsx(Bt,{state:s.state}),i.jsxs("span",{className:"lane-meta",children:[Wl(S)," · ",s.eventCount," events",O?" · live":""]})]}),s.phases.length===0&&s.tools.length===0?i.jsx("p",{className:"lane-empty",children:"No trace events for this attempt yet."}):i.jsxs(i.Fragment,{children:[i.jsxs("div",{className:"lane-track",role:"list","aria-label":"phases",children:[s.phases.map(x=>i.jsx(yv,{span:x,startMs:s.startMs,endMs:r,nowMs:d,onSelect:m},x.key)),s.marks.map(x=>i.jsx(vv,{mark:x,startMs:s.startMs,endMs:r},x.key))]}),s.tools.length>0&&i.jsxs("details",{className:"evidence",open:O,children:[i.jsxs("summary",{children:["Tool activity · ",s.tools.length," calls"]}),i.jsx("ol",{className:"tool-list","aria-label":`attempt ${s.attemptNumber} tool calls`,children:s.tools.map(x=>i.jsx(pv,{span:x,startMs:s.startMs,endMs:r,nowMs:d},x.key))})]})]})]})}function yv({span:s,startMs:d,endMs:m,nowMs:r,onSelect:S}){const O=Wl(Cs(s,r)),x=s.status??"running";return i.jsxs("button",{type:"button",role:"listitem",className:`phase-block phase-${x}`,style:{left:`${th(s,d,m)}%`,width:`${lh(s,d,m,r)}%`},"aria-label":`phase ${s.label}, ${x}, ${O}`,onClick:()=>S?.(s.phase),children:[i.jsx("span",{className:"phase-name",children:s.label}),i.jsx("span",{className:"phase-duration",children:O})]})}function vv({mark:s,startMs:d,endMs:m}){const r=Math.max(1,m-d),S=Math.min(100,Math.max(0,(s.atMs-d)/r*100));return i.jsx("span",{className:`mark mark-${s.kind}`,style:{left:`${S}%`},title:`${s.label}${s.detail?`: ${s.detail}`:""} (${Ya(new Date(s.atMs).toISOString())})`,"aria-label":`${s.kind.replace("_"," ")} ${s.label}`})}function pv({span:s,startMs:d,endMs:m,nowMs:r}){const S=s.endMs===null,O=Wl(Cs(s,r));return i.jsxs("li",{className:"tool-row",children:[i.jsx("span",{className:"tool-name",children:s.label}),i.jsx("span",{className:"tool-track",children:i.jsx("span",{className:S?"tool-span tool-running":"tool-span",style:{marginLeft:`${th(s,d,m)}%`,width:`${lh(s,d,m,r)}%`}})}),i.jsxs("span",{className:"tool-duration",children:[O,S?" (running)":""]})]})}function gv({runID:s}){const d=Z.useCallback(()=>Me.run(s),[s]),{data:m,error:r,loading:S}=Mt(d,3e3,`run:${s}`),O=Id();if(S&&!m)return i.jsx(Ga,{label:"Loading run…"});if(!m)return i.jsx(Oe,{error:r});const x=Object.entries(m.run.parameters??{});return i.jsxs("div",{className:"view",children:[i.jsxs("p",{children:[i.jsx(Ae,{href:"/",children:"← New task"})," · ",i.jsx(Ae,{href:"/runs",children:"My tasks"})]}),i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:m.run.targets.map(D=>Hn(D.repository)).join(", ")}),i.jsxs("p",{className:"subtle",children:[m.run.targets.map(D=>Hn(D.repository)).join(", ")," · ",ai(m.run.created_at)]})]}),i.jsx(Bt,{state:li(m.run)})]}),i.jsx(Oe,{error:r}),i.jsxs("section",{className:"panel directive",children:[i.jsx("h2",{children:m.run.parameters?.task_mode==="auto"?"Agents choose the directive":m.run.parameters?.task_mode==="build"?"Directive · make changes":"Question · get an answer"}),i.jsxs("details",{open:Ha(m.run).length<=250,children:[i.jsx("summary",{children:"View your instructions"}),i.jsx("p",{children:Ha(m.run)})]}),i.jsx("p",{className:"subtle",children:m.run.parameters?.task_mode==="auto"||m.run.parameters?.task_mode==="build"?"Agents plan, build, and test automatically. Failed tests return to planning for up to three repair rounds. Changes stay in the saved working folder.":"Codex reads this project and returns an answer. This task does not implement the recommendations."})]}),x.length>0&&i.jsxs("details",{className:"evidence",children:[i.jsx("summary",{children:"Task settings"}),i.jsx("dl",{className:"parameters",children:x.map(([D,N])=>i.jsxs("div",{children:[i.jsx("dt",{children:D}),i.jsx("dd",{children:N})]},D))})]}),m.jobs.length>1&&i.jsxs("section",{className:"panel","aria-label":"Run overview",children:[i.jsxs("h2",{children:[m.jobs.length," repositories"]}),i.jsxs("p",{children:[m.jobs.filter(D=>D.state==="active").length," running · ",m.jobs.filter(D=>D.state==="queued").length," waiting · ",m.jobs.filter(D=>D.state==="failed").length," failed · ",m.jobs.filter(D=>D.state==="accepted_unpublished").length," unpublished"]}),i.jsx("p",{className:"subtle",children:"Acceptance checks verify the workflow. Read each agent's assessment to see its conclusion about the repository."}),i.jsx("ul",{className:"repository-list",children:m.jobs.map(D=>i.jsxs("li",{children:[i.jsx("a",{href:`#job-${D.id}`,children:D.repository})," · ",i.jsx(Bt,{state:D.state})]},D.id))})]}),m.jobs.length===0?i.jsx(Ba,{title:"No jobs",detail:"This run admitted no targets."}):m.jobs.map(D=>i.jsx(ah,{jobID:D.id,nowMs:O,compact:!0,taskMode:m.run.parameters?.task_mode==="auto"?"auto":m.run.parameters?.task_mode==="build"?"build":m.run.parameters?.task_mode==="ask"?"ask":void 0},D.id))]})}function bv({jobID:s}){const d=Id();return i.jsx("div",{className:"view",children:i.jsx(ah,{jobID:s,nowMs:d,standalone:!0,compact:!0})})}function ah({jobID:s,nowMs:d,standalone:m=!1,compact:r=!1,taskMode:S}){const O=Z.useCallback(()=>Me.job(s),[s]),{data:x,error:D,loading:N,refresh:_}=Mt(O,3e3,`job:${s}`),[Y,C]=Z.useState(null),[$,U]=Z.useState(!1),R=async ee=>{U(!0);try{ee==="retry"?await Me.retryJob(s):await Me.cancelJob(s),C(null),_()}catch(fe){C(fe)}finally{U(!1)}};if(N&&!x)return i.jsx(Ga,{label:"Loading job…"});if(!x)return i.jsx(Oe,{error:D});const X=x.attempts??[],Q=X.at(-1),K=Q&&Ms(Q).title==="Task complete · kept local";return i.jsxs("section",{className:"panel",id:`job-${s}`,children:[i.jsxs("header",{className:"panel-header",children:[i.jsxs("div",{children:[i.jsx("h2",{children:r?Hn(x.job.repository):x.job.repository}),r&&i.jsx("p",{className:"subtle",children:x.job.repository}),!r&&i.jsxs("p",{className:"subtle",children:[x.definition?`${x.definition} · `:"","base ",x.job.base_sha.slice(0,12)," ·"," ",m?i.jsxs(Ae,{href:`/runs/${x.run_id}`,children:["run ",As(x.run_id)]}):i.jsxs(Ae,{href:`/jobs/${x.job.id}`,children:["job ",As(x.job.id)]})]})]}),i.jsxs("div",{className:"panel-actions",children:[i.jsx(Bt,{state:K?S==="ask"?"complete":"ready":x.job.state}),x.job.state==="failed"&&i.jsx("button",{type:"button",disabled:$,onClick:()=>{R("retry")},children:"Retry same workflow"}),["queued","active"].includes(x.job.state)&&i.jsx("button",{type:"button",disabled:$||x.job.cancellation_requested,onClick:()=>{R("cancel")},children:x.job.cancellation_requested?"Cancellation requested":"Cancel"})]})]}),i.jsx(Oe,{error:Y}),i.jsx(Oe,{error:D}),X.length>1&&i.jsxs("details",{className:"evidence",children:[i.jsxs("summary",{children:["Compare ",X.length," attempts"]}),i.jsxs("table",{className:"table",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"Attempt"}),i.jsx("th",{children:"Runtime"}),i.jsx("th",{children:"Outcome"}),i.jsx("th",{children:"Started"})]})}),i.jsx("tbody",{children:X.map(ee=>i.jsxs("tr",{children:[i.jsxs("td",{children:["#",ee.attempt_number]}),i.jsx("td",{children:ee.runtime_name??"Not recorded"}),i.jsx("td",{children:Ms(ee).title}),i.jsx("td",{children:ai(ee.started_at??ee.created_at)})]},ee.id))})]}),i.jsx("p",{className:"subtle",children:"A different outcome is evidence to inspect, not proof of better quality. Each attempt's checks and results remain below."})]}),x.worktree&&i.jsxs("p",{className:"notice",children:[r?"Saved working folder: ":"Worktree retained at ",i.jsx("code",{children:x.worktree.path}),!r&&i.jsxs(i.Fragment,{children:[" — ",x.worktree.reason," ",i.jsx(Ae,{href:"/worktrees",children:"release it"})]})]}),(x.publish??[]).length>0&&i.jsx("ul",{className:"publish",children:(x.publish??[]).map(ee=>i.jsxs("li",{children:[i.jsx("strong",{children:ee.step})," ",ee.branch,ee.pr_url?i.jsxs(i.Fragment,{children:[" ",i.jsx("a",{href:ee.pr_url,rel:"noreferrer noopener",target:"_blank",children:"pull request"})]}):null]},`${ee.attempt_id}-${ee.step}`))}),X.length===0?i.jsx(Ba,{title:"No attempts yet",detail:"This job is waiting for a worker to claim it."}):X.map(ee=>i.jsx(jv,{attempt:ee,nowMs:d,compact:r,taskMode:S},ee.id)),r&&Q&&al(Q.state)&&i.jsxs("section",{className:"next-action",children:[i.jsx("h3",{children:"What next?"}),i.jsx("p",{children:S==="ask"?"Turn a recommendation into work. Write one clear change you want Codex to make.":"Review the result and saved working folder above. You can also give Codex a new directive."}),i.jsxs("p",{children:[i.jsx(Ae,{href:`/?project=${encodeURIComponent(x.job.repository)}&mode=build&continue=${encodeURIComponent(x.run_id)}`,children:"Continue from this result →"})," ",i.jsx("span",{className:"subtle",children:"Passes this task's directive and result to the next one."})]}),i.jsx(Ae,{href:`/?project=${encodeURIComponent(x.job.repository)}&mode=build`,children:"Make changes to this project →"}),i.jsx("span",{children:" · "}),i.jsx(Ae,{href:`/?project=${encodeURIComponent(x.job.repository)}&mode=ask`,children:"Ask another question →"}),i.jsx("p",{children:i.jsx(Ae,{href:`/?project=${encodeURIComponent(x.job.repository)}&mode=auto`,children:"Let agents choose the next improvement →"})})]})]})}function jv({attempt:s,nowMs:d,compact:m=!1,taskMode:r}){const{events:S,error:O}=wy(s.id,s.state),x=Z.useMemo(()=>dv(s,S),[s,S]),[D,N]=Z.useState(null),_=Ms(s),Y=al(s.state)?void 0:x.phases.slice().reverse().find(k=>k.endMs===null),C=Yn(s.result)?.phases??[],$=r?lv[r]:[...new Set(x.phases.map(k=>k.phase))],U=i.jsx(mv,{lane:x,nowMs:d,onSelectPhase:N}),R=S.filter(k=>!["keep-local","deliver"].includes(k.phase??"")&&(k.type==="tool_call"||k.type==="log"&&["agent_text","repair_edge","repair_exhausted"].includes(k.name??"")||["phase_start","phase_end","gate_fail","error"].includes(k.type))).slice(-6),X=S.at(-1),Q=S.slice().reverse().find(k=>k.type==="handoff"&&k.phase==="plan"),K=Q?.payload&&typeof Q.payload=="object"&&"summary"in Q.payload&&typeof Q.payload.summary=="string"?Q.payload.summary:null,ee=S.slice().reverse().find(k=>k.type==="log"&&k.name==="agent_text"),fe=ee?.payload&&typeof ee.payload=="object"&&"text"in ee.payload&&typeof ee.payload.text=="string"?ee.payload.text:null;return i.jsxs("div",{className:"attempt",children:[i.jsxs("section",{className:`outcome outcome-${s.state}`,"aria-label":`Attempt ${s.attempt_number} outcome`,children:[i.jsx("h3",{children:m&&_.title==="Task complete · kept local"?r==="ask"?"Your answer is ready":"Changes are ready to review":_.title}),i.jsxs("p",{children:[Y?`Current phase: ${Y.label}. `:"",_.detail]}),i.jsxs("p",{children:[i.jsx("strong",{children:"Next step:"})," ",_.next]}),i.jsxs("p",{className:"subtle",children:["Attempt ",s.attempt_number," · ",s.runtime_name??"Runtime not recorded"," · ",ai(s.started_at??s.created_at)]}),m&&i.jsxs("p",{className:"subtle",children:[Wl((s.completed_at?Date.parse(s.completed_at):d)-Date.parse(s.started_at??s.created_at))," elapsed",X?.started_at&&!al(s.state)?` · Last activity ${Wl(Math.max(0,d-Date.parse(X.started_at)))} ago`:""]}),m&&!al(s.state)&&fe&&i.jsx("p",{className:"agent-message",children:fe})]}),m?i.jsxs(i.Fragment,{children:[r==="auto"&&K&&i.jsxs("section",{className:"directive",children:[i.jsx("h3",{children:"Agent's directive"}),i.jsx("p",{children:K}),i.jsx("p",{className:"subtle",children:"The builder receives the full plan automatically. No input is needed here."})]}),i.jsx("ol",{className:"task-steps","aria-label":"Task progress",children:$.map(k=>{const Fe=x.phases.slice().reverse().find(De=>De.phase===k),te=C.slice().reverse().find(De=>De.phase===k)?.status??Fe?.status??(Fe?.endMs===null?"running":al(s.state)?"not run":"waiting"),xe=x.phases.filter(De=>De.phase===k).length;return i.jsxs("li",{children:[i.jsxs("span",{children:[k==="scout"?"Read project":k,xe>1?` · round ${xe}`:""]}),i.jsx(Bt,{state:te})]},k)})}),i.jsxs("details",{className:"activity","aria-label":"Recent activity",open:!al(s.state),children:[i.jsx("summary",{children:al(s.state)?"Activity history":"Live activity"}),R.length===0?i.jsx("p",{className:"subtle",children:"Waiting for the worker's first activity. This page checks for updates automatically."}):i.jsx("ol",{children:R.map(k=>i.jsxs("li",{children:[i.jsx("time",{children:Ya(k.started_at)}),i.jsx("span",{children:k.type==="tool_call"?`Codex used ${k.name??"a tool"}`:k.type==="phase_start"?`Started ${k.phase==="scout"?"reading the project":k.phase}`:k.type==="phase_end"?`Finished ${k.phase==="scout"?"reading the project":k.phase}`:k.name==="agent_text"?"Codex sent a progress update":k.name==="repair_edge"?"Check failed → agents are repairing and retesting automatically":k.name==="repair_exhausted"?"Repair limit reached; see the diagnostic":k.type==="gate_fail"?"A check failed; inspect the workflow's repair activity":"Worker reported an error"})]},k.seq))})]}),i.jsxs("details",{className:"evidence",children:[i.jsx("summary",{children:"Technical activity"}),U]})]}):U,D&&i.jsx("button",{type:"button",onClick:()=>N(null),children:"Clear phase filter"}),i.jsx(Oe,{error:O}),i.jsx(Sv,{attempt:s,openPhase:D,compact:m})]})}function Sv({attempt:s,openPhase:d,compact:m=!1}){const r=al(s.state),S=Z.useCallback(()=>Me.attemptGates(s.id),[s.id]),O=Z.useCallback(()=>Me.attemptEnvelopes(s.id),[s.id]),x=Mt(S,r?0:5e3,`gates:${s.id}:${s.state}`),D=Mt(O,r?0:5e3,`envelopes:${s.id}:${s.state}`),N=Z.useMemo(()=>Yn(s.result),[s.result]),_=N?.phases??[],Y=_.map(U=>{const R=U.envelope;return U.kind!=="code"&&R!==null&&typeof R=="object"&&"summary"in R&&typeof R.summary=="string"}).lastIndexOf(!0),C=(x.data??[]).filter(U=>!d||U.phase===d),$=(D.data??[]).filter(U=>!d||U.phase===d);return!s.result&&C.length===0&&$.length===0&&!s.error&&!x.error&&!D.error?null:i.jsxs(i.Fragment,{children:[m&&N&&i.jsxs("section",{className:"result-facts","aria-label":"Result facts",children:[i.jsx("h3",{children:N.changed_paths?.length?"Changed files":"Files changed"}),N.changed_paths?.length?i.jsx("ul",{children:N.changed_paths.map(U=>i.jsx("li",{children:i.jsx("code",{children:U})},U))}):i.jsx("p",{children:"No file changes recorded."}),i.jsx("h3",{children:"Verification"}),i.jsxs("p",{children:[_.some(U=>U.phase==="test"&&U.status==="success")?"Test command passed.":_.some(U=>U.phase==="test"&&U.status==="fail")?"Test command failed. Review the diagnostic below.":"No test command result recorded."," ",N.acceptance?.passed===!0?"Workflow checks passed.":N.acceptance?.passed===!1?"Workflow checks did not pass.":""]})]}),_.map((U,R)=>{const X=U.envelope,Q=X&&typeof X=="object"?X:{},K="summary"in Q?Q.summary:null;if(typeof K!="string")return null;const ee=i.jsxs("section",{className:"report",children:[i.jsx("h4",{children:m&&R===Y?"Result":`${U.phase} · result`}),"approved"in Q&&typeof Q.approved=="boolean"&&i.jsx("p",{children:i.jsxs("strong",{children:["Agent assessment: ",Q.approved?"Approved":"Not approved"]})}),i.jsx("p",{className:"report-text",children:K}),"blocking"in Q&&Array.isArray(Q.blocking)&&Q.blocking.length>0&&i.jsx("ul",{className:"checks",children:Q.blocking.filter(fe=>typeof fe=="string").map((fe,k)=>i.jsx("li",{children:fe},k))})]},`${U.phase}-${U.phase_attempt}`);return m&&R!==Y?i.jsxs("details",{className:"evidence",children:[i.jsxs("summary",{children:[U.kind==="code"?"Check":"Earlier step",": ",U.phase]}),ee]},`${U.phase}-${U.phase_attempt}`):ee}),s.error&&i.jsx("p",{className:"attempt-error",role:"alert",children:s.error}),i.jsx(Oe,{error:x.error}),i.jsx(Oe,{error:D.error}),s.result&&!N&&i.jsxs("details",{className:"evidence",children:[i.jsx("summary",{children:"Unrecognized result · view original record"}),i.jsx("pre",{children:s.result})]}),i.jsxs("details",{className:"evidence",open:d!==null,children:[i.jsxs("summary",{children:["Evidence",d?` · ${d}`:""," — ",C.length," gate check",C.length===1?"":"s",$.length>0?`, ${$.length} invalid emission`:""]}),(N?.acceptance?.checks??[]).length>0&&i.jsxs(i.Fragment,{children:[i.jsx("h4",{children:"Acceptance checks"}),i.jsx("ul",{className:"checks",children:N?.acceptance?.checks?.map((U,R)=>i.jsxs("li",{className:U.ok?"ok":"not-ok",children:[U.ok?"Pass":"Fail"," · ",U.item,": ",U.note]},R))})]}),_.filter(U=>!d||U.phase===d).map(U=>i.jsx(xv,{phase:U},`${U.phase}-${U.phase_attempt}`)),C.length>0&&i.jsxs("table",{className:"gates",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"Phase"}),i.jsx("th",{children:"Gate"}),i.jsx("th",{children:"Item"}),i.jsx("th",{children:"Result"}),i.jsx("th",{children:"Note"})]})}),i.jsx("tbody",{children:C.map((U,R)=>i.jsxs("tr",{children:[i.jsx("td",{children:U.phase}),i.jsx("td",{children:U.gate}),i.jsx("td",{children:U.item}),i.jsx("td",{className:U.ok?"ok":"not-ok",children:U.ok?"pass":"fail"}),i.jsx("td",{children:U.note})]},`${U.phase}-${U.gate}-${U.item}-${R}`))})]}),$.map(U=>i.jsxs("div",{className:"invalid-envelope",children:[i.jsxs("h4",{children:["Invalid emission · ",U.phase," · seq ",U.emission]}),i.jsx("p",{className:"subtle",children:U.parse_error}),i.jsx("pre",{children:U.body}),i.jsx("p",{className:"subtle",children:"Stored capped; the complete emission is in this attempt's JSONL trace."})]},`${U.phase}-${U.emission}`))]})]})}function xv({phase:s}){const d=s.started_at?Date.parse(s.started_at):null,m=s.ended_at?Date.parse(s.ended_at):null;return i.jsxs("div",{className:"envelope",children:[i.jsxs("h4",{children:[s.phase," ",i.jsx("span",{className:`badge badge-${s.status}`,children:s.status}),d&&m?i.jsxs("span",{className:"subtle",children:[" · ",Wl(m-d)]}):null]}),s.envelope?i.jsx("pre",{children:JSON.stringify(s.envelope,null,2)}):i.jsx("p",{className:"subtle",children:"No envelope recorded for this phase."}),(s.gates?.checks??[]).length>0&&i.jsx("ul",{className:"checks",children:(s.gates?.checks??[]).map((r,S)=>i.jsxs("li",{className:r.ok?"ok":"not-ok",children:[r.item,": ",r.note??(r.ok?"ok":"failed")]},`${r.item}-${S}`))})]})}function _v(){const s=Z.useCallback(()=>Me.worktrees(),[]),{data:d,error:m,loading:r,refresh:S}=Mt(s,5e3,"worktrees"),[O,x]=Z.useState(null),[D,N]=Z.useState(null),_=async Y=>{try{await Me.releaseWorktree(Y),N(null),x(null),S()}catch(C){N(C)}};return r&&!d?i.jsx(Ga,{label:"Loading worktrees…"}):d?i.jsxs("div",{className:"view",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:"Retained worktrees"}),i.jsx("p",{className:"subtle",children:"Kept because publish could not be proven. Inspect the path, then release."})]}),i.jsx("div",{className:"counters",children:i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.length}),i.jsx("span",{className:"counter-label",children:"retained"})]})})]}),i.jsx(Oe,{error:m}),i.jsx(Oe,{error:D}),d.length===0?i.jsx(Ba,{title:"Nothing retained",detail:"Every attempt's worktree was disposed cleanly."}):i.jsxs("table",{className:"table",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"Repository"}),i.jsx("th",{children:"Path"}),i.jsx("th",{children:"Reason"}),i.jsx("th",{children:"Attempt"}),i.jsx("th",{children:"Since"}),i.jsx("th",{})]})}),i.jsx("tbody",{children:d.map(Y=>i.jsxs("tr",{children:[i.jsx("td",{children:Y.repository}),i.jsx("td",{children:i.jsx("code",{children:Y.path})}),i.jsx("td",{children:Y.reason}),i.jsx("td",{children:i.jsx(Ae,{href:`/jobs/${Y.attempt_id}`,children:As(Y.attempt_id)})}),i.jsx("td",{children:Ya(Y.created_at)}),i.jsx("td",{children:O===Y.attempt_id?i.jsxs("span",{className:"confirm",children:[i.jsx("button",{type:"button",onClick:()=>{_(Y.attempt_id)},children:"Confirm release"}),i.jsx("button",{type:"button",onClick:()=>x(null),children:"Keep"})]}):i.jsx("button",{type:"button",onClick:()=>x(Y.attempt_id),children:"Release…"})})]},Y.attempt_id))})]})]}):i.jsx(Oe,{error:m})}function Tv(){const s=ky();return i.jsxs("div",{className:"app",children:[i.jsxs("nav",{className:"nav","aria-label":"Main navigation",children:[i.jsxs("span",{className:"brand",children:["jig",i.jsx("span",{className:"brand-caption",children:"software factory"})]}),i.jsx("span",{className:"nav-caption",children:"WORKSPACE"}),i.jsxs(Ae,{href:"/",current:s.name==="tasks",children:[i.jsx("span",{"aria-hidden":"true",children:"+"})," New task"]}),i.jsxs(Ae,{href:"/runs",current:["runs","run","job"].includes(s.name),children:[i.jsx("span",{"aria-hidden":"true",children:"▦"})," My tasks"]}),i.jsxs("details",{className:"nav-tools",children:[i.jsx("summary",{children:"Tools"}),i.jsx(Ae,{href:"/queue",current:s.name==="queue",children:"Work queue"}),i.jsx(Ae,{href:"/fleet",current:s.name==="fleet",children:"Workers"}),i.jsx(Ae,{href:"/worktrees",current:s.name==="worktrees",children:"Saved worktrees"})]}),i.jsxs("div",{className:"nav-footer",children:[i.jsx("span",{className:"nav-caption",children:"LOCAL BY DESIGN"}),i.jsxs("p",{children:["Your projects.",i.jsx("br",{}),"Your Codex.",i.jsx("br",{}),"Your next move."]})]})]}),i.jsxs("main",{children:[s.name==="tasks"&&i.jsx(cv,{}),s.name==="queue"&&i.jsx(fv,{}),s.name==="runs"&&i.jsx(ov,{}),s.name==="run"&&i.jsx(gv,{runID:s.id}),s.name==="job"&&i.jsx(bv,{jobID:s.id}),s.name==="worktrees"&&i.jsx(_v,{}),s.name==="fleet"&&i.jsx(Vy,{}),s.name==="unknown"&&i.jsx(Ba,{title:"No such view",detail:`Nothing is served at ${s.path}.`})]})]})}Hy.createRoot(document.getElementById("root")).render(i.jsx(Z.StrictMode,{children:i.jsx(Tv,{})})); diff --git a/web/dist/assets/index-Earanm8w.js b/web/dist/assets/index-Earanm8w.js new file mode 100644 index 0000000..1bdd429 --- /dev/null +++ b/web/dist/assets/index-Earanm8w.js @@ -0,0 +1,177 @@ +(function(){const d=document.createElement("link").relList;if(d&&d.supports&&d.supports("modulepreload"))return;for(const S of document.querySelectorAll('link[rel="modulepreload"]'))r(S);new MutationObserver(S=>{for(const O of S)if(O.type==="childList")for(const x of O.addedNodes)x.tagName==="LINK"&&x.rel==="modulepreload"&&r(x)}).observe(document,{childList:!0,subtree:!0});function m(S){const O={};return S.integrity&&(O.integrity=S.integrity),S.referrerPolicy&&(O.referrerPolicy=S.referrerPolicy),S.crossOrigin==="use-credentials"?O.credentials="include":S.crossOrigin==="anonymous"?O.credentials="omit":O.credentials="same-origin",O}function r(S){if(S.ep)return;S.ep=!0;const O=m(S);fetch(S.href,O)}})();var xs={exports:{}},Cn={};var Bd;function Ny(){if(Bd)return Cn;Bd=1;var s=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function m(r,S,O){var x=null;if(O!==void 0&&(x=""+O),S.key!==void 0&&(x=""+S.key),"key"in S){O={};for(var D in S)D!=="key"&&(O[D]=S[D])}else O=S;return S=O.ref,{$$typeof:s,type:r,key:x,ref:S!==void 0?S:null,props:O}}return Cn.Fragment=d,Cn.jsx=m,Cn.jsxs=m,Cn}var Gd;function Ay(){return Gd||(Gd=1,xs.exports=Ny()),xs.exports}var i=Ay(),_s={exports:{}},I={};var wd;function My(){if(wd)return I;wd=1;var s=Symbol.for("react.transitional.element"),d=Symbol.for("react.portal"),m=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),S=Symbol.for("react.profiler"),O=Symbol.for("react.consumer"),x=Symbol.for("react.context"),D=Symbol.for("react.forward_ref"),N=Symbol.for("react.suspense"),_=Symbol.for("react.memo"),Y=Symbol.for("react.lazy"),C=Symbol.for("react.activity"),$=Symbol.iterator;function U(y){return y===null||typeof y!="object"?null:(y=$&&y[$]||y["@@iterator"],typeof y=="function"?y:null)}var R={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},X=Object.assign,Q={};function J(y,M,H){this.props=y,this.context=M,this.refs=Q,this.updater=H||R}J.prototype.isReactComponent={},J.prototype.setState=function(y,M){if(typeof y!="object"&&typeof y!="function"&&y!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,y,M,"setState")},J.prototype.forceUpdate=function(y){this.updater.enqueueForceUpdate(this,y,"forceUpdate")};function F(){}F.prototype=J.prototype;function fe(y,M,H){this.props=y,this.context=M,this.refs=Q,this.updater=H||R}var k=fe.prototype=new F;k.constructor=fe,X(k,J.prototype),k.isPureReactComponent=!0;var Fe=Array.isArray;function we(){}var te={H:null,A:null,T:null,S:null},xe=Object.prototype.hasOwnProperty;function De(y,M,H){var G=H.ref;return{$$typeof:s,type:y,key:M,ref:G!==void 0?G:null,props:H}}function nl(y,M){return De(y.type,M,y.props)}function gt(y){return typeof y=="object"&&y!==null&&y.$$typeof===s}function W(y){var M={"=":"=0",":":"=2"};return"$"+y.replace(/[=:]/g,function(H){return M[H]})}var Ue=/\/+/g;function Ot(y,M){return typeof y=="object"&&y!==null&&y.key!=null?W(""+y.key):M.toString(36)}function ct(y){switch(y.status){case"fulfilled":return y.value;case"rejected":throw y.reason;default:switch(typeof y.status=="string"?y.then(we,we):(y.status="pending",y.then(function(M){y.status==="pending"&&(y.status="fulfilled",y.value=M)},function(M){y.status==="pending"&&(y.status="rejected",y.reason=M)})),y.status){case"fulfilled":return y.value;case"rejected":throw y.reason}}throw y}function E(y,M,H,G,P){var ae=typeof y;(ae==="undefined"||ae==="boolean")&&(y=null);var he=!1;if(y===null)he=!0;else switch(ae){case"bigint":case"string":case"number":he=!0;break;case"object":switch(y.$$typeof){case s:case d:he=!0;break;case Y:return he=y._init,E(he(y._payload),M,H,G,P)}}if(he)return P=P(y),he=G===""?"."+Ot(y,0):G,Fe(P)?(H="",he!=null&&(H=he.replace(Ue,"$&/")+"/"),E(P,M,H,"",function(wa){return wa})):P!=null&&(gt(P)&&(P=nl(P,H+(P.key==null||y&&y.key===P.key?"":(""+P.key).replace(Ue,"$&/")+"/")+he)),M.push(P)),1;he=0;var Ie=G===""?".":G+":";if(Fe(y))for(var Re=0;Re>>1,je=E[ve];if(0>>1;veS(H,K))GS(P,H)?(E[ve]=P,E[G]=K,ve=G):(E[ve]=H,E[M]=K,ve=M);else if(GS(P,K))E[ve]=P,E[G]=K,ve=G;else break e}}return q}function S(E,q){var K=E.sortIndex-q.sortIndex;return K!==0?K:E.id-q.id}if(s.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var O=performance;s.unstable_now=function(){return O.now()}}else{var x=Date,D=x.now();s.unstable_now=function(){return x.now()-D}}var N=[],_=[],Y=1,C=null,$=3,U=!1,R=!1,X=!1,Q=!1,J=typeof setTimeout=="function"?setTimeout:null,F=typeof clearTimeout=="function"?clearTimeout:null,fe=typeof setImmediate<"u"?setImmediate:null;function k(E){for(var q=m(_);q!==null;){if(q.callback===null)r(_);else if(q.startTime<=E)r(_),q.sortIndex=q.expirationTime,d(N,q);else break;q=m(_)}}function Fe(E){if(X=!1,k(E),!R)if(m(N)!==null)R=!0,we||(we=!0,W());else{var q=m(_);q!==null&&ct(Fe,q.startTime-E)}}var we=!1,te=-1,xe=5,De=-1;function nl(){return Q?!0:!(s.unstable_now()-DeE&&nl());){var ve=C.callback;if(typeof ve=="function"){C.callback=null,$=C.priorityLevel;var je=ve(C.expirationTime<=E);if(E=s.unstable_now(),typeof je=="function"){C.callback=je,k(E),q=!0;break t}C===m(N)&&r(N),k(E)}else r(N);C=m(N)}if(C!==null)q=!0;else{var y=m(_);y!==null&&ct(Fe,y.startTime-E),q=!1}}break e}finally{C=null,$=K,U=!1}q=void 0}}finally{q?W():we=!1}}}var W;if(typeof fe=="function")W=function(){fe(gt)};else if(typeof MessageChannel<"u"){var Ue=new MessageChannel,Ot=Ue.port2;Ue.port1.onmessage=gt,W=function(){Ot.postMessage(null)}}else W=function(){J(gt,0)};function ct(E,q){te=J(function(){E(s.unstable_now())},q)}s.unstable_IdlePriority=5,s.unstable_ImmediatePriority=1,s.unstable_LowPriority=4,s.unstable_NormalPriority=3,s.unstable_Profiling=null,s.unstable_UserBlockingPriority=2,s.unstable_cancelCallback=function(E){E.callback=null},s.unstable_forceFrameRate=function(E){0>E||125ve?(E.sortIndex=K,d(_,E),m(N)===null&&E===m(_)&&(X?(F(te),te=-1):X=!0,ct(Fe,K-ve))):(E.sortIndex=je,d(N,E),R||U||(R=!0,we||(we=!0,W()))),E},s.unstable_shouldYield=nl,s.unstable_wrapCallback=function(E){var q=$;return function(){var K=$;$=q;try{return E.apply(this,arguments)}finally{$=K}}}})(zs)),zs}var kd;function Dy(){return kd||(kd=1,Es.exports=Oy()),Es.exports}var Ns={exports:{}},$e={};var Ld;function Uy(){if(Ld)return $e;Ld=1;var s=Os();function d(N){var _="https://react.dev/errors/"+N;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(d){console.error(d)}}return s(),Ns.exports=Uy(),Ns.exports}var Vd;function Cy(){if(Vd)return qn;Vd=1;var s=Dy(),d=Os(),m=Ry();function r(e){var t="https://react.dev/errors/"+e;if(1je||(e.current=ve[je],ve[je]=null,je--)}function H(e,t){je++,ve[je]=e.current,e.current=t}var G=y(null),P=y(null),ae=y(null),he=y(null);function Ie(e,t){switch(H(ae,t),H(P,e),H(G,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?cd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=cd(t),e=sd(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}M(G),H(G,e)}function Re(){M(G),M(P),M(ae)}function wa(e){e.memoizedState!==null&&H(he,e);var t=G.current,l=sd(t,e.type);t!==l&&(H(P,e),H(G,l))}function Bn(e){P.current===e&&(M(G),M(P)),he.current===e&&(M(he),On._currentValue=K)}var ni,qs;function Dl(e){if(ni===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);ni=t&&t[1]||"",qs=-1)":-1n||o[a]!==g[n]){var T=` +`+o[a].replace(" at new "," at ");return e.displayName&&T.includes("")&&(T=T.replace("",e.displayName)),T}while(1<=a&&0<=n);break}}}finally{ui=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Dl(l):""}function nh(e,t){switch(e.tag){case 26:case 27:case 5:return Dl(e.type);case 16:return Dl("Lazy");case 13:return e.child!==t&&t!==null?Dl("Suspense Fallback"):Dl("Suspense");case 19:return Dl("SuspenseList");case 0:case 15:return ii(e.type,!1);case 11:return ii(e.type.render,!1);case 1:return ii(e.type,!0);case 31:return Dl("Activity");default:return""}}function Hs(e){try{var t="",l=null;do t+=nh(e,l),l=e,e=e.return;while(e);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var ci=Object.prototype.hasOwnProperty,si=s.unstable_scheduleCallback,fi=s.unstable_cancelCallback,uh=s.unstable_shouldYield,ih=s.unstable_requestPaint,st=s.unstable_now,ch=s.unstable_getCurrentPriorityLevel,Ys=s.unstable_ImmediatePriority,Bs=s.unstable_UserBlockingPriority,Gn=s.unstable_NormalPriority,sh=s.unstable_LowPriority,Gs=s.unstable_IdlePriority,fh=s.log,rh=s.unstable_setDisableYieldValue,Qa=null,ft=null;function ul(e){if(typeof fh=="function"&&rh(e),ft&&typeof ft.setStrictMode=="function")try{ft.setStrictMode(Qa,e)}catch{}}var rt=Math.clz32?Math.clz32:hh,oh=Math.log,dh=Math.LN2;function hh(e){return e>>>=0,e===0?32:31-(oh(e)/dh|0)|0}var wn=256,Qn=262144,Xn=4194304;function Ul(e){var t=e&42;if(t!==0)return t;switch(e&-e){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:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function kn(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var n=0,u=e.suspendedLanes,c=e.pingedLanes;e=e.warmLanes;var f=a&134217727;return f!==0?(a=f&~u,a!==0?n=Ul(a):(c&=f,c!==0?n=Ul(c):l||(l=f&~e,l!==0&&(n=Ul(l))))):(f=a&~u,f!==0?n=Ul(f):c!==0?n=Ul(c):l||(l=a&~e,l!==0&&(n=Ul(l)))),n===0?0:t!==0&&t!==n&&(t&u)===0&&(u=n&-n,l=t&-t,u>=l||u===32&&(l&4194048)!==0)?t:n}function Xa(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function mh(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32: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 t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ws(){var e=Xn;return Xn<<=1,(Xn&62914560)===0&&(Xn=4194304),e}function ri(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function ka(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function yh(e,t,l,a,n,u){var c=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var f=e.entanglements,o=e.expirationTimes,g=e.hiddenUpdates;for(l=c&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var Sh=/[\n"\\]/g;function jt(e){return e.replace(Sh,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function vi(e,t,l,a,n,u,c,f){e.name="",c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?e.type=c:e.removeAttribute("type"),t!=null?c==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+bt(t)):e.value!==""+bt(t)&&(e.value=""+bt(t)):c!=="submit"&&c!=="reset"||e.removeAttribute("value"),t!=null?pi(e,c,bt(t)):l!=null?pi(e,c,bt(l)):a!=null&&e.removeAttribute("value"),n==null&&u!=null&&(e.defaultChecked=!!u),n!=null&&(e.checked=n&&typeof n!="function"&&typeof n!="symbol"),f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"?e.name=""+bt(f):e.removeAttribute("name")}function Ps(e,t,l,a,n,u,c,f){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||l!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){yi(e);return}l=l!=null?""+bt(l):"",t=t!=null?""+bt(t):l,f||t===e.value||(e.value=t),e.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=f?e.checked:!!a,e.defaultChecked=!!a,c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(e.name=c),yi(e)}function pi(e,t,l){t==="number"&&Vn(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function la(e,t,l,a){if(e=e.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),xi=!1;if(Qt)try{var Ka={};Object.defineProperty(Ka,"passive",{get:function(){xi=!0}}),window.addEventListener("test",Ka,Ka),window.removeEventListener("test",Ka,Ka)}catch{xi=!1}var cl=null,_i=null,Jn=null;function cf(){if(Jn)return Jn;var e,t=_i,l=t.length,a,n="value"in cl?cl.value:cl.textContent,u=n.length;for(e=0;e=Wa),hf=" ",mf=!1;function yf(e,t){switch(e){case"keyup":return $h.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function vf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ia=!1;function Fh(e,t){switch(e){case"compositionend":return vf(t);case"keypress":return t.which!==32?null:(mf=!0,hf);case"textInput":return e=t.data,e===hf&&mf?null:e;default:return null}}function Ih(e,t){if(ia)return e==="compositionend"||!Ai&&yf(e,t)?(e=cf(),Jn=_i=cl=null,ia=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Tf(l)}}function zf(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?zf(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Nf(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Vn(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=Vn(e.document)}return t}function Di(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var im=Qt&&"documentMode"in document&&11>=document.documentMode,ca=null,Ui=null,en=null,Ri=!1;function Af(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Ri||ca==null||ca!==Vn(a)||(a=ca,"selectionStart"in a&&Di(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),en&&Pa(en,a)||(en=a,a=Qu(Ui,"onSelect"),0>=c,n-=c,Ct=1<<32-rt(t)+n|l<le?(ce=w,w=null):ce=w.sibling;var oe=b(v,w,p[le],z);if(oe===null){w===null&&(w=ce);break}e&&w&&oe.alternate===null&&t(v,w),h=u(oe,h,le),re===null?L=oe:re.sibling=oe,re=oe,w=ce}if(le===p.length)return l(v,w),se&&kt(v,le),L;if(w===null){for(;lele?(ce=w,w=null):ce=w.sibling;var Ml=b(v,w,oe.value,z);if(Ml===null){w===null&&(w=ce);break}e&&w&&Ml.alternate===null&&t(v,w),h=u(Ml,h,le),re===null?L=Ml:re.sibling=Ml,re=Ml,w=ce}if(oe.done)return l(v,w),se&&kt(v,le),L;if(w===null){for(;!oe.done;le++,oe=p.next())oe=A(v,oe.value,z),oe!==null&&(h=u(oe,h,le),re===null?L=oe:re.sibling=oe,re=oe);return se&&kt(v,le),L}for(w=a(w);!oe.done;le++,oe=p.next())oe=j(w,v,le,oe.value,z),oe!==null&&(e&&oe.alternate!==null&&w.delete(oe.key===null?le:oe.key),h=u(oe,h,le),re===null?L=oe:re.sibling=oe,re=oe);return e&&w.forEach(function(zy){return t(v,zy)}),se&&kt(v,le),L}function be(v,h,p,z){if(typeof p=="object"&&p!==null&&p.type===X&&p.key===null&&(p=p.props.children),typeof p=="object"&&p!==null){switch(p.$$typeof){case U:e:{for(var L=p.key;h!==null;){if(h.key===L){if(L=p.type,L===X){if(h.tag===7){l(v,h.sibling),z=n(h,p.props.children),z.return=v,v=z;break e}}else if(h.elementType===L||typeof L=="object"&&L!==null&&L.$$typeof===xe&&kl(L)===h.type){l(v,h.sibling),z=n(h,p.props),cn(z,p),z.return=v,v=z;break e}l(v,h);break}else t(v,h);h=h.sibling}p.type===X?(z=Bl(p.props.children,v.mode,z,p.key),z.return=v,v=z):(z=nu(p.type,p.key,p.props,null,v.mode,z),cn(z,p),z.return=v,v=z)}return c(v);case R:e:{for(L=p.key;h!==null;){if(h.key===L)if(h.tag===4&&h.stateNode.containerInfo===p.containerInfo&&h.stateNode.implementation===p.implementation){l(v,h.sibling),z=n(h,p.children||[]),z.return=v,v=z;break e}else{l(v,h);break}else t(v,h);h=h.sibling}z=wi(p,v.mode,z),z.return=v,v=z}return c(v);case xe:return p=kl(p),be(v,h,p,z)}if(ct(p))return B(v,h,p,z);if(W(p)){if(L=W(p),typeof L!="function")throw Error(r(150));return p=L.call(p),V(v,h,p,z)}if(typeof p.then=="function")return be(v,h,ou(p),z);if(p.$$typeof===fe)return be(v,h,cu(v,p),z);du(v,p)}return typeof p=="string"&&p!==""||typeof p=="number"||typeof p=="bigint"?(p=""+p,h!==null&&h.tag===6?(l(v,h.sibling),z=n(h,p),z.return=v,v=z):(l(v,h),z=Gi(p,v.mode,z),z.return=v,v=z),c(v)):l(v,h)}return function(v,h,p,z){try{un=0;var L=be(v,h,p,z);return ga=null,L}catch(w){if(w===pa||w===fu)throw w;var re=dt(29,w,null,v.mode);return re.lanes=z,re.return=v,re}}}var Zl=Ff(!0),If=Ff(!1),dl=!1;function Ii(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Pi(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function hl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function ml(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(de&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=au(e),qf(e,null,l),t}return lu(e,a,t,l),au(e)}function sn(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Xs(e,l)}}function ec(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var c={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=c:u=u.next=c,l=l.next}while(l!==null);u===null?n=u=t:u=u.next=t}else n=u=t;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var tc=!1;function fn(){if(tc){var e=va;if(e!==null)throw e}}function rn(e,t,l,a){tc=!1;var n=e.updateQueue;dl=!1;var u=n.firstBaseUpdate,c=n.lastBaseUpdate,f=n.shared.pending;if(f!==null){n.shared.pending=null;var o=f,g=o.next;o.next=null,c===null?u=g:c.next=g,c=o;var T=e.alternate;T!==null&&(T=T.updateQueue,f=T.lastBaseUpdate,f!==c&&(f===null?T.firstBaseUpdate=g:f.next=g,T.lastBaseUpdate=o))}if(u!==null){var A=n.baseState;c=0,T=g=o=null,f=u;do{var b=f.lane&-536870913,j=b!==f.lane;if(j?(ie&b)===b:(a&b)===b){b!==0&&b===ya&&(tc=!0),T!==null&&(T=T.next={lane:0,tag:f.tag,payload:f.payload,callback:null,next:null});e:{var B=e,V=f;b=t;var be=l;switch(V.tag){case 1:if(B=V.payload,typeof B=="function"){A=B.call(be,A,b);break e}A=B;break e;case 3:B.flags=B.flags&-65537|128;case 0:if(B=V.payload,b=typeof B=="function"?B.call(be,A,b):B,b==null)break e;A=C({},A,b);break e;case 2:dl=!0}}b=f.callback,b!==null&&(e.flags|=64,j&&(e.flags|=8192),j=n.callbacks,j===null?n.callbacks=[b]:j.push(b))}else j={lane:b,tag:f.tag,payload:f.payload,callback:f.callback,next:null},T===null?(g=T=j,o=A):T=T.next=j,c|=b;if(f=f.next,f===null){if(f=n.shared.pending,f===null)break;j=f,f=j.next,j.next=null,n.lastBaseUpdate=j,n.shared.pending=null}}while(!0);T===null&&(o=A),n.baseState=o,n.firstBaseUpdate=g,n.lastBaseUpdate=T,u===null&&(n.shared.lanes=0),bl|=c,e.lanes=c,e.memoizedState=A}}function Pf(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function er(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;eu?u:8;var c=E.T,f={};E.T=f,jc(e,!1,t,l);try{var o=n(),g=E.S;if(g!==null&&g(f,o),o!==null&&typeof o=="object"&&typeof o.then=="function"){var T=ym(o,a);hn(e,t,T,pt(e))}else hn(e,t,a,pt(e))}catch(A){hn(e,t,{then:function(){},status:"rejected",reason:A},pt())}finally{q.p=u,c!==null&&f.types!==null&&(c.types=f.types),E.T=c}}function Sm(){}function gc(e,t,l,a){if(e.tag!==5)throw Error(r(476));var n=Ur(e).queue;Dr(e,n,t,K,l===null?Sm:function(){return Rr(e),l(a)})}function Ur(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:K,baseState:K,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Kt,lastRenderedState:K},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Kt,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Rr(e){var t=Ur(e);t.next===null&&(t=e.alternate.memoizedState),hn(e,t.next.queue,{},pt())}function bc(){return Ve(On)}function Cr(){return qe().memoizedState}function qr(){return qe().memoizedState}function xm(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=pt();e=hl(l);var a=ml(t,e,l);a!==null&&(it(a,t,l),sn(a,t,l)),t={cache:Ji()},e.payload=t;return}t=t.return}}function _m(e,t,l){var a=pt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},xu(e)?Yr(t,l):(l=Yi(e,t,l,a),l!==null&&(it(l,e,a),Br(l,t,a)))}function Hr(e,t,l){var a=pt();hn(e,t,l,a)}function hn(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(xu(e))Yr(t,n);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var c=t.lastRenderedState,f=u(c,l);if(n.hasEagerState=!0,n.eagerState=f,ot(f,c))return lu(e,t,n,0),Se===null&&tu(),!1}catch{}if(l=Yi(e,t,n,a),l!==null)return it(l,e,a),Br(l,t,a),!0}return!1}function jc(e,t,l,a){if(a={lane:2,revertLane:Ic(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},xu(e)){if(t)throw Error(r(479))}else t=Yi(e,l,a,2),t!==null&&it(t,e,2)}function xu(e){var t=e.alternate;return e===ee||t!==null&&t===ee}function Yr(e,t){ja=yu=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Br(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Xs(e,l)}}var mn={readContext:Ve,use:gu,useCallback:ze,useContext:ze,useEffect:ze,useImperativeHandle:ze,useLayoutEffect:ze,useInsertionEffect:ze,useMemo:ze,useReducer:ze,useRef:ze,useState:ze,useDebugValue:ze,useDeferredValue:ze,useTransition:ze,useSyncExternalStore:ze,useId:ze,useHostTransitionStatus:ze,useFormState:ze,useActionState:ze,useOptimistic:ze,useMemoCache:ze,useCacheRefresh:ze};mn.useEffectEvent=ze;var Gr={readContext:Ve,use:gu,useCallback:function(e,t){return Pe().memoizedState=[e,t===void 0?null:t],e},useContext:Ve,useEffect:xr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,ju(4194308,4,zr.bind(null,t,e),l)},useLayoutEffect:function(e,t){return ju(4194308,4,e,t)},useInsertionEffect:function(e,t){ju(4,2,e,t)},useMemo:function(e,t){var l=Pe();t=t===void 0?null:t;var a=e();if(Vl){ul(!0);try{e()}finally{ul(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=Pe();if(l!==void 0){var n=l(t);if(Vl){ul(!0);try{l(t)}finally{ul(!1)}}}else n=t;return a.memoizedState=a.baseState=n,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},a.queue=e,e=e.dispatch=_m.bind(null,ee,e),[a.memoizedState,e]},useRef:function(e){var t=Pe();return e={current:e},t.memoizedState=e},useState:function(e){e=hc(e);var t=e.queue,l=Hr.bind(null,ee,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:vc,useDeferredValue:function(e,t){var l=Pe();return pc(l,e,t)},useTransition:function(){var e=hc(!1);return e=Dr.bind(null,ee,e.queue,!0,!1),Pe().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=ee,n=Pe();if(se){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),Se===null)throw Error(r(349));(ie&127)!==0||ir(a,t,l)}n.memoizedState=l;var u={value:l,getSnapshot:t};return n.queue=u,xr(sr.bind(null,a,u,e),[e]),a.flags|=2048,xa(9,{destroy:void 0},cr.bind(null,a,u,l,t),null),l},useId:function(){var e=Pe(),t=Se.identifierPrefix;if(se){var l=qt,a=Ct;l=(a&~(1<<32-rt(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=vu++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?c.createElement("select",{is:a.is}):c.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?c.createElement(n,{is:a.is}):c.createElement(n)}}u[Le]=t,u[et]=a;e:for(c=t.child;c!==null;){if(c.tag===5||c.tag===6)u.appendChild(c.stateNode);else if(c.tag!==4&&c.tag!==27&&c.child!==null){c.child.return=c,c=c.child;continue}if(c===t)break e;for(;c.sibling===null;){if(c.return===null||c.return===t)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}t.stateNode=u;e:switch(Je(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&$t(t)}}return Te(t),Cc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&$t(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=ae.current,ha(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=Ze,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[Le]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||ud(e.nodeValue,l)),e||rl(t,!0)}else e=Xu(e).createTextNode(a),e[Le]=t,t.stateNode=e}return Te(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=ha(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[Le]=t}else Gl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Te(t),e=!1}else l=Li(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(mt(t),t):(mt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Te(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=ha(t),a!==null&&a.dehydrated!==null){if(e===null){if(!n)throw Error(r(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(r(317));n[Le]=t}else Gl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Te(t),n=!1}else n=Li(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(mt(t),t):(mt(t),null)}return mt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Nu(t,t.updateQueue),Te(t),null);case 4:return Re(),e===null&&ls(t.stateNode.containerInfo),Te(t),null;case 10:return Zt(t.type),Te(t),null;case 19:if(M(Ce),a=t.memoizedState,a===null)return Te(t),null;if(n=(t.flags&128)!==0,u=a.rendering,u===null)if(n)vn(a,!1);else{if(Ne!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=mu(e),u!==null){for(t.flags|=128,vn(a,!1),e=u.updateQueue,t.updateQueue=e,Nu(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Hf(l,e),l=l.sibling;return H(Ce,Ce.current&1|2),se&&kt(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&st()>Uu&&(t.flags|=128,n=!0,vn(a,!1),t.lanes=4194304)}else{if(!n)if(e=mu(u),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,Nu(t,e),vn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!u.alternate&&!se)return Te(t),null}else 2*st()-a.renderingStartTime>Uu&&l!==536870912&&(t.flags|=128,n=!0,vn(a,!1),t.lanes=4194304);a.isBackwards?(u.sibling=t.child,t.child=u):(e=a.last,e!==null?e.sibling=u:t.child=u,a.last=u)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=st(),e.sibling=null,l=Ce.current,H(Ce,n?l&1|2:l&1),se&&kt(t,a.treeForkCount),e):(Te(t),null);case 22:case 23:return mt(t),ac(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(Te(t),t.subtreeFlags&6&&(t.flags|=8192)):Te(t),l=t.updateQueue,l!==null&&Nu(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&M(Xl),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),Zt(He),Te(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Am(e,t){switch(Xi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Zt(He),Re(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Bn(t),null;case 31:if(t.memoizedState!==null){if(mt(t),t.alternate===null)throw Error(r(340));Gl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(mt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));Gl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return M(Ce),null;case 4:return Re(),null;case 10:return Zt(t.type),null;case 22:case 23:return mt(t),ac(),e!==null&&M(Xl),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Zt(He),null;case 25:return null;default:return null}}function fo(e,t){switch(Xi(t),t.tag){case 3:Zt(He),Re();break;case 26:case 27:case 5:Bn(t);break;case 4:Re();break;case 31:t.memoizedState!==null&&mt(t);break;case 13:mt(t);break;case 19:M(Ce);break;case 10:Zt(t.type);break;case 22:case 23:mt(t),ac(),e!==null&&M(Xl);break;case 24:Zt(He)}}function pn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&e)===e){a=void 0;var u=l.create,c=l.inst;a=u(),c.destroy=a}l=l.next}while(l!==n)}}catch(f){ye(t,t.return,f)}}function pl(e,t,l){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&e)===e){var c=a.inst,f=c.destroy;if(f!==void 0){c.destroy=void 0,n=t;var o=l,g=f;try{g()}catch(T){ye(n,o,T)}}}a=a.next}while(a!==u)}}catch(T){ye(t,t.return,T)}}function ro(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{er(t,l)}catch(a){ye(e,e.return,a)}}}function oo(e,t,l){l.props=Kl(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){ye(e,t,a)}}function gn(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(n){ye(e,t,n)}}function Ht(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){ye(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){ye(e,t,n)}else l.current=null}function ho(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(n){ye(e,e.return,n)}}function qc(e,t,l){try{var a=e.stateNode;Wm(a,e.type,l,t),a[et]=t}catch(n){ye(e,e.return,n)}}function mo(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Tl(e.type)||e.tag===4}function Hc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||mo(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Tl(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Yc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=wt));else if(a!==4&&(a===27&&Tl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Yc(e,t,l),e=e.sibling;e!==null;)Yc(e,t,l),e=e.sibling}function Au(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&Tl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Au(e,t,l),e=e.sibling;e!==null;)Au(e,t,l),e=e.sibling}function yo(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);Je(t,a,l),t[Le]=e,t[et]=l}catch(u){ye(e,e.return,u)}}var Wt=!1,Ge=!1,Bc=!1,vo=typeof WeakSet=="function"?WeakSet:Set,ke=null;function Mm(e,t){if(e=e.containerInfo,us=$u,e=Nf(e),Di(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var n=a.anchorOffset,u=a.focusNode;a=a.focusOffset;try{l.nodeType,u.nodeType}catch{l=null;break e}var c=0,f=-1,o=-1,g=0,T=0,A=e,b=null;t:for(;;){for(var j;A!==l||n!==0&&A.nodeType!==3||(f=c+n),A!==u||a!==0&&A.nodeType!==3||(o=c+a),A.nodeType===3&&(c+=A.nodeValue.length),(j=A.firstChild)!==null;)b=A,A=j;for(;;){if(A===e)break t;if(b===l&&++g===n&&(f=c),b===u&&++T===a&&(o=c),(j=A.nextSibling)!==null)break;A=b,b=A.parentNode}A=j}l=f===-1||o===-1?null:{start:f,end:o}}else l=null}l=l||{start:0,end:0}}else l=null;for(is={focusedElem:e,selectionRange:l},$u=!1,ke=t;ke!==null;)if(t=ke,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,ke=e;else for(;ke!==null;){switch(t=ke,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),Je(u,a,l),u[Le]=e,Xe(u),a=u;break e;case"link":var c=xd("link","href",n).get(a+(l.href||""));if(c){for(var f=0;fbe&&(c=be,be=V,V=c);var v=Ef(f,V),h=Ef(f,be);if(v&&h&&(j.rangeCount!==1||j.anchorNode!==v.node||j.anchorOffset!==v.offset||j.focusNode!==h.node||j.focusOffset!==h.offset)){var p=A.createRange();p.setStart(v.node,v.offset),j.removeAllRanges(),V>be?(j.addRange(p),j.extend(h.node,h.offset)):(p.setEnd(h.node,h.offset),j.addRange(p))}}}}for(A=[],j=f;j=j.parentNode;)j.nodeType===1&&A.push({element:j,left:j.scrollLeft,top:j.scrollTop});for(typeof f.focus=="function"&&f.focus(),f=0;fl?32:l,E.T=null,l=Zc,Zc=null;var u=Sl,c=tl;if(Qe=0,Na=Sl=null,tl=0,(de&6)!==0)throw Error(r(331));var f=de;if(de|=4,No(u.current),To(u,u.current,c,l),de=f,Tn(0,!1),ft&&typeof ft.onPostCommitFiberRoot=="function")try{ft.onPostCommitFiberRoot(Qa,u)}catch{}return!0}finally{q.p=n,E.T=a,Zo(e,t)}}function Ko(e,t,l){t=xt(l,t),t=Tc(e.stateNode,t,2),e=ml(e,t,2),e!==null&&(ka(e,2),Yt(e))}function ye(e,t,l){if(e.tag===3)Ko(e,e,l);else for(;t!==null;){if(t.tag===3){Ko(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(jl===null||!jl.has(a))){e=xt(l,e),l=Kr(2),a=ml(t,l,2),a!==null&&(Jr(l,a,t,e),ka(a,2),Yt(a));break}}t=t.return}}function $c(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Um;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(l)||(Qc=!0,n.add(l),e=Ym.bind(null,e,t,l),t.then(e,e))}function Ym(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Se===e&&(ie&l)===l&&(Ne===4||Ne===3&&(ie&62914560)===ie&&300>st()-Du?(de&2)===0&&Aa(e,0):Xc|=l,za===ie&&(za=0)),Yt(e)}function Jo(e,t){t===0&&(t=ws()),e=Yl(e,t),e!==null&&(ka(e,t),Yt(e))}function Bm(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),Jo(e,l)}function Gm(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,n=e.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),Jo(e,l)}function wm(e,t){return si(e,t)}var Bu=null,Oa=null,Wc=!1,Gu=!1,Fc=!1,_l=0;function Yt(e){e!==Oa&&e.next===null&&(Oa===null?Bu=Oa=e:Oa=Oa.next=e),Gu=!0,Wc||(Wc=!0,Xm())}function Tn(e,t){if(!Fc&&Gu){Fc=!0;do for(var l=!1,a=Bu;a!==null;){if(e!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var c=a.suspendedLanes,f=a.pingedLanes;u=(1<<31-rt(42|e)+1)-1,u&=n&~(c&~f),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,Io(a,u))}else u=ie,u=kn(a,a===Se?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||Xa(a,u)||(l=!0,Io(a,u));a=a.next}while(l);Fc=!1}}function Qm(){$o()}function $o(){Gu=Wc=!1;var e=0;_l!==0&&Im()&&(e=_l);for(var t=st(),l=null,a=Bu;a!==null;){var n=a.next,u=Wo(a,t);u===0?(a.next=null,l===null?Bu=n:l.next=n,n===null&&(Oa=l)):(l=a,(e!==0||(u&3)!==0)&&(Gu=!0)),a=n}Qe!==0&&Qe!==5||Tn(e),_l!==0&&(_l=0)}function Wo(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,n=e.expirationTimes,u=e.pendingLanes&-62914561;0f)break;var T=o.transferSize,A=o.initiatorType;T&&id(A)&&(o=o.responseEnd,c+=T*(o"u"?null:document;function gd(e,t,l){var a=Da;if(a&&typeof t=="string"&&t){var n=jt(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),pd.has(n)||(pd.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),Je(t,"link",e),Xe(t),a.head.appendChild(t)))}}function cy(e){ll.D(e),gd("dns-prefetch",e,null)}function sy(e,t){ll.C(e,t),gd("preconnect",e,t)}function fy(e,t,l){ll.L(e,t,l);var a=Da;if(a&&e&&t){var n='link[rel="preload"][as="'+jt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+jt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+jt(l.imageSizes)+'"]')):n+='[href="'+jt(e)+'"]';var u=n;switch(t){case"style":u=Ua(e);break;case"script":u=Ra(e)}At.has(u)||(e=C({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),At.set(u,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(An(u))||t==="script"&&a.querySelector(Mn(u))||(t=a.createElement("link"),Je(t,"link",e),Xe(t),a.head.appendChild(t)))}}function ry(e,t){ll.m(e,t);var l=Da;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+jt(a)+'"][href="'+jt(e)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ra(e)}if(!At.has(u)&&(e=C({rel:"modulepreload",href:e},t),At.set(u,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(Mn(u)))return}a=l.createElement("link"),Je(a,"link",e),Xe(a),l.head.appendChild(a)}}}function oy(e,t,l){ll.S(e,t,l);var a=Da;if(a&&e){var n=ea(a).hoistableStyles,u=Ua(e);t=t||"default";var c=n.get(u);if(!c){var f={loading:0,preload:null};if(c=a.querySelector(An(u)))f.loading=5;else{e=C({rel:"stylesheet",href:e,"data-precedence":t},l),(l=At.get(u))&&hs(e,l);var o=c=a.createElement("link");Xe(o),Je(o,"link",e),o._p=new Promise(function(g,T){o.onload=g,o.onerror=T}),o.addEventListener("load",function(){f.loading|=1}),o.addEventListener("error",function(){f.loading|=2}),f.loading|=4,Lu(c,t,a)}c={type:"stylesheet",instance:c,count:1,state:f},n.set(u,c)}}}function dy(e,t){ll.X(e,t);var l=Da;if(l&&e){var a=ea(l).hoistableScripts,n=Ra(e),u=a.get(n);u||(u=l.querySelector(Mn(n)),u||(e=C({src:e,async:!0},t),(t=At.get(n))&&ms(e,t),u=l.createElement("script"),Xe(u),Je(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function hy(e,t){ll.M(e,t);var l=Da;if(l&&e){var a=ea(l).hoistableScripts,n=Ra(e),u=a.get(n);u||(u=l.querySelector(Mn(n)),u||(e=C({src:e,async:!0,type:"module"},t),(t=At.get(n))&&ms(e,t),u=l.createElement("script"),Xe(u),Je(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function bd(e,t,l,a){var n=(n=ae.current)?ku(n):null;if(!n)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=Ua(l.href),l=ea(n).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=Ua(l.href);var u=ea(n).hoistableStyles,c=u.get(e);if(c||(n=n.ownerDocument||n,c={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,c),(u=n.querySelector(An(e)))&&!u._p&&(c.instance=u,c.state.loading=5),At.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},At.set(e,l),u||my(n,e,l,c.state))),t&&a===null)throw Error(r(528,""));return c}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Ra(l),l=ea(n).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function Ua(e){return'href="'+jt(e)+'"'}function An(e){return'link[rel="stylesheet"]['+e+"]"}function jd(e){return C({},e,{"data-precedence":e.precedence,precedence:null})}function my(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),Je(t,"link",l),Xe(t),e.head.appendChild(t))}function Ra(e){return'[src="'+jt(e)+'"]'}function Mn(e){return"script[async]"+e}function Sd(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+jt(l.href)+'"]');if(a)return t.instance=a,Xe(a),a;var n=C({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),Xe(a),Je(a,"style",n),Lu(a,l.precedence,e),t.instance=a;case"stylesheet":n=Ua(l.href);var u=e.querySelector(An(n));if(u)return t.state.loading|=4,t.instance=u,Xe(u),u;a=jd(l),(n=At.get(n))&&hs(a,n),u=(e.ownerDocument||e).createElement("link"),Xe(u);var c=u;return c._p=new Promise(function(f,o){c.onload=f,c.onerror=o}),Je(u,"link",a),t.state.loading|=4,Lu(u,l.precedence,e),t.instance=u;case"script":return u=Ra(l.src),(n=e.querySelector(Mn(u)))?(t.instance=n,Xe(n),n):(a=l,(n=At.get(u))&&(a=C({},l),ms(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),Xe(n),Je(n,"link",a),e.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,Lu(a,l.precedence,e));return t.instance}function Lu(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,c=0;c title"):null)}function yy(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Td(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function vy(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=Ua(a.href),u=t.querySelector(An(n));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=Vu.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=u,Xe(u);return}u=t.ownerDocument||t,a=jd(a),(n=At.get(n))&&hs(a,n),u=u.createElement("link"),Xe(u);var c=u;c._p=new Promise(function(f,o){c.onload=f,c.onerror=o}),Je(u,"link",a),l.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=Vu.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var ys=0;function py(e,t){return e.stylesheets&&e.count===0&&Ju(e,e.stylesheets),0ys?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Vu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Ju(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Ku=null;function Ju(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Ku=new Map,t.forEach(gy,e),Ku=null,Vu.call(e))}function gy(e,t){if(!(t.state.loading&4)){var l=Ku.get(e);if(l)var a=l.get(null);else{l=new Map,Ku.set(e,l);for(var n=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(d){console.error(d)}}return s(),Ts.exports=Cy(),Ts.exports}var Hy=qy();class Ds extends Error{constructor(d,m,r){super(m),this.code=d,this.status=r,this.name="APIError"}code;status}async function We(s,d){const m=await fetch(s,{...d,headers:d?.body?{"Content-Type":"application/json",...d.headers}:d?.headers});if(!m.ok){let r;try{r=await m.json()}catch{}throw new Ds(r?.error?.code??"request_failed",r?.error?.message??`Request failed with status ${m.status}`,m.status)}if(m.status!==204)return await m.json()}const Me={definitions:()=>We("/api/definitions"),createDefinition:s=>We("/api/definitions",{method:"POST",body:JSON.stringify({source:s})}),startTask:(s,d,m,r,{delivery:S="local",context:O,ref:x,continues:D}={})=>We("/api/runs",{method:"POST",body:JSON.stringify({definition_id:s,instructions:m,parameters:{task_title:m,task_mode:r,task_delivery:S,...D?{task_continues:D}:{}},...O?.length?{context:O}:{},targets:[{repository:d,...x?{ref:x}:{}}]})}),queue:()=>We("/api/queue"),runs:()=>We("/api/runs").then(s=>s??[]),run:s=>We(`/api/runs/${encodeURIComponent(s)}`),job:s=>We(`/api/jobs/${encodeURIComponent(s)}`),attempt:s=>We(`/api/attempts/${encodeURIComponent(s)}`),attemptEvents:(s,d,m=200)=>We(`/api/attempts/${encodeURIComponent(s)}/events?after=${d}&limit=${m}`),attemptGates:s=>We(`/api/attempts/${encodeURIComponent(s)}/gates`).then(d=>d??[]),attemptEnvelopes:s=>We(`/api/attempts/${encodeURIComponent(s)}/envelopes`).then(d=>d??[]),fleet:()=>We("/api/workers"),worktrees:()=>We("/api/worktrees").then(s=>s??[]),releaseWorktree:s=>We(`/api/worktrees/${encodeURIComponent(s)}/release`,{method:"POST",body:JSON.stringify({confirm:!0})}),retryJob:s=>We(`/api/jobs/${encodeURIComponent(s)}/retry`,{method:"POST"}),cancelJob:s=>We(`/api/jobs/${encodeURIComponent(s)}/cancel`,{method:"POST"})};async function Yy(s){const d=(await Me.definitions()).find(m=>m.source===s);if(d)return d;try{return await Me.createDefinition(s)}catch(m){if(!(m instanceof Ds)||m.code!=="definition_exists")throw m;const r=(await Me.definitions()).find(S=>S.source===s);if(!r)throw m;return r}}function Yn(s){if(!s)return null;try{const d=JSON.parse(s);return typeof d!="object"||d===null||Array.isArray(d)||d.phases!=null&&(!Array.isArray(d.phases)||d.phases.some(r=>!r||typeof r!="object"||typeof r.phase!="string"||typeof r.status!="string"))||[d.acceptance?.checks,...(d.phases??[]).map(r=>r.gates?.checks)].some(r=>r!=null&&(!Array.isArray(r)||r.some(S=>!S||typeof S!="object"||typeof S.item!="string"||typeof S.ok!="boolean")))?null:d}catch{return null}}function Ha(s){return s.parameters?.task_title??s.parameters?.prompt?.replace(/^Trusted instructions:\s*/,"").split(` + +Untrusted context:`)[0].trim()??"Previous task"}function Hn(s){return s.replace(/\/$/,"").split("/").pop()||s}function Fd(s){return s.parameters?.task_delivery==="publish"?"publish":"local"}function li(s){return s.state==="mixed"&&s.targets.length===1&&Fd(s)==="local"&&s.snapshot.includes('hold_when: "jig_ui_delivery != publish"')?s.parameters?.task_mode==="ask"?"complete":"ready":s.state}function Ol(s){if(!s)return null;const d=Date.parse(s);return Number.isNaN(d)?null:d}function Wl(s){if(!Number.isFinite(s)||s<0)return"—";if(s<1e3)return`${Math.round(s)}ms`;const d=s/1e3;if(d<60)return`${d.toFixed(d<10?1:0)}s`;const m=Math.floor(d/60),r=Math.round(d-m*60);if(m<60)return`${m}m ${r}s`;const S=Math.floor(m/60);return`${S}h ${m-S*60}m`}function Ya(s){const d=Ol(s);return d===null?"—":new Date(d).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit"})}function As(s){return s.length>12?`${s.slice(0,8)}…`:s}function ai(s){const d=Ol(s);return d===null?"—":new Date(d).toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"numeric",minute:"2-digit"})}const By=new Set(["accepted","accepted_unpublished","failed","cancelled","lost"]);function al(s){return By.has(s)}function Gy(s){return{accepted:"Accepted",accepted_unpublished:"Accepted · not published",mixed:"Mixed results",live:"Online",stale:"Offline",active:"In progress",ready:"Ready to review",complete:"Complete"}[s]??s.replace(/_/g," ")}function Us(){const[s,d]=Z.useState(()=>typeof document>"u"||document.visibilityState!=="hidden");return Z.useEffect(()=>{const m=()=>d(document.visibilityState!=="hidden");return document.addEventListener("visibilitychange",m),()=>document.removeEventListener("visibilitychange",m)},[]),s}function Id(s=1e3){const[d,m]=Z.useState(()=>Date.now()),r=Us();return Z.useEffect(()=>{if(!r||s<=0)return;const S=setInterval(()=>m(Date.now()),s);return()=>clearInterval(S)},[s,r]),d}function Mt(s,d,m){const[r,S]=Z.useState(null),[O,x]=Z.useState(null),[D,N]=Z.useState(!0),[_,Y]=Z.useState(0),C=Us(),$=Z.useRef(s);$.current=s,Z.useEffect(()=>{S(null),N(!0),x(null)},[m]),Z.useEffect(()=>{let R=!1,X=!1;const Q=async()=>{if(!X){X=!0;try{const F=await $.current();if(R)return;S(F),x(null)}catch(F){R||x(F)}finally{X=!1,R||N(!1)}}};if(Q(),!C||d<=0)return()=>{R=!0};const J=setInterval(Q,d);return()=>{R=!0,clearInterval(J)}},[m,d,C,_]);const U=Z.useCallback(()=>Y(R=>R+1),[]);return{data:r,error:O,loading:D,refresh:U}}function wy(s,d,m=1e3){const[r,S]=Z.useState([]),[O,x]=Z.useState(null),D=Z.useRef(0),N=Z.useRef(0),[_,Y]=Z.useState(0),C=Us(),$=al(d);return Z.useEffect(()=>{D.current=0,N.current=0,Y(0),S([]),x(null)},[s]),Z.useEffect(()=>{let U=!1,R=null;const X=async()=>{try{const Q=await Me.attemptEvents(s,D.current);if(U)return;const J=Q.events??[];if(x(null),J.length===0){N.current+=1,$&&N.current>=2&&R&&(clearInterval(R),R=null);return}N.current=0;const F=Math.max(D.current,Q.next_cursor);D.current=F,Y(F),S(fe=>Qy(fe,J))}catch(Q){U||x(Q)}};return X(),C&&m>0&&(R=setInterval(()=>{X()},m)),()=>{U=!0,R&&clearInterval(R)}},[s,$,m,C]),{events:r,cursor:_,error:O}}function Qy(s,d){if(d.length===0)return s;const m=new Map;for(const r of s)m.set(r.seq,r);for(const r of d)m.has(r.seq)||m.set(r.seq,r);return[...m.values()].sort((r,S)=>r.seq-S.seq)}function Xy(s){const d=s.split("/").filter(Boolean);return d.length===0?{name:"tasks"}:d[0]==="queue"&&d.length===1?{name:"queue"}:d[0]==="runs"&&d.length===1?{name:"runs"}:d[0]==="runs"&&d.length===2?{name:"run",id:decodeURIComponent(d[1])}:d[0]==="jobs"&&d.length===2?{name:"job",id:decodeURIComponent(d[1])}:d[0]==="worktrees"&&d.length===1?{name:"worktrees"}:d[0]==="fleet"&&d.length===1?{name:"fleet"}:{name:"unknown",path:s}}function Pd(s){window.history.pushState({},"",s),window.dispatchEvent(new PopStateEvent("popstate"))}function ky(){const[s,d]=Z.useState(()=>window.location.pathname);return Z.useEffect(()=>{const m=()=>d(window.location.pathname);return window.addEventListener("popstate",m),()=>window.removeEventListener("popstate",m)},[]),Xy(s)}function Bt({state:s}){return i.jsxs("span",{className:`badge badge-${s}`,children:[i.jsx("span",{className:"dot"}),Gy(s)]})}function Ae({href:s,children:d,current:m=!1}){return i.jsx("a",{href:s,"aria-current":m?"page":void 0,onClick:r=>{r.metaKey||r.ctrlKey||r.shiftKey||(r.preventDefault(),Pd(s))},children:d})}function Oe({error:s}){if(!s)return null;const d=s instanceof Ds?s.code:"request_failed";return i.jsxs("div",{className:"error-banner",role:"alert",children:[i.jsx("strong",{children:d})," ",s.message]})}function Ba({title:s,detail:d}){return i.jsxs("div",{className:"empty",children:[i.jsx("h2",{children:s}),i.jsx("p",{children:d})]})}function Ga({label:s}){return i.jsx("div",{className:"loading",role:"status",children:s})}function Ly(s,d){const m=Ol(d),r=Ol(s.last_heartbeat);return m===null||r===null?"—":`${Wl(Math.max(m-r,0))} ago`}function Zy(s){const d=s.runtimes??[];return d.length===0?"—":d.map(m=>`${m.name} ${m.version}`).join(", ")}function Vy(){const s=Z.useCallback(()=>Me.fleet(),[]),{data:d,error:m,loading:r}=Mt(s,3e3,"fleet");if(r&&!d)return i.jsx(Ga,{label:"Loading fleet…"});if(!d)return i.jsx(Oe,{error:m});const S=d.workers??[],O=S.filter(x=>!x.live).reduce((x,D)=>x+D.active_count,0);return i.jsxs("div",{className:"view",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:"Workers"}),i.jsx("p",{className:"subtle",children:"Online workers execute queued jobs. Offline workers are saved records of previous sessions."}),i.jsxs("p",{className:"subtle",children:["Observed ",Ya(d.observed_at)]})]}),i.jsxs("div",{className:"counters",children:[i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.live_count}),i.jsx("span",{className:"counter-label",children:"online"})]}),i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.stale_count}),i.jsx("span",{className:"counter-label",children:"offline"})]}),i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.available_slots}),i.jsx("span",{className:"counter-label",children:"free slots"})]})]})]}),i.jsx(Oe,{error:m}),S.length===0?i.jsx(Ba,{title:"No workers registered",detail:"Nothing can claim queued work until a worker registers. Start one with `jig worker`."}):i.jsxs(i.Fragment,{children:[i.jsxs("table",{className:"table",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"Worker"}),i.jsx("th",{children:"State"}),i.jsx("th",{children:"Runtime"}),i.jsx("th",{children:"Slots"}),i.jsx("th",{children:"Env"}),i.jsx("th",{children:"Last heartbeat"})]})}),i.jsx("tbody",{children:S.map(x=>i.jsxs("tr",{children:[i.jsxs("td",{children:[x.name,i.jsxs("p",{className:"subtle",children:[i.jsx("code",{children:x.id})," · ",x.worker_version]})]}),i.jsx("td",{children:i.jsx(Bt,{state:x.live?"live":"stale"})}),i.jsx("td",{children:Zy(x)}),i.jsxs("td",{children:[x.active_count," / ",x.capacity]}),i.jsxs("td",{title:(x.env_names??[]).join(" "),children:[(x.env_names??[]).length," names"]}),i.jsx("td",{children:Ly(x,d.observed_at)})]},x.id))})]}),O>0&&i.jsxs("p",{className:"subtle",children:[O," attempt",O===1?" is":"s are"," leased to a worker that stopped heartbeating. The sweeper marks them lost after three missed beats of server uptime, and their jobs are then retryable."]})]})]})}const Ky=[{id:"waiting",label:"Waiting"},{id:"running",label:"Running"},{id:"review",label:"Needs review"},{id:"done",label:"Done"},{id:"stopped",label:"Stopped"}];function Jy(s,d){if(s.state==="active")return d?.length&&d.every(m=>m==="queued")?"waiting":"running";switch(li(s)){case"accepted":case"complete":return"done";case"failed":case"cancelled":return"stopped";default:return"review"}}function $y(s,d){const m=new Map;for(const O of d??[]){const x=m.get(O.run_id);x?x.push(O.state):m.set(O.run_id,[O.state])}const r=Ky.map(O=>({...O,runs:[]})),S=new Map(r.map(O=>[O.id,O]));for(const O of s)S.get(Jy(O,m.get(O.id))).runs.push(O);return r}const Jd=12e3;function $d(s){return s.length<=Jd?s:`${s.slice(0,Jd)} +[truncated]`}function Wy(s){if(!s||typeof s!="object")return"";const{summary:d,notes_for_next_agent:m}=s;return[typeof d=="string"?d:"",typeof m=="string"?m:""].filter(Boolean).join(` + +`)}function Fy(s,d){const m=(d.attempts??[]).at(-1),r=Yn(m?.result),O=[...(r?.phases??[]).map(D=>({phase:D.phase,text:Wy(D.envelope)})).filter(D=>D.text).map(D=>`## ${D.phase} +${D.text}`),r?.changed_paths?.length?`## Changed files +${r.changed_paths.join(` +`)}`:""].filter(Boolean).join(` + +`),x=(d.publish??[]).find(D=>D.step==="push"&&D.branch);return{runID:s.id,repository:d.job.repository,title:Ha(s),context:[{label:"Previous task",body:$d(Ha(s))},...O?[{label:"Previous result",body:$d(O)}]:[]],ref:x?.branch,keptLocal:Fd(s)==="local"&&!x}}async function Iy(s){const d=await Me.run(s),m=d.jobs[0];if(!m)throw new Error("The earlier task has no job to continue from.");return Fy(d.run,await Me.job(m.id))}const Py=`# smoke.yaml — the install check (U11): one genuinely read-only agent phase +# that validates and passes on any repository. +# +# jig run --def examples/definitions/smoke.yaml . "what is this repo?" +# +# Read-only is enforced, not requested: the scout's write allowlist is +# empty, so any repository write rolls back and aborts the attempt (R10). +# The report travels in the envelope alone — no file artifacts, so no file +# gates; the verdict_consistent gate checks the envelope against ITSELF +# (an approval shipping blocking items, or a rejection naming no problem, +# is refuted without reading the repo), which makes it repo-independent. +name: smoke +roster: + scout: + model: haiku + system_prompt: | + You are a read-only scout examining a git repository. You never + create, modify, or delete any file in the repository — you only read, + and you report exclusively through your final JSON envelope. + user_prompt: | + Task: {{prompt}} + + Explore this repository (its layout, languages, build files, and + purpose) and answer the task in your report's "summary" field, in a + few sentences. + + Your final JSON must also include: + - "approved": true if you were able to read the repository and + complete the task, false otherwise + - "blocking": a list of strings naming anything that prevented you + (an empty list when nothing did) + env: [PATH] + writes: [] +phases: + - name: scout + kind: agent + owner: scout + gates: + - {name: verdict_consistent} +acceptance: [all_phases_passed, verdict_consistent] +`,ev=`# plan-build-test.yaml — the code-phase repair edge (U9, KTD2). Plan the +# change, build it, then run the repository's own test command; a failing +# test suite routes its adapter envelope back to the planner, runs the +# builder with the revised plan, and re-runs the suite, budget bounded. +# +# jig run --def examples/definitions/plan-build-test.yaml "add a --version flag" +# +# The repair edge is the whole point. A code phase's failure is nonzero exit +# (R8), and the adapter envelope that carries the exit status and output tail +# enters the repair loop through exactly the same door an agent's failing +# report would — so "the tests broke" is a workflow state, not an incident. +# \`budget: 3\` bounds it and \`exhausted: fail-job\` means a suite that is still +# red after three repair rounds fails the job rather than shipping. +# +# TWO THINGS TO EDIT before using this on your own repository: +# +# 1. The test phase's command. It detects the common entry points, and +# fails loudly when it finds none — an undetected test command must +# never look like a green run. Replace it with your repository's real +# command. +# 2. The builder's \`writes\` allowlist. \`**\` permits every path in the +# worktree, which is the honest default for an open-ended build but the +# weakest write boundary jig can enforce (R10). Narrow it to the +# directories the work belongs in. +# +# THE ROSTER. The builder writes the code, so it runs on \`opus\`; the planner +# only reads and plans, on \`sonnet\`. \`effort: medium\` sets how much the +# builder thinks and verifies while building to a plan — the test phase is +# its check. Leave \`effort\` out to take the CLI's default for the model. +name: plan-build-test +roster: + planner: + model: sonnet + system_prompt: | + You are a read-only planner working in a git repository. You never + create, modify, or delete any file; you produce a plan the builder + will execute, and you report exclusively through your final JSON + envelope. + user_prompt: | + Task: {{prompt}} + + Read enough of this repository to plan the change: which files to + touch, in what order, and how the result will be verified by the + repository's own test command. + + If the previous report contains failed tests, diagnose that failure + and revise the plan before the builder runs again. Pass the failure + evidence and a concrete repair directive in notes_for_next_agent. + Preserve the user's scope. Never weaken tests to make them pass. + + Your final JSON must also include: + - "notes_for_next_agent": the plan itself, concrete enough to + execute without re-deriving it + env: [PATH] + writes: [] + builder: + model: opus + effort: medium + system_prompt: | + You are a builder working in a git repository. You execute the plan + you are handed, you write only what the task requires, and you report + honestly: claim only files you actually created or modified. + + When you are handed a failing test result, fix the cause the failure + names. Do not weaken, skip, or delete a test to make it pass. + user_prompt: | + Task: {{prompt}} + + The plan and any previous phase's report are above. Make the change, + then stop — the test suite runs as its own phase. + On repairs, report all paths changed relative to the original commit, + including changes already present from the previous build. + + Your final JSON must also include: + - "changed_files": the repo-relative paths of every file you + created or modified + - "artifacts": the same paths, for existence verification + env: [PATH] + writes: ["**"] +phases: + - name: plan + kind: agent + owner: planner + - name: build + kind: agent + owner: builder + gates: + - {name: artifacts_exist} + - {name: diff_matches_claims} + - name: test + kind: code + owner: builder + command: > + if [ -f Justfile ] || [ -f justfile ]; then just test; + elif [ -f Makefile ]; then make test; + elif [ -f go.mod ]; then go test ./...; + elif [ -f package.json ]; then npm test --silent; + else echo "plan-build-test: no test command detected — edit the test phase"; exit 1; fi + on_fail: {run: plan, then: rerun-chain, budget: 3, exhausted: fail-job} +acceptance: [all_phases_passed, artifacts_exist, diff_matches_claims] +`,eh="Inspect this project, choose one useful improvement supported by the code, write a concrete directive and implementation plan, build it, and verify it with the existing tests. Keep the change focused. Do not add paid services or change deployment, authentication, secrets, or security policy. Do not weaken tests. Report the chosen improvement, changes, and verification.",tv="gpt-6.1-sol",lv={ask:["scout"],build:["plan","build","test"],auto:["plan","build","test"]};function av(s){return/^(https:\/\/)?github\.com\/[^/\s]+\/[^/\s]+/.test(s.trim())}async function nv(s,d,m="",r="local"){let S=(s==="ask"?Py:ev).replace(/^(\s*)model: .+$/gm,(D,N)=>`${N}model: ${JSON.stringify(d.trim())}`);s==="auto"&&(S=S.replace(" Task: {{prompt}}",` Goal or limits: {{prompt}} + + Inspect the project and choose one focused, useful improvement that + fits this goal. You own the directive: do not ask the user to write it. + Put the chosen directive in summary, and the concrete implementation + plan and failure evidence in notes_for_next_agent. The builder will + execute your plan automatically. Avoid paid services and changes to + deployment, authentication, secrets, or security policy.`)),s!=="ask"&&m.trim()&&(S=S.replace(/ command: >\n(?: .*\n)+/,()=>` command: ${JSON.stringify(m.trim())} +`));const O=s==="ask"?"local":r,x=O==="publish"?"deliver":"keep-local";return S=S.replace(/^acceptance:/m,` - name: ${x} + kind: code + reports_fields: true + command: "printf '%s\\n' '{\\"jig_ui_delivery\\":\\"${O}\\"}'" +acceptance:`),S+=` +publish: + hold_when: "jig_ui_delivery != publish" +`,S=S.replace(/^name: .+$/m,D=>`${D} +runtime: codex`),S.replace(/^name: .+$/m,`name: jig-task-${s}-${await uv(S)}`)}async function uv(s){return Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(s)))).map(d=>d.toString(16).padStart(2,"0")).join("").slice(0,16)}function iv(){try{return localStorage.getItem("jig-project")}catch{return null}}function cv(){const s=Z.useCallback(()=>Me.runs(),[]),d=Mt(s,3e3,"tasks"),m=Z.useCallback(()=>Me.fleet(),[]),r=Mt(m,3e3,"task-workers"),[S,O]=Z.useState(()=>new URLSearchParams(window.location.search).get("project")??iv()??""),[x,D]=Z.useState(""),[N,_]=Z.useState(()=>{const W=new URLSearchParams(window.location.search).get("mode");return W==="ask"||W==="build"?W:"auto"}),[Y,C]=Z.useState(tv),[$,U]=Z.useState(""),[R,X]=Z.useState("local"),[Q]=Z.useState(()=>new URLSearchParams(window.location.search).get("continue")),[J,F]=Z.useState(null),[fe,k]=Z.useState(!1),[Fe,we]=Z.useState(null),te=N!=="ask"&&av(S),xe=te&&R==="publish";Z.useEffect(()=>{if(!Q)return;let W=!0;return Iy(Q).then(Ue=>{W&&(F(Ue),O(Ue.repository))},Ue=>{W&&we(Ue)}),()=>{W=!1}},[Q]);const De=(r.data?.workers??[]).some(W=>W.live&&W.runtimes?.some(Ue=>Ue.name==="codex")),nl=[...new Set((d.data??[]).flatMap(W=>W.targets.map(Ue=>Ue.repository)))],gt=async W=>{if(W.preventDefault(),!(fe||!S.trim()||N!=="auto"&&!x.trim()||!Y.trim()||!De||r.error||Q&&!J)){k(!0),we(null);try{const Ue=xe?"publish":"local",Ot=await Yy(await nv(N,Y,$,Ue)),ct=await Me.startTask(Ot.id,S.trim(),x.trim()||eh,N,{delivery:Ue,context:J?.context,ref:J?.ref,continues:J?.runID});try{localStorage.setItem("jig-project",S.trim())}catch{}Pd(`/runs/${ct.run.id}`)}catch(Ue){we(Ue)}finally{k(!1)}}};return i.jsxs("div",{className:"view workspace",children:[i.jsxs("header",{className:"view-header workspace-hero",children:[i.jsxs("div",{children:[i.jsx("span",{className:"eyebrow",children:"IDEA IN. WORKING SOFTWARE OUT."}),i.jsxs("h1",{children:["Make your ",i.jsx("span",{children:"next move."})]}),i.jsx("p",{className:"subtle",children:"Give agents a project. They find the work, build it, and prove it."})]}),i.jsxs("div",{className:"runtime-status",children:[i.jsx(Bt,{state:De&&!r.error?"live":"stale"}),i.jsx("span",{children:"Codex connection"})]})]}),i.jsxs("div",{className:"workspace-grid",children:[i.jsxs("form",{className:"panel task-form",onSubmit:W=>{gt(W)},children:[i.jsxs("div",{className:"composer-heading",children:[i.jsx("span",{className:"eyebrow",children:"THE WORKBENCH"}),i.jsx("h2",{children:"Let’s build something."}),i.jsx("span",{className:"composer-mark","aria-hidden":"true",children:"↗"})]}),i.jsxs("fieldset",{disabled:fe,children:[i.jsx("label",{htmlFor:"project",children:"1. Project"}),i.jsx("input",{id:"project",list:"projects",placeholder:"Paste a local folder path or GitHub repository",required:!0,value:S,onChange:W=>O(W.target.value)}),i.jsx("datalist",{id:"projects",children:nl.map(W=>i.jsx("option",{value:W,children:Hn(W)},W))}),i.jsx("p",{className:"subtle",children:"Use a Git project. Work starts from its latest commit; uncommitted edits are not included."}),i.jsxs("fieldset",{className:"mode-choice",children:[i.jsx("legend",{children:"2. What result do you want?"}),i.jsxs("label",{className:N==="auto"?"selected":"",children:[i.jsx("input",{type:"radio",name:"mode",value:"auto",checked:N==="auto",onChange:()=>_("auto")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Let agents improve it"}),i.jsx("small",{children:"Agents choose the directive, plan, build, and test. No task-writing required."})]})]}),i.jsxs("label",{className:N==="ask"?"selected":"",children:[i.jsx("input",{type:"radio",name:"mode",value:"ask",checked:N==="ask",onChange:()=>_("ask")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Get an answer"}),i.jsx("small",{children:"Research and recommendations. No files changed."})]})]}),i.jsxs("label",{className:N==="build"?"selected":"",children:[i.jsx("input",{type:"radio",name:"mode",value:"build",checked:N==="build",onChange:()=>_("build")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Make changes"}),i.jsx("small",{children:"Edit files, run tests, and prepare work for review."})]})]})]}),i.jsx("p",{className:"subtle",children:N==="ask"?"Read-only. Codex reads the project and gives you an answer.":"Plan → build → test. Failed tests restart the loop automatically, up to three repair rounds."}),N!=="ask"&&i.jsxs("fieldset",{className:"mode-choice delivery-choice",children:[i.jsx("legend",{children:"When the checks pass"}),i.jsxs("label",{className:xe?"":"selected",children:[i.jsx("input",{type:"radio",name:"delivery",value:"local",checked:!xe,onChange:()=>X("local")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Keep it local"}),i.jsx("small",{children:"Changes stay in a saved working folder on this Mac. Nothing is pushed to GitHub."})]})]}),i.jsxs("label",{className:xe?"selected":"",children:[i.jsx("input",{type:"radio",name:"delivery",value:"publish",disabled:!te,checked:xe,onChange:()=>X("publish")}),i.jsxs("span",{children:[i.jsx("strong",{children:"Open a pull request"}),i.jsx("small",{children:te?"Jig commits the changes, pushes a branch, and opens a pull request with your GitHub login.":"Needs a GitHub project, such as github.com/owner/repo. A local folder can only keep changes local."})]})]})]}),Q&&i.jsx("div",{className:"notice continuation",role:"status",children:J?i.jsxs(i.Fragment,{children:[i.jsx("strong",{children:"Continuing:"})," ",J.title.split(` +`)[0],i.jsx("p",{className:"subtle",children:J.ref?`Starts from the earlier task's branch ${J.ref}, so its changes are included.`:J.keptLocal?"The earlier changes were kept local and never pushed, so this task starts from the project's latest commit without them. The earlier directive and result are passed along as context.":"This task starts from the project's latest commit. The earlier directive and result are passed along as context."})]}):"Loading the earlier task…"}),i.jsxs("details",{className:"goal-options",open:N!=="auto",children:[i.jsx("summary",{children:N==="auto"?"Add a goal or limits (optional)":"Your directive"}),i.jsx("label",{htmlFor:"task",children:N==="auto"?"3. Goal or limits (optional)":"3. What should Codex do?"}),i.jsx("textarea",{id:"task",required:N!=="auto",rows:5,maxLength:2e4,placeholder:N==="auto"?"Leave blank: agents inspect the project and choose one useful improvement. Or give a goal, such as make installation easier.":N==="ask"?"Explain what this project does and how I can use it.":"Describe the change you want and what a working result looks like.",value:x,onChange:W=>D(W.target.value)})]}),i.jsxs("details",{className:"evidence",children:[i.jsx("summary",{children:"Options"}),i.jsx("label",{htmlFor:"model",children:"Codex model"}),i.jsx("input",{id:"model",required:!0,value:Y,onChange:W=>C(W.target.value)}),N!=="ask"&&i.jsxs(i.Fragment,{children:[i.jsx("label",{htmlFor:"test-command",children:"Test command"}),i.jsx("input",{id:"test-command",placeholder:"Leave blank to detect the project's test command",value:$,onChange:W=>U(W.target.value)})]})]}),i.jsx(Oe,{error:Fe}),i.jsx(Oe,{error:r.error}),i.jsxs("div",{className:"start-row",children:[i.jsx("button",{className:"primary",type:"submit",disabled:fe||!De||!!r.error||!S.trim()||N!=="auto"&&!x.trim()||!Y.trim()||!!(Q&&!J),children:fe?"Starting…":"Start task"}),i.jsx("span",{className:"subtle",children:De?`Uses your signed-in Codex. ${xe?"Passing work becomes a pull request.":"Results stay local."}`:r.loading?"Checking Codex…":"Codex is offline. Check Workers before starting."})]}),i.jsxs("p",{className:"task-intent",children:[i.jsx("strong",{children:N==="ask"?"This task will return an answer.":"This task will change files in a separate working folder."})," ",N==="ask"?"Choose Make changes if you want Codex to implement something.":xe?"Your original project stays untouched; review and merge the pull request on GitHub.":"Your original project stays untouched. Nothing reaches GitHub unless you choose Open a pull request."]})]})]}),i.jsxs("aside",{className:"recent-work","aria-label":"Recent work",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("span",{className:"eyebrow",children:"IN THE FACTORY"}),i.jsx("h2",{children:"Recent tasks"})]}),i.jsx(Ae,{href:"/runs",children:"View all →"})]}),i.jsx(Oe,{error:d.error}),i.jsx("div",{className:"task-cards",children:(d.data??[]).slice(0,6).map(W=>i.jsx(Rs,{run:W},W.id))}),!d.loading&&d.data?.length===0&&i.jsx("p",{className:"subtle",children:"Your first task will appear here when you press Start."}),i.jsxs("div",{className:"loop-guide",children:[i.jsx("span",{className:"eyebrow",children:"THE AGENT LOOP"}),i.jsxs("div",{children:[i.jsx("span",{children:"01"}),i.jsx("strong",{children:"Plan"}),i.jsx("p",{children:"Find a useful change. Write the directive."})]}),i.jsxs("div",{children:[i.jsx("span",{children:"02"}),i.jsx("strong",{children:"Build"}),i.jsx("p",{children:"Turn the plan into working code."})]}),i.jsxs("div",{children:[i.jsx("span",{children:"03"}),i.jsx("strong",{children:"Verify"}),i.jsx("p",{children:"Run tests. Replan and repair if they fail."})]}),i.jsx("p",{className:"subtle",children:"Up to three repair rounds. You choose whether passing work stays local or becomes a pull request."})]})]})]})]})}function Rs({run:s}){const d=Ha(s)===eh?"Agent-led improvement":Ha(s).split(` +`)[0].replace(/^>\s*/,"");return i.jsxs("article",{className:`panel task-card task-card-${li(s)}`,children:[i.jsxs("div",{className:"task-card-meta",children:[i.jsx("span",{className:"task-project",children:s.targets.map(m=>Hn(m.repository)).join(", ")}),i.jsx(Bt,{state:li(s)})]}),i.jsx("h3",{children:i.jsx(Ae,{href:`/runs/${s.id}`,children:d})}),i.jsx("p",{className:"subtle",children:ai(s.created_at)}),i.jsx(Ae,{href:`/runs/${s.id}`,children:"Open task →"})]})}function sv({runs:s}){const d=Z.useCallback(()=>Me.queue(),[]),m=Mt(d,2e3,"board-queue"),r=$y(s,m.data?m.data.entries??[]:null);return i.jsxs(i.Fragment,{children:[i.jsx(Oe,{error:m.error}),i.jsx("div",{className:"board",children:r.map(S=>i.jsxs("section",{className:`board-column board-column-${S.id}`,"aria-labelledby":`board-${S.id}`,children:[i.jsxs("h2",{id:`board-${S.id}`,children:[S.label," ",i.jsx("span",{className:"board-count",children:S.runs.length})]}),S.runs.length===0?i.jsx("p",{className:"subtle board-empty",children:"Nothing here."}):S.runs.map(O=>i.jsx(Rs,{run:O},O.id))]},S.id))})]})}function fv(){const s=Z.useCallback(()=>Me.queue(),[]),{data:d,error:m,loading:r}=Mt(s,2e3,"queue"),S=Z.useCallback(()=>Me.fleet(),[]),O=Mt(S,3e3,"queue-workers");if(r&&!d)return i.jsx(Ga,{label:"Loading queue…"});if(!d)return i.jsx(Oe,{error:m});const x=d.entries??[];return i.jsxs("div",{className:"view",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:"Work queue"}),i.jsx("p",{className:"subtle",children:"Live work appears here. Completed and older runs are in Run history."}),i.jsxs("p",{className:"subtle",children:["Observed ",Ya(d.observed_at)]})]}),i.jsxs("div",{className:"counters",children:[i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.depth}),i.jsx("span",{className:"counter-label",children:"queued"})]}),i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.active_count}),i.jsx("span",{className:"counter-label",children:"running"})]})]})]}),i.jsx(Oe,{error:m}),i.jsxs("section",{className:"panel readiness","aria-label":"Worker readiness",children:[i.jsx("h2",{children:O.data?`${O.data.live_count} worker${O.data.live_count===1?"":"s"} online`:"Checking workers…"}),i.jsx("p",{children:O.data?.live_count?`Ready runtimes: ${(O.data.workers??[]).filter(D=>D.live).flatMap(D=>(D.runtimes??[]).map(N=>N.name)).join(", ")}. Jobs start when a compatible worker has a free slot.`:"Jobs need an online worker before they can start."}),i.jsx(Ae,{href:"/fleet",children:"View workers →"}),i.jsx(Oe,{error:O.error})]}),x.length===0?i.jsxs("section",{className:"panel",children:[i.jsx("h2",{children:"No work is running"}),i.jsx("p",{children:"The queue is empty. Opening an old run does not restart it."}),i.jsx("p",{children:i.jsx(Ae,{href:"/",children:"Start a new task →"})}),i.jsx(Ae,{href:"/runs",children:"Browse previous results →"})]}):i.jsxs("table",{className:"table",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"#"}),i.jsx("th",{children:"Repository"}),i.jsx("th",{children:"Definition"}),i.jsx("th",{children:"State"}),i.jsx("th",{children:"Attempt"}),i.jsx("th",{children:"Enqueued"})]})}),i.jsx("tbody",{children:x.map(D=>i.jsxs("tr",{children:[i.jsx("td",{children:D.position??"—"}),i.jsx("td",{children:i.jsx(Ae,{href:`/jobs/${D.job_id}`,children:D.repository})}),i.jsx("td",{children:D.definition??"—"}),i.jsx("td",{children:i.jsx(Bt,{state:D.state})}),i.jsx("td",{children:D.attempt?i.jsxs(i.Fragment,{children:["#",D.attempt.attempt_number," ",i.jsx(Bt,{state:D.attempt.state})]}):"—"}),i.jsx("td",{children:Ya(D.enqueued_at)})]},D.job_id))})]})]})}function rv(){try{return localStorage.getItem("jig-tasks-layout")==="board"?"board":"list"}catch{return"list"}}function ov(){const s=Z.useCallback(()=>Me.runs(),[]),{data:d,error:m,loading:r}=Mt(s,4e3,"runs"),[S,O]=Z.useState(rv),x=D=>{O(D);try{localStorage.setItem("jig-tasks-layout",D)}catch{}};return r&&!d?i.jsx(Ga,{label:"Loading runs…"}):d?i.jsxs("div",{className:"view",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:"My tasks"}),i.jsx("p",{className:"subtle",children:"Open a task to follow its progress or read the result."})]}),i.jsxs("div",{className:"layout-switch",role:"group","aria-label":"Layout",children:[i.jsx("button",{type:"button","aria-pressed":S==="list",onClick:()=>x("list"),children:"List"}),i.jsx("button",{type:"button","aria-pressed":S==="board",onClick:()=>x("board"),children:"Board"})]})]}),i.jsx(Oe,{error:m}),d.length===0?i.jsx(Ba,{title:"No tasks yet",detail:"Start a task from the New task page."}):S==="board"?i.jsx(sv,{runs:d}):i.jsx("div",{className:"task-cards",children:d.map(D=>i.jsx(Rs,{run:D},D.id))})]}):i.jsx(Oe,{error:m})}function Wd(s,d){return Ol(s.started_at)??d}function qa(s,d){const m=s.payload;if(!m||typeof m!="object")return;const r=m[d];return typeof r=="string"?r:void 0}function dv(s,d){const m=[...d].sort((R,X)=>R.seq-X.seq),r=Ol(s.started_at)??Ol(s.created_at)??0,S=m.length?Wd(m[0],r):r,O=Math.min(r||S,S),x=[],D=[],N=[],_=new Map;let Y=null,C=O;const $=R=>{Y&&Y.endMs===null&&(Y.endMs=Math.max(R,Y.startMs)),Y=null};for(const R of m){const X=Wd(R,C);C=Math.max(C,X);const Q=R.phase??"";switch(Y&&(Y.phase===Q||R.type==="phase_end")&&$(X),R.type){case"phase_start":{const J={key:`phase-${R.seq}`,label:Q,phase:Q,startMs:X,endMs:null,kind:"phase"};x.push(J),_.set(Q,J);break}case"phase_end":case"phase_death":{const J=_.get(Q);J&&(J.endMs=X,J.status=R.type==="phase_death"?"death":qa(R,"status")??"unknown",_.delete(Q)),R.type==="phase_death"&&N.push({key:`mark-${R.seq}`,label:"phase death",phase:Q,atMs:X,kind:"error",detail:qa(R,"cause")??qa(R,"error")});break}case"tool_call":{const J={key:`tool-${R.seq}`,label:R.name??"tool",phase:Q,startMs:X,endMs:null,kind:"tool"};D.push(J),Y=J;break}case"gate_pass":case"gate_fail":N.push({key:`mark-${R.seq}`,label:R.name??"gate",phase:Q,atMs:X,kind:R.type});break;case"handoff":N.push({key:`mark-${R.seq}`,label:"handoff",phase:Q,atMs:X,kind:"handoff",detail:qa(R,"summary")});break;case"error":N.push({key:`mark-${R.seq}`,label:R.name??"error",phase:Q,atMs:X,kind:"error",detail:qa(R,"error")??qa(R,"reason")});break}}const U=Ol(s.completed_at);if(U!==null){const R=Yn(s.result)?.phases?.slice().reverse()??[];$(Math.max(U,C));for(const X of _.values())X.endMs===null&&(X.endMs=Math.max(U,C)),X.status=R.find(Q=>Q.phase===X.phase)?.status??"stopped"}return{attemptId:s.id,attemptNumber:s.attempt_number,state:s.state,startMs:O,endMs:U,phases:x,tools:D,marks:N,eventCount:m.length}}function hv(s,d){if(s.endMs!==null)return Math.max(s.endMs,s.startMs+1);const m=Math.max(s.startMs,...s.phases.map(r=>r.endMs??r.startMs),...s.tools.map(r=>r.endMs??r.startMs),...s.marks.map(r=>r.atMs));return Math.max(d,m,s.startMs+1)}function Cs(s,d){return Math.max(0,(s.endMs??d)-s.startMs)}function th(s,d,m){const r=Math.max(1,m-d);return Math.min(100,Math.max(0,(s.startMs-d)/r*100))}function lh(s,d,m,r){const S=Math.max(1,m-d),O=Cs(s,r)/S*100;return Math.min(100,Math.max(1.5,O))}function Ms(s){const d=Yn(s.result),m=d?.publish,r=m&&typeof m=="object"?m.code:void 0;if(s.state==="queued")return{title:"Waiting for a worker",detail:"This attempt has not started.",next:"Check Workers for an online worker with the workflow's runtime and a free slot."};if(s.state==="preparing")return{title:"Preparing the repository",detail:"The worker is setting up an isolated worktree.",next:"Wait for the first phase to start; the page updates automatically."};if(s.state==="running")return{title:"Work is running",detail:"The worker is executing the workflow and its checks.",next:"Follow the current phase below. Failed checks can trigger the workflow's bounded repair loop."};if(s.state==="accepted")return{title:"Work accepted",detail:"This attempt passed Jig's acceptance checks.",next:"Review the agent's result and any published pull request below."};if(s.state==="accepted_unpublished")return d?.publish_hold?.startsWith('publish.hold_when "jig_ui_delivery != publish" held')&&(m==="held"||typeof m=="object"&&m?.state==="held")?{title:"Task complete · kept local",detail:"The task passed its checks. Any changes remain in the separate working folder on this Mac; nothing was pushed to GitHub.",next:"Read the result below. For a build task, review the saved changes before applying them, or start the task again with Open a pull request."}:r==="publish_empty_changeset"||s.error?.includes("(publish_empty_changeset)")?{title:"Checks passed · nothing to publish",detail:"The workflow passed its acceptance checks, but the worktree had no new commit to publish. Read-only assessments can legitimately produce no changes.",next:"Read the assessment below. If the task required edits, review why the builder produced no changes; retrying publication alone will not fix that."}:m==="held"||typeof m=="object"&&m?.state==="held"?{title:"Checks passed · awaiting review",detail:"The workflow deliberately held publication for human review.",next:"Review the result and retained worktree before releasing the publication hold."}:m==="not_attempted"&&!s.error?{title:"Checks passed · publication not attempted",detail:"The recorded result does not include a completed publication step.",next:"Read the result below; a direct run does not publish a branch or pull request."}:{title:"Checks passed · publication incomplete",detail:"The coding workflow passed, but delivery did not finish. The diagnostic below records where it stopped.",next:"Resolve the publication or CI problem before retrying publication; rerunning the coding workflow is a separate action."};if(s.state==="cancelled")return{title:"Work cancelled",detail:"This attempt stopped without an accepted result.",next:"Inspect the recorded work before submitting a new task."};if(s.state==="lost")return{title:"Worker connection lost",detail:"Jig stopped receiving the worker's heartbeat.",next:"Check Workers and the retained worktree. Retry the failed job once the worker is available."};if(s.error?.includes("outside its write allowlist"))return{title:"Stopped at the write boundary",detail:"The agent modified a path the workflow did not allow. Jig stopped the attempt; the diagnostic records its rollback result.",next:"For a read-only task, remove commands that write caches or files. For an editing task, check the permitted paths before submitting a revised workflow."};const S=d?.phases?.slice().reverse().find(O=>O.status==="fail");return{title:S?`Stopped in ${S.phase}`:"Work did not pass",detail:"The attempt did not meet Jig's acceptance requirements. Inspect the diagnostic and failed checks below.",next:"Fix the cause before retrying. A retry uses the same frozen workflow; prompt, model, or workflow changes require a new run."}}function mv({lane:s,nowMs:d,onSelectPhase:m}){const r=hv(s,d),S=Math.max(1,r-s.startMs),O=s.endMs===null;return i.jsxs("section",{className:"lane","aria-label":`attempt ${s.attemptNumber} swim lane`,children:[i.jsxs("header",{className:"lane-header",children:[i.jsxs("h3",{children:["Attempt ",s.attemptNumber]}),i.jsx(Bt,{state:s.state}),i.jsxs("span",{className:"lane-meta",children:[Wl(S)," · ",s.eventCount," events",O?" · live":""]})]}),s.phases.length===0&&s.tools.length===0?i.jsx("p",{className:"lane-empty",children:"No trace events for this attempt yet."}):i.jsxs(i.Fragment,{children:[i.jsxs("div",{className:"lane-track",role:"list","aria-label":"phases",children:[s.phases.map(x=>i.jsx(yv,{span:x,startMs:s.startMs,endMs:r,nowMs:d,onSelect:m},x.key)),s.marks.map(x=>i.jsx(vv,{mark:x,startMs:s.startMs,endMs:r},x.key))]}),s.tools.length>0&&i.jsxs("details",{className:"evidence",open:O,children:[i.jsxs("summary",{children:["Tool activity · ",s.tools.length," calls"]}),i.jsx("ol",{className:"tool-list","aria-label":`attempt ${s.attemptNumber} tool calls`,children:s.tools.map(x=>i.jsx(pv,{span:x,startMs:s.startMs,endMs:r,nowMs:d},x.key))})]})]})]})}function yv({span:s,startMs:d,endMs:m,nowMs:r,onSelect:S}){const O=Wl(Cs(s,r)),x=s.status??"running";return i.jsxs("button",{type:"button",role:"listitem",className:`phase-block phase-${x}`,style:{left:`${th(s,d,m)}%`,width:`${lh(s,d,m,r)}%`},"aria-label":`phase ${s.label}, ${x}, ${O}`,onClick:()=>S?.(s.phase),children:[i.jsx("span",{className:"phase-name",children:s.label}),i.jsx("span",{className:"phase-duration",children:O})]})}function vv({mark:s,startMs:d,endMs:m}){const r=Math.max(1,m-d),S=Math.min(100,Math.max(0,(s.atMs-d)/r*100));return i.jsx("span",{className:`mark mark-${s.kind}`,style:{left:`${S}%`},title:`${s.label}${s.detail?`: ${s.detail}`:""} (${Ya(new Date(s.atMs).toISOString())})`,"aria-label":`${s.kind.replace("_"," ")} ${s.label}`})}function pv({span:s,startMs:d,endMs:m,nowMs:r}){const S=s.endMs===null,O=Wl(Cs(s,r));return i.jsxs("li",{className:"tool-row",children:[i.jsx("span",{className:"tool-name",children:s.label}),i.jsx("span",{className:"tool-track",children:i.jsx("span",{className:S?"tool-span tool-running":"tool-span",style:{marginLeft:`${th(s,d,m)}%`,width:`${lh(s,d,m,r)}%`}})}),i.jsxs("span",{className:"tool-duration",children:[O,S?" (running)":""]})]})}function gv({runID:s}){const d=Z.useCallback(()=>Me.run(s),[s]),{data:m,error:r,loading:S}=Mt(d,3e3,`run:${s}`),O=Id();if(S&&!m)return i.jsx(Ga,{label:"Loading run…"});if(!m)return i.jsx(Oe,{error:r});const x=Object.entries(m.run.parameters??{});return i.jsxs("div",{className:"view",children:[i.jsxs("p",{children:[i.jsx(Ae,{href:"/",children:"← New task"})," · ",i.jsx(Ae,{href:"/runs",children:"My tasks"})]}),i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:m.run.targets.map(D=>Hn(D.repository)).join(", ")}),i.jsxs("p",{className:"subtle",children:[m.run.targets.map(D=>Hn(D.repository)).join(", ")," · ",ai(m.run.created_at)]})]}),i.jsx(Bt,{state:li(m.run)})]}),i.jsx(Oe,{error:r}),i.jsxs("section",{className:"panel directive",children:[i.jsx("h2",{children:m.run.parameters?.task_mode==="auto"?"Agents choose the directive":m.run.parameters?.task_mode==="build"?"Directive · make changes":"Question · get an answer"}),i.jsxs("details",{open:Ha(m.run).length<=250,children:[i.jsx("summary",{children:"View your instructions"}),i.jsx("p",{children:Ha(m.run)})]}),i.jsx("p",{className:"subtle",children:m.run.parameters?.task_mode==="auto"||m.run.parameters?.task_mode==="build"?"Agents plan, build, and test automatically. Failed tests return to planning for up to three repair rounds. Changes stay in the saved working folder.":"Codex reads this project and returns an answer. This task does not implement the recommendations."})]}),x.length>0&&i.jsxs("details",{className:"evidence",children:[i.jsx("summary",{children:"Task settings"}),i.jsx("dl",{className:"parameters",children:x.map(([D,N])=>i.jsxs("div",{children:[i.jsx("dt",{children:D}),i.jsx("dd",{children:N})]},D))})]}),m.jobs.length>1&&i.jsxs("section",{className:"panel","aria-label":"Run overview",children:[i.jsxs("h2",{children:[m.jobs.length," repositories"]}),i.jsxs("p",{children:[m.jobs.filter(D=>D.state==="active").length," running · ",m.jobs.filter(D=>D.state==="queued").length," waiting · ",m.jobs.filter(D=>D.state==="failed").length," failed · ",m.jobs.filter(D=>D.state==="accepted_unpublished").length," unpublished"]}),i.jsx("p",{className:"subtle",children:"Acceptance checks verify the workflow. Read each agent's assessment to see its conclusion about the repository."}),i.jsx("ul",{className:"repository-list",children:m.jobs.map(D=>i.jsxs("li",{children:[i.jsx("a",{href:`#job-${D.id}`,children:D.repository})," · ",i.jsx(Bt,{state:D.state})]},D.id))})]}),m.jobs.length===0?i.jsx(Ba,{title:"No jobs",detail:"This run admitted no targets."}):m.jobs.map(D=>i.jsx(ah,{jobID:D.id,nowMs:O,compact:!0,taskMode:m.run.parameters?.task_mode==="auto"?"auto":m.run.parameters?.task_mode==="build"?"build":m.run.parameters?.task_mode==="ask"?"ask":void 0},D.id))]})}function bv({jobID:s}){const d=Id();return i.jsx("div",{className:"view",children:i.jsx(ah,{jobID:s,nowMs:d,standalone:!0,compact:!0})})}function ah({jobID:s,nowMs:d,standalone:m=!1,compact:r=!1,taskMode:S}){const O=Z.useCallback(()=>Me.job(s),[s]),{data:x,error:D,loading:N,refresh:_}=Mt(O,3e3,`job:${s}`),[Y,C]=Z.useState(null),[$,U]=Z.useState(!1),R=async F=>{U(!0);try{F==="retry"?await Me.retryJob(s):await Me.cancelJob(s),C(null),_()}catch(fe){C(fe)}finally{U(!1)}};if(N&&!x)return i.jsx(Ga,{label:"Loading job…"});if(!x)return i.jsx(Oe,{error:D});const X=x.attempts??[],Q=X.at(-1),J=Q&&Ms(Q).title==="Task complete · kept local";return i.jsxs("section",{className:"panel",id:`job-${s}`,children:[i.jsxs("header",{className:"panel-header",children:[i.jsxs("div",{children:[i.jsx("h2",{children:r?Hn(x.job.repository):x.job.repository}),r&&i.jsx("p",{className:"subtle",children:x.job.repository}),!r&&i.jsxs("p",{className:"subtle",children:[x.definition?`${x.definition} · `:"","base ",x.job.base_sha.slice(0,12)," ·"," ",m?i.jsxs(Ae,{href:`/runs/${x.run_id}`,children:["run ",As(x.run_id)]}):i.jsxs(Ae,{href:`/jobs/${x.job.id}`,children:["job ",As(x.job.id)]})]})]}),i.jsxs("div",{className:"panel-actions",children:[i.jsx(Bt,{state:J?S==="ask"?"complete":"ready":x.job.state}),x.job.state==="failed"&&i.jsx("button",{type:"button",disabled:$,onClick:()=>{R("retry")},children:"Retry same workflow"}),["queued","active"].includes(x.job.state)&&i.jsx("button",{type:"button",disabled:$||x.job.cancellation_requested,onClick:()=>{R("cancel")},children:x.job.cancellation_requested?"Cancellation requested":"Cancel"})]})]}),i.jsx(Oe,{error:Y}),i.jsx(Oe,{error:D}),X.length>1&&i.jsxs("details",{className:"evidence",children:[i.jsxs("summary",{children:["Compare ",X.length," attempts"]}),i.jsxs("table",{className:"table",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"Attempt"}),i.jsx("th",{children:"Runtime"}),i.jsx("th",{children:"Outcome"}),i.jsx("th",{children:"Started"})]})}),i.jsx("tbody",{children:X.map(F=>i.jsxs("tr",{children:[i.jsxs("td",{children:["#",F.attempt_number]}),i.jsx("td",{children:F.runtime_name??"Not recorded"}),i.jsx("td",{children:Ms(F).title}),i.jsx("td",{children:ai(F.started_at??F.created_at)})]},F.id))})]}),i.jsx("p",{className:"subtle",children:"A different outcome is evidence to inspect, not proof of better quality. Each attempt's checks and results remain below."})]}),x.worktree&&i.jsxs("p",{className:"notice",children:[r?"Saved working folder: ":"Worktree retained at ",i.jsx("code",{children:x.worktree.path}),!r&&i.jsxs(i.Fragment,{children:[" — ",x.worktree.reason," ",i.jsx(Ae,{href:"/worktrees",children:"release it"})]})]}),(x.publish??[]).length>0&&i.jsx("ul",{className:"publish",children:(x.publish??[]).map(F=>i.jsxs("li",{children:[i.jsx("strong",{children:F.step})," ",F.branch,F.pr_url?i.jsxs(i.Fragment,{children:[" ",i.jsx("a",{href:F.pr_url,rel:"noreferrer noopener",target:"_blank",children:"pull request"})]}):null]},`${F.attempt_id}-${F.step}`))}),X.length===0?i.jsx(Ba,{title:"No attempts yet",detail:"This job is waiting for a worker to claim it."}):X.map(F=>i.jsx(jv,{attempt:F,nowMs:d,compact:r,taskMode:S},F.id)),r&&Q&&al(Q.state)&&i.jsxs("section",{className:"next-action",children:[i.jsx("h3",{children:"What next?"}),i.jsx("p",{children:S==="ask"?"Turn a recommendation into work. Write one clear change you want Codex to make.":"Review the result and saved working folder above. You can also give Codex a new directive."}),i.jsxs("p",{children:[i.jsx(Ae,{href:`/?project=${encodeURIComponent(x.job.repository)}&mode=build&continue=${encodeURIComponent(x.run_id)}`,children:"Continue from this result →"})," ",i.jsx("span",{className:"subtle",children:"Passes this task's directive and result to the next one."})]}),i.jsx(Ae,{href:`/?project=${encodeURIComponent(x.job.repository)}&mode=build`,children:"Make changes to this project →"}),i.jsx("span",{children:" · "}),i.jsx(Ae,{href:`/?project=${encodeURIComponent(x.job.repository)}&mode=ask`,children:"Ask another question →"}),i.jsx("p",{children:i.jsx(Ae,{href:`/?project=${encodeURIComponent(x.job.repository)}&mode=auto`,children:"Let agents choose the next improvement →"})})]})]})}function jv({attempt:s,nowMs:d,compact:m=!1,taskMode:r}){const{events:S,error:O}=wy(s.id,s.state),x=Z.useMemo(()=>dv(s,S),[s,S]),[D,N]=Z.useState(null),_=Ms(s),Y=al(s.state)?void 0:x.phases.slice().reverse().find(k=>k.endMs===null),C=Yn(s.result)?.phases??[],$=r?lv[r]:[...new Set(x.phases.map(k=>k.phase))],U=i.jsx(mv,{lane:x,nowMs:d,onSelectPhase:N}),R=S.filter(k=>!["keep-local","deliver"].includes(k.phase??"")&&(k.type==="tool_call"||k.type==="log"&&["agent_text","repair_edge","repair_exhausted"].includes(k.name??"")||["phase_start","phase_end","gate_fail","error"].includes(k.type))).slice(-6),X=S.at(-1),Q=S.slice().reverse().find(k=>k.type==="handoff"&&k.phase==="plan"),J=Q?.payload&&typeof Q.payload=="object"&&"summary"in Q.payload&&typeof Q.payload.summary=="string"?Q.payload.summary:null,F=S.slice().reverse().find(k=>k.type==="log"&&k.name==="agent_text"),fe=F?.payload&&typeof F.payload=="object"&&"text"in F.payload&&typeof F.payload.text=="string"?F.payload.text:null;return i.jsxs("div",{className:"attempt",children:[i.jsxs("section",{className:`outcome outcome-${s.state}`,"aria-label":`Attempt ${s.attempt_number} outcome`,children:[i.jsx("h3",{children:m&&_.title==="Task complete · kept local"?r==="ask"?"Your answer is ready":"Changes are ready to review":_.title}),i.jsxs("p",{children:[Y?`Current phase: ${Y.label}. `:"",_.detail]}),i.jsxs("p",{children:[i.jsx("strong",{children:"Next step:"})," ",_.next]}),i.jsxs("p",{className:"subtle",children:["Attempt ",s.attempt_number," · ",s.runtime_name??"Runtime not recorded"," · ",ai(s.started_at??s.created_at)]}),m&&i.jsxs("p",{className:"subtle",children:[Wl((s.completed_at?Date.parse(s.completed_at):d)-Date.parse(s.started_at??s.created_at))," elapsed",X?.started_at&&!al(s.state)?` · Last activity ${Wl(Math.max(0,d-Date.parse(X.started_at)))} ago`:""]}),m&&!al(s.state)&&fe&&i.jsx("p",{className:"agent-message",children:fe})]}),m?i.jsxs(i.Fragment,{children:[r==="auto"&&J&&i.jsxs("section",{className:"directive",children:[i.jsx("h3",{children:"Agent's directive"}),i.jsx("p",{children:J}),i.jsx("p",{className:"subtle",children:"The builder receives the full plan automatically. No input is needed here."})]}),i.jsx("ol",{className:"task-steps","aria-label":"Task progress",children:$.map(k=>{const Fe=x.phases.slice().reverse().find(De=>De.phase===k),te=C.slice().reverse().find(De=>De.phase===k)?.status??Fe?.status??(Fe?.endMs===null?"running":al(s.state)?"not run":"waiting"),xe=x.phases.filter(De=>De.phase===k).length;return i.jsxs("li",{children:[i.jsxs("span",{children:[k==="scout"?"Read project":k,xe>1?` · round ${xe}`:""]}),i.jsx(Bt,{state:te})]},k)})}),i.jsxs("details",{className:"activity","aria-label":"Recent activity",open:!al(s.state),children:[i.jsx("summary",{children:al(s.state)?"Activity history":"Live activity"}),R.length===0?i.jsx("p",{className:"subtle",children:"Waiting for the worker's first activity. This page checks for updates automatically."}):i.jsx("ol",{children:R.map(k=>i.jsxs("li",{children:[i.jsx("time",{children:Ya(k.started_at)}),i.jsx("span",{children:k.type==="tool_call"?`Codex used ${k.name??"a tool"}`:k.type==="phase_start"?`Started ${k.phase==="scout"?"reading the project":k.phase}`:k.type==="phase_end"?`Finished ${k.phase==="scout"?"reading the project":k.phase}`:k.name==="agent_text"?"Codex sent a progress update":k.name==="repair_edge"?"Check failed → agents are repairing and retesting automatically":k.name==="repair_exhausted"?"Repair limit reached; see the diagnostic":k.type==="gate_fail"?"A check failed; inspect the workflow's repair activity":"Worker reported an error"})]},k.seq))})]}),i.jsxs("details",{className:"evidence",children:[i.jsx("summary",{children:"Technical activity"}),U]})]}):U,D&&i.jsx("button",{type:"button",onClick:()=>N(null),children:"Clear phase filter"}),i.jsx(Oe,{error:O}),i.jsx(Sv,{attempt:s,openPhase:D,compact:m})]})}function Sv({attempt:s,openPhase:d,compact:m=!1}){const r=al(s.state),S=Z.useCallback(()=>Me.attemptGates(s.id),[s.id]),O=Z.useCallback(()=>Me.attemptEnvelopes(s.id),[s.id]),x=Mt(S,r?0:5e3,`gates:${s.id}:${s.state}`),D=Mt(O,r?0:5e3,`envelopes:${s.id}:${s.state}`),N=Z.useMemo(()=>Yn(s.result),[s.result]),_=N?.phases??[],Y=_.map(U=>{const R=U.envelope;return U.kind!=="code"&&R!==null&&typeof R=="object"&&"summary"in R&&typeof R.summary=="string"}).lastIndexOf(!0),C=(x.data??[]).filter(U=>!d||U.phase===d),$=(D.data??[]).filter(U=>!d||U.phase===d);return!s.result&&C.length===0&&$.length===0&&!s.error&&!x.error&&!D.error?null:i.jsxs(i.Fragment,{children:[m&&N&&i.jsxs("section",{className:"result-facts","aria-label":"Result facts",children:[i.jsx("h3",{children:N.changed_paths?.length?"Changed files":"Files changed"}),N.changed_paths?.length?i.jsx("ul",{children:N.changed_paths.map(U=>i.jsx("li",{children:i.jsx("code",{children:U})},U))}):i.jsx("p",{children:"No file changes recorded."}),i.jsx("h3",{children:"Verification"}),i.jsxs("p",{children:[_.some(U=>U.phase==="test"&&U.status==="success")?"Test command passed.":_.some(U=>U.phase==="test"&&U.status==="fail")?"Test command failed. Review the diagnostic below.":"No test command result recorded."," ",N.acceptance?.passed===!0?"Workflow checks passed.":N.acceptance?.passed===!1?"Workflow checks did not pass.":""]})]}),_.map((U,R)=>{const X=U.envelope,Q=X&&typeof X=="object"?X:{},J="summary"in Q?Q.summary:null;if(typeof J!="string")return null;const F=i.jsxs("section",{className:"report",children:[i.jsx("h4",{children:m&&R===Y?"Result":`${U.phase} · result`}),"approved"in Q&&typeof Q.approved=="boolean"&&i.jsx("p",{children:i.jsxs("strong",{children:["Agent assessment: ",Q.approved?"Approved":"Not approved"]})}),i.jsx("p",{className:"report-text",children:J}),"blocking"in Q&&Array.isArray(Q.blocking)&&Q.blocking.length>0&&i.jsx("ul",{className:"checks",children:Q.blocking.filter(fe=>typeof fe=="string").map((fe,k)=>i.jsx("li",{children:fe},k))})]},`${U.phase}-${U.phase_attempt}`);return m&&R!==Y?i.jsxs("details",{className:"evidence",children:[i.jsxs("summary",{children:[U.kind==="code"?"Check":"Earlier step",": ",U.phase]}),F]},`${U.phase}-${U.phase_attempt}`):F}),s.error&&i.jsx("p",{className:"attempt-error",role:"alert",children:s.error}),i.jsx(Oe,{error:x.error}),i.jsx(Oe,{error:D.error}),s.result&&!N&&i.jsxs("details",{className:"evidence",children:[i.jsx("summary",{children:"Unrecognized result · view original record"}),i.jsx("pre",{children:s.result})]}),i.jsxs("details",{className:"evidence",open:d!==null,children:[i.jsxs("summary",{children:["Evidence",d?` · ${d}`:""," — ",C.length," gate check",C.length===1?"":"s",$.length>0?`, ${$.length} invalid emission`:""]}),(N?.acceptance?.checks??[]).length>0&&i.jsxs(i.Fragment,{children:[i.jsx("h4",{children:"Acceptance checks"}),i.jsx("ul",{className:"checks",children:N?.acceptance?.checks?.map((U,R)=>i.jsxs("li",{className:U.ok?"ok":"not-ok",children:[U.ok?"Pass":"Fail"," · ",U.item,": ",U.note]},R))})]}),_.filter(U=>!d||U.phase===d).map(U=>i.jsx(xv,{phase:U},`${U.phase}-${U.phase_attempt}`)),C.length>0&&i.jsxs("table",{className:"gates",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"Phase"}),i.jsx("th",{children:"Gate"}),i.jsx("th",{children:"Item"}),i.jsx("th",{children:"Result"}),i.jsx("th",{children:"Note"})]})}),i.jsx("tbody",{children:C.map((U,R)=>i.jsxs("tr",{children:[i.jsx("td",{children:U.phase}),i.jsx("td",{children:U.gate}),i.jsx("td",{children:U.item}),i.jsx("td",{className:U.ok?"ok":"not-ok",children:U.ok?"pass":"fail"}),i.jsx("td",{children:U.note})]},`${U.phase}-${U.gate}-${U.item}-${R}`))})]}),$.map(U=>i.jsxs("div",{className:"invalid-envelope",children:[i.jsxs("h4",{children:["Invalid emission · ",U.phase," · seq ",U.emission]}),i.jsx("p",{className:"subtle",children:U.parse_error}),i.jsx("pre",{children:U.body}),i.jsx("p",{className:"subtle",children:"Stored capped; the complete emission is in this attempt's JSONL trace."})]},`${U.phase}-${U.emission}`))]})]})}function xv({phase:s}){const d=s.started_at?Date.parse(s.started_at):null,m=s.ended_at?Date.parse(s.ended_at):null;return i.jsxs("div",{className:"envelope",children:[i.jsxs("h4",{children:[s.phase," ",i.jsx("span",{className:`badge badge-${s.status}`,children:s.status}),d&&m?i.jsxs("span",{className:"subtle",children:[" · ",Wl(m-d)]}):null]}),s.envelope?i.jsx("pre",{children:JSON.stringify(s.envelope,null,2)}):i.jsx("p",{className:"subtle",children:"No envelope recorded for this phase."}),(s.gates?.checks??[]).length>0&&i.jsx("ul",{className:"checks",children:(s.gates?.checks??[]).map((r,S)=>i.jsxs("li",{className:r.ok?"ok":"not-ok",children:[r.item,": ",r.note??(r.ok?"ok":"failed")]},`${r.item}-${S}`))})]})}function _v(){const s=Z.useCallback(()=>Me.worktrees(),[]),{data:d,error:m,loading:r,refresh:S}=Mt(s,5e3,"worktrees"),[O,x]=Z.useState(null),[D,N]=Z.useState(null),_=async Y=>{try{await Me.releaseWorktree(Y),N(null),x(null),S()}catch(C){N(C)}};return r&&!d?i.jsx(Ga,{label:"Loading worktrees…"}):d?i.jsxs("div",{className:"view",children:[i.jsxs("header",{className:"view-header",children:[i.jsxs("div",{children:[i.jsx("h1",{children:"Retained worktrees"}),i.jsx("p",{className:"subtle",children:"Kept because publish could not be proven. Inspect the path, then release."})]}),i.jsx("div",{className:"counters",children:i.jsxs("div",{className:"counter",children:[i.jsx("span",{className:"counter-value",children:d.length}),i.jsx("span",{className:"counter-label",children:"retained"})]})})]}),i.jsx(Oe,{error:m}),i.jsx(Oe,{error:D}),d.length===0?i.jsx(Ba,{title:"Nothing retained",detail:"Every attempt's worktree was disposed cleanly."}):i.jsxs("table",{className:"table",children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{children:"Repository"}),i.jsx("th",{children:"Path"}),i.jsx("th",{children:"Reason"}),i.jsx("th",{children:"Attempt"}),i.jsx("th",{children:"Since"}),i.jsx("th",{})]})}),i.jsx("tbody",{children:d.map(Y=>i.jsxs("tr",{children:[i.jsx("td",{children:Y.repository}),i.jsx("td",{children:i.jsx("code",{children:Y.path})}),i.jsx("td",{children:Y.reason}),i.jsx("td",{children:i.jsx(Ae,{href:`/jobs/${Y.attempt_id}`,children:As(Y.attempt_id)})}),i.jsx("td",{children:Ya(Y.created_at)}),i.jsx("td",{children:O===Y.attempt_id?i.jsxs("span",{className:"confirm",children:[i.jsx("button",{type:"button",onClick:()=>{_(Y.attempt_id)},children:"Confirm release"}),i.jsx("button",{type:"button",onClick:()=>x(null),children:"Keep"})]}):i.jsx("button",{type:"button",onClick:()=>x(Y.attempt_id),children:"Release…"})})]},Y.attempt_id))})]})]}):i.jsx(Oe,{error:m})}function Tv(){const s=ky();return i.jsxs("div",{className:"app",children:[i.jsxs("nav",{className:"nav","aria-label":"Main navigation",children:[i.jsxs("span",{className:"brand",children:["jig",i.jsx("span",{className:"brand-caption",children:"software factory"})]}),i.jsx("span",{className:"nav-caption",children:"WORKSPACE"}),i.jsxs(Ae,{href:"/",current:s.name==="tasks",children:[i.jsx("span",{"aria-hidden":"true",children:"+"})," New task"]}),i.jsxs(Ae,{href:"/runs",current:["runs","run","job"].includes(s.name),children:[i.jsx("span",{"aria-hidden":"true",children:"▦"})," My tasks"]}),i.jsxs("details",{className:"nav-tools",children:[i.jsx("summary",{children:"Tools"}),i.jsx(Ae,{href:"/queue",current:s.name==="queue",children:"Work queue"}),i.jsx(Ae,{href:"/fleet",current:s.name==="fleet",children:"Workers"}),i.jsx(Ae,{href:"/worktrees",current:s.name==="worktrees",children:"Saved worktrees"})]}),i.jsxs("div",{className:"nav-footer",children:[i.jsx("span",{className:"nav-caption",children:"LOCAL BY DESIGN"}),i.jsxs("p",{children:["Your projects.",i.jsx("br",{}),"Your Codex.",i.jsx("br",{}),"Your next move."]})]})]}),i.jsxs("main",{children:[s.name==="tasks"&&i.jsx(cv,{}),s.name==="queue"&&i.jsx(fv,{}),s.name==="runs"&&i.jsx(ov,{}),s.name==="run"&&i.jsx(gv,{runID:s.id}),s.name==="job"&&i.jsx(bv,{jobID:s.id}),s.name==="worktrees"&&i.jsx(_v,{}),s.name==="fleet"&&i.jsx(Vy,{}),s.name==="unknown"&&i.jsx(Ba,{title:"No such view",detail:`Nothing is served at ${s.path}.`})]})]})}Hy.createRoot(document.getElementById("root")).render(i.jsx(Z.StrictMode,{children:i.jsx(Tv,{})})); diff --git a/web/dist/index.html b/web/dist/index.html index 6ee6388..522a5da 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -6,7 +6,7 @@ jig - + diff --git a/web/src/polling.test.ts b/web/src/polling.test.ts new file mode 100644 index 0000000..aba5d9b --- /dev/null +++ b/web/src/polling.test.ts @@ -0,0 +1,45 @@ +import { act, renderHook } from "@testing-library/react"; +import { afterEach, expect, it, vi } from "vitest"; +import { usePolled } from "./polling"; + +afterEach(() => vi.useRealTimers()); + +it("waits for a slow request before polling again", async () => { + vi.useFakeTimers(); + let finish!: (value: string) => void; + const load = vi.fn(() => new Promise((resolve) => { finish = resolve; })); + const { result } = renderHook(() => usePolled(load, 1000, "slow")); + await act(async () => { vi.advanceTimersByTime(3000); }); + expect(load).toHaveBeenCalledTimes(1); + await act(async () => { finish("first result"); }); + expect(result.current.data).toBe("first result"); + await act(async () => { vi.advanceTimersByTime(1000); }); + expect(load).toHaveBeenCalledTimes(2); + await act(async () => { finish("new result"); }); + expect(result.current.data).toBe("new result"); +}); + +it("resumes polling after a failed request", async () => { + vi.useFakeTimers(); + const failure = new Error("offline"); + const load = vi.fn().mockRejectedValueOnce(failure).mockResolvedValueOnce("recovered"); + const { result } = renderHook(() => usePolled(load, 1000, "recovery")); + await act(async () => {}); + expect(result.current.error).toBe(failure); + await act(async () => { vi.advanceTimersByTime(1000); }); + expect(result.current.data).toBe("recovered"); + expect(result.current.error).toBeNull(); +}); + +it("ignores a pending response after changing the resource", async () => { + let finishOld!: (value: string) => void; + const old = () => new Promise((resolve) => { finishOld = resolve; }); + const current = async () => "current resource"; + const { result, rerender } = renderHook(({ key, load }) => usePolled(load, 0, key), { + initialProps: { key: "old", load: old }, + }); + rerender({ key: "current", load: current }); + await act(async () => {}); + await act(async () => { finishOld("old resource"); }); + expect(result.current.data).toBe("current resource"); +}); diff --git a/web/src/polling.ts b/web/src/polling.ts index 771a3d1..065e323 100644 --- a/web/src/polling.ts +++ b/web/src/polling.ts @@ -63,7 +63,10 @@ export function usePolled(load: () => Promise, intervalMs: number, key: st useEffect(() => { let cancelled = false; + let inFlight = false; const run = async () => { + if (inFlight) return; + inFlight = true; try { const value = await loadRef.current(); if (cancelled) return; @@ -72,6 +75,7 @@ export function usePolled(load: () => Promise, intervalMs: number, key: st } catch (failure) { if (!cancelled) setError(failure as Error); } finally { + inFlight = false; if (!cancelled) setLoading(false); } };