pantheon-opencode 1.5.0-beta.10 → 1.5.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -18,6 +18,50 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
18
18
 
19
19
  ## ✅ Closed Issues
20
20
 
21
+ ## [v1.5.0-beta.12] - 2026-09-14
22
+
23
+ <!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
24
+ move this section to a versioned entry and reset the template below. -->
25
+
26
+ ## 🆕 What's New
27
+
28
+ - **TUI lê o board (4º canal):** o painel Delegations passa a ler o
29
+ BackgroundJobBoard via `readBoardState()` — jobs `pantheon_delegate` de todas
30
+ as sessões aparecem, não só os filhos nativos da sessão focada.
31
+ - **Toggle [Sessão]/[Tudo] + chips:** `[Sessão]` (default) mostra só a sessão
32
+ focada, `[Tudo]` mostra jobs de todas as sessões; chips clicáveis no header.
33
+ - **Raw `dist/tui.tsx` removido (bundle-only):** o dist passa a carregar só o
34
+ bundle compilado (`tui.js`); o fonte raw sai do pacote publicado.
35
+ - **117 testes TUI delegations:** `tests/pantheon/tui-delegations.test.ts` com
36
+ 117/117 passando, cobrindo board-read, split ativo/recente e toggle de escopo.
37
+ ## [v1.5.0-beta.11] - 2026-09-14
38
+
39
+ <!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
40
+ move this section to a versioned entry and reset the template below. -->
41
+
42
+ ## 🆕 What's New
43
+
44
+ - **Glyphs da FSM real no painel Delegations:** cada estado do BackgroundJobBoard
45
+ tem agora um glifo Unicode geométrico próprio — `⠋` running (spinner 1s),
46
+ `⟳` retry, `⚠` stale/startup, `✓` completed, `✕` error, `−` cancelled. Forma e
47
+ cor são canais independentes: as linhas seguem legíveis sem cor e sem Nerd Font.
48
+ - **Prefixo `nat:` / `pan:` documentado:** `docs/INSTALLATION.md` passa a
49
+ descrever os prefixos curtos das linhas nativas (`nat:<agent>`) e do board
50
+ (`pan:<alias>`) e o par de glyphs ◇/◆.
51
+ - **`scripts/dev-tui.sh` (dev local sem publish):** instala, builda e registra o
52
+ caminho absoluto do repo em `.opencode/tui.json` (gitignored) com hint de
53
+ restart — sem tocar `opencode.json` e sem publicar.
54
+ - **104 testes TUI delegations:** `tests/pantheon/tui-delegations.test.ts` com
55
+ 104/104 passando, cobrindo glifos/marker/tone dos estados reais da FSM.
56
+
57
+ ## 🐞 Fixed
58
+
59
+ - **Doctor F.2 (`hasUsableScripts`):** a resolução do diretório code-mode agora
60
+ exige um `.py`/`.sh` regular (paridade com `_has_usable_scripts` do MCP), então
61
+ um overlay de projeto vazio não mascara mais uma instalação que traz scripts.
62
+ - **`publish:next` órfão removido:** nenhum workflow usava o script (o release
63
+ publica via `--tag beta`); removido do `package.json` para eliminar o dist-tag
64
+ `next` obsoleto da linha de publicação.
21
65
  ## [v1.5.0-beta.10] - 2026-09-14
22
66
 
23
67
  &lt;!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pantheon-opencode",
3
- "version": "1.5.0-beta.10",
3
+ "version": "1.5.0-beta.12",
4
4
  "description": "Multi-agent orchestration for OpenCode — 14 specialized agents, TDD, Themis review gates.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -31,7 +31,6 @@
31
31
  "release:dry-run": "node scripts/versioning.mjs status && node scripts/release-notes.mjs && node scripts/package-evidence.mjs",
32
32
  "package:evidence": "node scripts/package-evidence.mjs",
33
33
  "package:validate": "node scripts/validate-package.mjs",
34
- "publish:next": "npm publish --tag next --access public",
35
34
  "lint": "biome ci .",
36
35
  "typecheck": "tsc --noEmit",
37
36
  "audit": "npm audit --audit-level=high",
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pantheon",
3
3
  "publisher": "ils15",
4
- "version": "1.5.0-beta.10",
4
+ "version": "1.5.0-beta.12",
5
5
  "displayName": "Pantheon",
6
6
  "description": "Conductor-Delegate orchestration platform with 14 specialized agents, 21 skills, and OpenCode support.",
7
7
  "agents": "./src/agents",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.backends._legacy:_Backend"
4
4
 
5
5
  [project]
6
6
  name = "pantheon"
7
- version = "1.5.0-beta.10"
7
+ version = "1.5.0-beta.12"
8
8
  description = "Multi-agent orchestration framework"
9
9
  requires-python = ">=3.11"
10
10
  dependencies = []
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+ # dev-tui.sh — load the Pantheon TUI from the repo (src/plugins/tui) WITHOUT publishing.
3
+ #
4
+ # Flow: build the bundle → register the repo's absolute path in
5
+ # .opencode/tui.json (read by the OpenCode TUI loader) → restart hint.
6
+ # It deliberately does NOT touch opencode.json: that file is packaged and
7
+ # merged into user configs by the installer, so a repo-relative path would
8
+ # leak into third-party installs and break the CI package gates.
9
+ #
10
+ # Usage: scripts/dev-tui.sh [--test]
11
+ # --test also run the full repo test suite (npm run test:all) after build.
12
+ set -euo pipefail
13
+
14
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
15
+ TUI_DIR="$ROOT/src/plugins/tui"
16
+ TUI_JSON="$ROOT/.opencode/tui.json"
17
+
18
+ command -v npm >/dev/null 2>&1 || { echo "error: npm not found in PATH" >&2; exit 1; }
19
+ [ -d "$TUI_DIR" ] || { echo "error: TUI source not found: $TUI_DIR" >&2; exit 1; }
20
+
21
+ echo "==> TUI dev source: $TUI_DIR"
22
+
23
+ # 1. Install pinned deps + build dist/tui.js (the bundle is the only load path).
24
+ echo "==> Installing TUI dev dependencies (npm ci)"
25
+ npm ci --prefix "$TUI_DIR" --ignore-scripts --no-audit --no-fund
26
+
27
+ echo "==> Building TUI plugin"
28
+ npm run build --prefix "$TUI_DIR"
29
+
30
+ # 2. Optional: full suite to match the CI gate before opening a PR.
31
+ if [[ "${1:-}" == "--test" ]]; then
32
+ echo "==> Running full test suite (npm run test:all)"
33
+ npm run test:all
34
+ fi
35
+
36
+ # 3. Register the repo path in the project tui.json (absolute, gitignored).
37
+ # Reuses the installer's registerPlugin so the array is merged, not clobbered.
38
+ echo "==> Registering repo TUI path in $TUI_JSON"
39
+ ROOT="$ROOT" TUI_JSON="$TUI_JSON" TUI_DIR="$TUI_DIR" node --input-type=module <<'NODE'
40
+ const { registerPlugin } = await import(`${process.env.ROOT}/scripts/install/plugin.mjs`)
41
+ const result = registerPlugin(process.env.TUI_JSON, process.env.TUI_DIR)
42
+ console.log(`${result}: ${process.env.TUI_DIR}`)
43
+ NODE
44
+
45
+ # 4. Restart hint + dev-mode caveat.
46
+ echo "==> Done. Restart OpenCode to load the rebuilt TUI plugin."
47
+ echo " Dev mode caveat: do NOT run 'init' in this repo while iterating — it"
48
+ echo " removes repo path refs as stale. If you do, re-run scripts/dev-tui.sh."
@@ -23,7 +23,7 @@
23
23
 
24
24
  import { spawn as spawnAsync, spawnSync } from 'node:child_process'
25
25
  import { createHash } from 'node:crypto'
26
- import { existsSync, mkdirSync, readdirSync, readFileSync, statSync } from 'node:fs'
26
+ import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, statSync } from 'node:fs'
27
27
  import { homedir } from 'node:os'
28
28
  import { basename, dirname, join, resolve } from 'node:path'
29
29
  import { fileURLToPath } from 'node:url'
@@ -959,6 +959,35 @@ function checkVenvLayer(args) {
959
959
  // Check F.2: Code-Mode Scripts Directory
960
960
  // ---------------------------------------------------------------------------
961
961
 
962
+ /**
963
+ * Return whether *dir* contains an executable code-mode target.
964
+ *
965
+ * Mirrors `_has_usable_scripts` in `scripts/code_mode_server.py`: a directory
966
+ * is only a valid resolver candidate when it is a real (non-symlink) directory
967
+ * containing a regular `.py`/`.sh` direct child. This prevents an empty project
968
+ * overlay from masking a lower-priority installation that actually ships
969
+ * scripts. Keep both implementations in sync (see tests/test_doctor_layers.mjs).
970
+ */
971
+ function hasUsableScripts(dir) {
972
+ try {
973
+ if (!existsSync(dir)) return false
974
+ const stat = lstatSync(dir)
975
+ if (stat.isSymbolicLink() || !stat.isDirectory()) return false
976
+ return readdirSync(dir).some((name) => {
977
+ if (name.startsWith('.')) return false
978
+ const lower = name.toLowerCase()
979
+ if (!lower.endsWith('.py') && !lower.endsWith('.sh')) return false
980
+ try {
981
+ return statSync(join(dir, name)).isFile()
982
+ } catch {
983
+ return false
984
+ }
985
+ })
986
+ } catch {
987
+ return false
988
+ }
989
+ }
990
+
962
991
  /**
963
992
  * Verify the code-mode scripts directory exists for the resolved runtime
964
993
  * root (project → <target>/.opencode, otherwise the global config dir).
@@ -977,7 +1006,7 @@ export function checkCodeModeDir(args) {
977
1006
  // install (.opencode present) gets its runtime dir created when missing.
978
1007
  // Only targets with no project layout fall back to the global config dir.
979
1008
  const codeModeDir =
980
- projectCandidates.find((candidate) => existsSync(candidate)) ??
1009
+ projectCandidates.find(hasUsableScripts) ??
981
1010
  (existsSync(join(target, '.opencode'))
982
1011
  ? projectCandidates[0]
983
1012
  : join(resolveOpenCodeConfigDir(env), '.pantheon', 'code-mode'))
@@ -1003,7 +1032,7 @@ export function resolveCodeModeDir(args) {
1003
1032
  join(target, '.opencode', '.pantheon', 'code-mode'),
1004
1033
  join(target, '.pantheon', 'code-mode'),
1005
1034
  ]
1006
- const projectDir = projectCandidates.find((candidate) => existsSync(candidate))
1035
+ const projectDir = projectCandidates.find(hasUsableScripts)
1007
1036
  if (projectDir) return projectDir
1008
1037
  return join(resolveOpenCodeConfigDir(env), '.pantheon', 'code-mode')
1009
1038
  }
@@ -8,8 +8,10 @@ import { isAbsolute, join, resolve } from 'node:path'
8
8
  import { ROOT, writeIfChanged } from './shared.mjs'
9
9
 
10
10
  /**
11
- * Copy a plugin's runtime payload (src/index.tsx → index.tsx, dist/*,
12
- * package.json and package-lock.json) from source to destination.
11
+ * Copy a plugin's runtime payload (the bundled dist/*, package.json and
12
+ * package-lock.json) from source to destination. Only the bundle is copied —
13
+ * the raw TSX source is never shipped to the destination, so the plugin can
14
+ * be modularized without the loader needing relative imports.
13
15
  * @param {string} srcDir - Source plugin directory (e.g. ROOT/src/plugins/tui)
14
16
  * @param {string} dstDir - Destination plugin directory
15
17
  * @param {object} [options]
@@ -22,16 +24,11 @@ export function copyPluginFiles(srcDir, dstDir, { dryRun = false } = {}) {
22
24
  if (!dryRun) mkdirSync(dstDir, { recursive: true })
23
25
  if (!dryRun) mkdirSync(join(dstDir, 'dist'), { recursive: true })
24
26
 
25
- // Copy src/index.tsx -> index.tsx
26
- const srcIdx = join(srcDir, 'src', 'index.tsx')
27
- if (existsSync(srcIdx)) {
28
- const idxStatus = writeIfChanged(
29
- join(dstDir, 'index.tsx'),
30
- readFileSync(srcIdx, 'utf8'),
31
- dryRun,
32
- )
33
- if (idxStatus === 'created') result.created++
34
- else result.skipped++
27
+ // Drop legacy raw copies from previous installs (root index.tsx + dist/tui.tsx).
28
+ // The loader consumes only the bundle, so stale raws must not linger.
29
+ if (!dryRun) {
30
+ rmSync(join(dstDir, 'index.tsx'), { force: true })
31
+ rmSync(join(dstDir, 'dist', 'tui.tsx'), { force: true })
35
32
  }
36
33
 
37
34
  // Copy dist/* files
@@ -10,7 +10,7 @@
10
10
  * If the user hasn't initialized yet → do nothing (silent exit).
11
11
  */
12
12
  import { execSync } from 'node:child_process'
13
- import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'
13
+ import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
14
14
  import { homedir } from 'node:os'
15
15
  import { join } from 'node:path'
16
16
  import { fileURLToPath, pathToFileURL } from 'node:url'
@@ -58,9 +58,9 @@ function resolveConfigDir() {
58
58
  }
59
59
 
60
60
  /**
61
- * Copy plugin runtime files (dist/*, package.json, package-lock.json,
62
- * src/index.tsx) from srcDir
63
- * to dstDir. Skips files that are byte-identical.
61
+ * Copy plugin runtime files (the bundled dist/*, package.json,
62
+ * package-lock.json) from srcDir to dstDir. Skips files that are byte-identical.
63
+ * The raw TSX source is never copied — the loader consumes only the bundle.
64
64
  * @returns {{ created: number, skipped: number }}
65
65
  */
66
66
  function copyPluginFiles(srcDir, dstDir) {
@@ -69,13 +69,10 @@ function copyPluginFiles(srcDir, dstDir) {
69
69
  mkdirSync(dstDir, { recursive: true })
70
70
  mkdirSync(join(dstDir, 'dist'), { recursive: true })
71
71
 
72
- // src/index.tsx → index.tsx
73
- const srcIdx = join(srcDir, 'src', 'index.tsx')
74
- if (existsSync(srcIdx)) {
75
- const content = readFileSync(srcIdx, 'utf8')
76
- if (writeIfChanged(join(dstDir, 'index.tsx'), content)) result.created++
77
- else result.skipped++
78
- }
72
+ // Drop legacy raw copies from previous installs (root index.tsx + dist/tui.tsx).
73
+ // The loader consumes only the bundle, so stale raws must not linger.
74
+ rmSync(join(dstDir, 'index.tsx'), { force: true })
75
+ rmSync(join(dstDir, 'dist', 'tui.tsx'), { force: true })
79
76
 
80
77
  // dist/*
81
78
  const distSrc = join(srcDir, 'dist')
@@ -10,8 +10,8 @@
10
10
  * never throw, never send the placeholder).
11
11
  *
12
12
  * Mirrors the TUI's `src/plugins/tui/src/index.tsx` contract verbatim so both
13
- * sides agree on what "valid" means. The TUI file remains self-contained
14
- * (dist/tui.tsx is a raw copy, no relative imports), so its local copy is kept
13
+ * sides agree on what "valid" means. The TUI plugin ships as a bundle
14
+ * (dist/tui.js) without the src/pantheon tree, so its local copy is kept
15
15
  * in sync — this module is the shared source for `src/pantheon/*` and
16
16
  * `src/plugin.ts`.
17
17
  *
@@ -22,8 +22,9 @@ type DelegationEntry = {
22
22
  read?: boolean;
23
23
  /** Internal provenance used to keep a finalized md report authoritative.
24
24
  * 'children-only' = a native task() child session with NO board report
25
- * (rendered with the distinct `nat:` prefix); 'md' = board report wins. */
26
- source?: 'child' | 'live' | 'md' | 'children-only';
25
+ * (rendered with the distinct `nat:` prefix); 'md' = board report wins;
26
+ * 'board' = read from .pantheon/board/state.json (cross-session FSM). */
27
+ source?: 'child' | 'live' | 'md' | 'children-only' | 'board';
27
28
  };
28
29
  /** Parse one delegation report md header into a structured entry.
29
30
  * Returns null (skip) when the file is not a recognizable report:
@@ -49,13 +50,39 @@ declare function readDelegationEntries(dir: string): Promise<DelegationEntry[]>;
49
50
  * desc — the sort applied by readDelegationEntries). Fail-open: a
50
51
  * missing/unreadable directory yields []. */
51
52
  declare function readAllDelegationEntries(root: string): Promise<DelegationEntry[]>;
53
+ /** The persisted subset of BackgroundJobRecord the panel consumes. Duck-typed
54
+ * so a corrupt/older record never breaks parsing. */
55
+ type BoardJobRecord = {
56
+ taskID: string;
57
+ parentSessionID: string;
58
+ agent: string;
59
+ description?: string;
60
+ state: string;
61
+ alias: string;
62
+ launchedAt?: number;
63
+ completedAt?: number;
64
+ updatedAt?: number;
65
+ timedOut?: boolean;
66
+ };
67
+ /** The FilePersistence state path: `<root>/.pantheon/board/state.json`. */
68
+ declare function boardStatePath(root: string): string;
69
+ /** Read `.pantheon/board/state.json` (the cross-session job board snapshot).
70
+ * Fail-open: missing file, corrupt JSON, non-array payload or an unreadable
71
+ * path all yield [] — the panel keeps rendering from the other channels. */
72
+ declare function readBoardState(root: string): Promise<BoardJobRecord[]>;
73
+ /** Resolve the PROJECT ROOT used by every pantheon file channel. `directory`
74
+ * wins over `worktree` (the old `resolveDelegationsDir` already did this);
75
+ * an absent/empty root or `/` (no git — e.g. the sandbox test project) falls
76
+ * back to cwd. Standardised here so the delegations md, the board state file
77
+ * and the panel logger all read the SAME root (audit finding: the channels
78
+ * resolved the root independently). Pure — no I/O. */
79
+ declare function resolvePantheonRoot(state: {
80
+ directory?: string;
81
+ worktree?: string;
82
+ } | undefined, cwd?: string): string;
52
83
  /** Resolve the directory where the job board writes delegation md reports.
53
84
  * The board writes `.pantheon/delegations` RELATIVE to the server cwd,
54
- * which the TUI exposes as `TuiState.path.directory`. `project` does NOT
55
- * exist on `TuiState.path` (the old `state?.project ?? state?.worktree`
56
- * resolution was always undefined for the first term) and `worktree` is
57
- * `/` when there is no git (e.g. the sandbox test project) — a root of
58
- * `''` or `'/'` must fall back to `process.cwd()`. */
85
+ * which the TUI exposes as `TuiState.path.directory`. */
59
86
  declare function resolveDelegationsDir(state: {
60
87
  directory?: string;
61
88
  worktree?: string;
@@ -116,6 +143,27 @@ declare function delegationActivityLabel(entry: DelegationEntry): string;
116
143
  /** Return a deterministic spinner frame. The View ticks this every 1000ms
117
144
  * (not 140ms — the fast tick flickered without adding information). */
118
145
  declare function delegationSpinnerFrame(now: number): string;
146
+ /** Every state the row knows how to draw: the real BackgroundJobBoard FSM
147
+ * (src/pantheon/background-job-board.ts) plus the TUI display-only states
148
+ * (`retry`, `stale-running`). Fase 1 deliberately omits speculative
149
+ * blocked/paused/scheduled/skipped. There is no `pending` display state: a
150
+ * pre-dispatch tool part maps to `running` in {@link reduceDelegationToolPart}. */
151
+ type DelegationDisplayState = DelegationEntry['state'];
152
+ /** Static glyph per display state. `running` shows its base spinner frame;
153
+ * callers that animate must prefer {@link delegationStateMarker}. Unicode
154
+ * geometric shapes only (no Nerd Font) — shape is an independent channel
155
+ * from color, so rows stay legible without color. */
156
+ declare const DELEGATION_STATE_GLYPHS: Readonly<Record<DelegationDisplayState, string>>;
157
+ declare function delegationStateGlyph(state: DelegationDisplayState): string;
158
+ /** Row marker (`<glyph> `) — the state channel. `running` animates through
159
+ * {@link delegationSpinnerFrame} for the given tick; every other state is
160
+ * static. Pure. */
161
+ declare function delegationStateMarker(state: DelegationDisplayState, now?: number): string;
162
+ /** Semantic tone mapped to the TUI theme at the row ({@link DelegationRow}).
163
+ * Kept separate + pure so the color channel is testable without booting the
164
+ * renderer. */
165
+ type DelegationStateTone = 'warning' | 'error' | 'success' | 'muted';
166
+ declare function delegationStateTone(state: DelegationDisplayState): DelegationStateTone;
119
167
  type ToolActivity = {
120
168
  tool: string;
121
169
  summary: string;
@@ -240,6 +288,40 @@ declare function toDelegationEntry(live: LiveDelegationEntry): DelegationEntry;
240
288
  * terminal md entry is authoritative over a live running entry for the
241
289
  * same job (it carries Finalized/timedOut/cancelled from finalize). */
242
290
  declare function mergeDelegationSources(live: readonly LiveDelegationEntry[], md: readonly DelegationEntry[]): DelegationEntry[];
291
+ /** Map one persisted board record into the display shape. Returns null for
292
+ * states the panel does not render (reconciled / unknown). Pure. */
293
+ declare function boardRecordToDelegationEntry(record: BoardJobRecord): DelegationEntry | null;
294
+ /** Map a whole board snapshot, dropping unrenderable states. Sorted like every
295
+ * other channel (running first, then most recent). Pure. */
296
+ declare function boardRecordsToDelegationEntries(records: readonly BoardJobRecord[]): DelegationEntry[];
297
+ /** Merge the board over any other channel. The board is AUTHORITATIVE for
298
+ * state/alias/agent (it is the persisted FSM) and it is the only channel
299
+ * that carries jobs from OTHER sessions. Dedup by taskID first, then by
300
+ * (sessionID, alias) — aliases are per parent session. Pure. */
301
+ declare function mergeBoardDelegationSources(base: readonly DelegationEntry[], board: readonly DelegationEntry[]): DelegationEntry[];
302
+ /** 'session' = focused session only (default); 'all' = every session the
303
+ * board knows about. */
304
+ type DelegationScope = 'session' | 'all';
305
+ /** api.kv key holding the persisted scope (defaults to 'session'). */
306
+ declare const DELEGATION_SCOPE_KV_KEY = "delegations.scope";
307
+ /** Structural subset of TuiKV — kept local so the pure helpers are testable
308
+ * without the TUI runtime. */
309
+ type DelegationScopeKv = {
310
+ get: (key: string, fallback?: unknown) => unknown;
311
+ set: (key: string, value: unknown) => void;
312
+ };
313
+ /** Read the persisted scope; anything malformed/absent → 'session'. */
314
+ declare function readDelegationScope(kv: DelegationScopeKv | undefined): DelegationScope;
315
+ /** Persist the scope. Failure is non-fatal — the signal keeps it in memory. */
316
+ declare function writeDelegationScope(kv: DelegationScopeKv | undefined, scope: DelegationScope): void;
317
+ /** Keyboard/click toggle target. Pure. */
318
+ declare function nextDelegationScope(scope: DelegationScope): DelegationScope;
319
+ /** Keep only the focused session's jobs ('session') or all of them ('all').
320
+ * An empty sessionID marks a current-session child (the children channel is
321
+ * session-scoped and only fills sessionID from a matching md report), so it
322
+ * counts as the current session. With no resolved session there is nothing
323
+ * to scope against — fail-open to the full list. Pure. */
324
+ declare function filterDelegationsByScope(entries: readonly DelegationEntry[], scope: DelegationScope, sessionID: string | null): DelegationEntry[];
243
325
  /** Server-aligned session id validity: opencode rejects anything not starting
244
326
  * with "ses" (SchemaError). This deliberately mirrors that exact contract —
245
327
  * nothing stricter, nothing looser — so a template placeholder ("{sessionID}"),
@@ -413,5 +495,5 @@ declare const plugin: TuiPluginModule & {
413
495
  setup: () => Promise<void>;
414
496
  };
415
497
  //#endregion
416
- export { ChildDelegationLike, DELEGATION_DESCRIPTION_MAX, DELEGATION_ELAPSED_WIDTH, DelegationActivity, DelegationEntry, DelegationToolPart, IDLE_SILENCE_MS, LiveDelegationEntry, LiveDelegationStore, ParsedDelegationToolPart, STALE_RUNNING_THRESHOLD_MS, ToolActivity, TuiSessionSources, buildChildrenPath, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationIcon, delegationSpinnerFrame, delegationTag, extractToolActivity, fmtElapsed, formatDelegationElapsed, formatDelegationHeader, formatDelegationIdentity, formatDelegationRow, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
498
+ export { BoardJobRecord, ChildDelegationLike, DELEGATION_DESCRIPTION_MAX, DELEGATION_ELAPSED_WIDTH, DELEGATION_SCOPE_KV_KEY, DELEGATION_STATE_GLYPHS, DelegationActivity, DelegationDisplayState, DelegationEntry, DelegationScope, DelegationScopeKv, DelegationStateTone, DelegationToolPart, IDLE_SILENCE_MS, LiveDelegationEntry, LiveDelegationStore, ParsedDelegationToolPart, STALE_RUNNING_THRESHOLD_MS, ToolActivity, TuiSessionSources, boardRecordToDelegationEntry, boardRecordsToDelegationEntries, boardStatePath, buildChildrenPath, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationIcon, delegationSpinnerFrame, delegationStateGlyph, delegationStateMarker, delegationStateTone, delegationTag, extractToolActivity, filterDelegationsByScope, fmtElapsed, formatDelegationElapsed, formatDelegationHeader, formatDelegationIdentity, formatDelegationRow, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeBoardDelegationSources, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, nextDelegationScope, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readBoardState, readDelegationEntries, readDelegationScope, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList, writeDelegationScope };
417
499
  //# sourceMappingURL=tui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":";;KAu7BY;;EAEV;;EAEA;;;;EAIA;;EAEA;EACA;;EAUA;;EAEA;EACA;EACA;;EAEA;;;;EAQA;;;;;;;;;;;iBAsBc,wBACd,aACA,oBACA,qBACC;;;;;;iBAkHmB,sBAAsB,cAAc,QAAQ;;;;;;;;iBAwC5C,yBAAyB,eAAe,QAAQ;;;;;;;;iBAWtD,sBACd;EAAS;EAAoB;eAC7B;;;;;;iBAYc,YAAY;;;iBAMZ,WAAW;;;;iBAOX,yBAAyB,GAAG,iBAAiB,GAAG;;;;;iBAahD,oBACd,cAAc,mBACd,oBACA,cACA;EACG,QAAQ;EAAmB,QAAQ;EAAmB,UAAU;;;;;iBAqBrD,sBACd,cAAc,mBACd,sBACA,cACA,4BACC;;cAMU;;;;cAKA;;;;;;;;;iBAUG,mBACd,OAAO,iBACP,aACA,uBACC;;;iBAWa,WAAW;;;;iBAeX,kBAAkB,OAAO,iBAAiB;;;KAQ9C;iBAQI,mBAAmB,OAAO,kBAAkB;iBAc5C,wBAAwB,OAAO;;;iBAsB/B,uBAAuB;KAY3B;EACV;EACA;EACA;;;;;iBA0Bc,oBACd;EACE;EACA;EACA;EACA;IAAU;IAAiB,QAAQ;;GAErC;EACG;EAAmB,UAAU;;;iBAYlB,kBACd,KAAK,YAAY,eACjB,mBACA,UAAU;;iBAWI,sBACd,KAAK,YAAY,eACjB,+BACA,cACA,iBACC;;;;;;;iBAca,4BACd,mBAAmB,mBACnB,eAAe,wBACd;;KAqFS;EACV;EACA;EACA;EACA;EACA;EACA;IACE;IACA,QAAQ;IACR;IACA;IACA;MAAS;MAAgB;;;;;KAKjB;;EAEV;;EAEA;;EAEA;EACA;;EAEA;EACA;;EAEA;;EAEA;EACA;EACA;EACA;;EAEA;;;KAIU;EACV;EACA;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;;iBAec,wBACd,MAAM,oBACN,eACC;;;iBAgGa,yBACd,KAAK,YAAY,sBACjB,MAAM,oBACN;;;iBAiGc,sBACd,KAAK,YAAY,sBACjB;;;;;;;;;iBAoBc,2BACd;EAAqB;EAAa;iBAClC,YAAY,uDACX;;;;;iBA6Ba,sBACd,KAAK,YAAY,sBACjB,gBAAgB,sBAChB;;;iBAWc,kBAAkB,MAAM,sBAAsB;;;;;;iBAqB9C,uBACd,eAAe,uBACf,aAAa,oBACZ;;;;;;;;;iBA8Da,iBAAiB,cAAc;;;;KAOnC;;EAEV;EACA;;IAEE;MAAU;;;IAEV;MAAU;QAAY;QAAe,SAAS;;;;;;;;;;iBASlC,wBAAwB,SAAS;;;;;;;;iBAmBjC,gBAAgB;EAAgB;IAAQ;;;;;;;iBASxC,kBAAkB;EAAkC;IAAQ;;;;KAKhE;;EAEV;;EAEA;;;EAGA;;;EAGA;EACA;IACE;IACA;;;;;;;iBAQY,mBAAmB;;;;;;;;;;;;;iBAkBnB,cAAc,OAAO;;;;;iBAQrB,eAAe,OAAO;;;;iBAOtB,yBAAyB,OAAO;;;cAQnC;;;;iBAoBG,8BACd,cACA;;;;cAUW;iBAEG,wBACd,OAAO,iBACP,aACA;;;iBASc,oBAAoB,OAAO,iBAAiB;;;;iBAY5C,uBAAuB,kBAAkB;;;;iBAazC,uBAAuB,kBAAkB;EACvD;EACA;EACA;;;;;iBAUc,mBACd,kBACA,kBACA,gBACA,YACA;;;;;;;;;;;;;;;;;;iBAsBc,4BACd,mBAAmB,mCACnB,aAAa,mBACb,eACC;;;;;;iBA4Ca,4BACd;EAAS,YAAY,cAAc,SAAS;eAC5C;;;;;KA4MU;EACV,KAAK,YAAY;;EAEjB;;EAEA;;cAsgBI,QAAQ;EAAoB;EAAY,aAAa"}
1
+ {"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":"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"}