omnish 1.6.4 → 1.6.5

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
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - **Dev tooling:** Prettier with root [`.prettierrc.json`](.prettierrc.json); run `pnpm format` or `pnpm format:check` before submitting PRs (CI enforces format check).
13
+
14
+ ### Changed
15
+
16
+ - **Documentation search (chat):** `/docs search` → **`/s q`** (shorthand **`/s`**, full form **`/search`**). List, show, and follow moved to `/s` / `/search`. Legacy **`/docs`**, **`/help search`**, and **`omnish docs`** still work. Host CLI: **`omnish search q`**.
17
+
18
+ ### Added
19
+
20
+ - **`omnish start`:** start the gateway in the background by default (pairs with **`omnish stop`**). Foreground: **`omnish start -f`**. **`omnish run`** stays foreground unless **`-d`** is passed.
21
+
10
22
  ## [1.6.2] - 2026-05-23
11
23
 
12
24
  ### Security
package/README.md CHANGED
@@ -18,10 +18,10 @@
18
18
 
19
19
  <p align="center"><em>Inbox and shell, linked — deterministic, local execution.</em></p>
20
20
 
21
- | WhatsApp | Telegram |
22
- |:--------:|:--------:|
21
+ | WhatsApp | Telegram |
22
+ | :------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------: |
23
23
  | <img src="https://omnish.dev/media/omnish_whatsapp_mockup.png" alt="WhatsApp" width="340" /> | <img src="https://omnish.dev/media/omnish_telegram_mockup.png" alt="Telegram" width="340" /> |
24
- | DM surface you already use | Same gateway pattern via bot DM |
24
+ | DM surface you already use | Same gateway pattern via bot DM |
25
25
 
26
26
  ---
27
27
 
@@ -53,22 +53,23 @@ No AI or agent layer — direct `bash -c` for sync jobs; PTY uses your configure
53
53
 
54
54
  **Multi-host cluster (optional, chat-driven):** with **`clusterEnabled`**, link the same WhatsApp number to several machines (multi-device). Each allowlisted **sender** picks one machine to talk to with **`/c use <label-or-id>`** (or **`/c here`** to bind to the local machine); only the bound machine answers that sender's normal traffic. Two controllers can independently bind to two different machines without affecting each other. Pre-seed defaults in **`clusterSenderBindings`**. There is **no shared file**, no Syncthing — coordination flows through the WhatsApp chat itself via an invisible footer on each reply. See [docs/features/cluster-and-chat-config.md](docs/features/cluster-and-chat-config.md).
55
55
 
56
- **Background gateway:** **`omnish run --background`** (`-d`) and **`omnish stop`** work on **Linux, macOS, and Windows** (detached run + pidfile). From an allowlisted chat, **`/service`** shows status, install hints, and logs; optional **`/service install`** after **`/config set serviceInstallFromChat true`**. For **login/boot**, see [Background gateway and start on boot](docs/guides/background-and-boot.md) and [Service from chat](docs/features/service-from-chat.md).
56
+ **Background gateway:** **`omnish start`** (background by default) and **`omnish stop`** work on **Linux, macOS, and Windows** (detached run + pidfile). Same detached behavior: **`omnish run -d`**. From an allowlisted chat, **`/service`** shows status, install hints, and logs; optional **`/service install`** after **`/config set serviceInstallFromChat true`**. For **login/boot**, see [Background gateway and start on boot](docs/guides/background-and-boot.md) and [Service from chat](docs/features/service-from-chat.md).
57
57
 
58
58
  **Config from chat:** `/config show`, `/config get`, `/config set` for a whitelist of `config.json` keys (same trust as shell). See the same doc.
59
59
 
60
60
  ## Running in the background and on boot
61
61
 
62
- - **`omnish run --background`** (or **`-d`**) — starts detached; logs append to **`--log-file`** (default: `<data>/logs/gateway.log`); PID in **`<data>/gateway.pid`**.
62
+ - **`omnish start`** — starts detached by default; logs append to **`--log-file`** (default: `<data>/logs/gateway.log`); PID in **`<data>/gateway.pid`**.
63
+ - **`omnish run -d`** (or **`--background`**) — same detached launch; **`omnish run`** alone stays in the foreground.
63
64
  - **`omnish stop`** — reads the pidfile and stops the process (**SIGTERM** on Unix; on Windows **`taskkill`** is used if signaling fails).
64
65
 
65
66
  Full steps for systemd, launchd, and Task Scheduler — **[docs/guides/background-and-boot.md](docs/guides/background-and-boot.md)**.
66
67
 
67
- | OS | Boot / auto-restart |
68
- |----|---------------------|
69
- | Linux | User systemd unit — [contrib/omnish.service](contrib/omnish.service), **`loginctl enable-linger`** if needed |
70
- | macOS | LaunchAgent — [contrib/dev.omnish.gateway.plist](contrib/dev.omnish.gateway.plist), **`launchctl bootstrap`** / **`kickstart`** |
71
- | Windows | Task Scheduler or import — [contrib/omnish-windows-task.xml](contrib/omnish-windows-task.xml); NSSM / WinSW advanced |
68
+ | OS | Boot / auto-restart |
69
+ | ------- | ------------------------------------------------------------------------------------------------------------------------------- |
70
+ | Linux | User systemd unit — [contrib/omnish.service](contrib/omnish.service), **`loginctl enable-linger`** if needed |
71
+ | macOS | LaunchAgent — [contrib/dev.omnish.gateway.plist](contrib/dev.omnish.gateway.plist), **`launchctl bootstrap`** / **`kickstart`** |
72
+ | Windows | Task Scheduler or import — [contrib/omnish-windows-task.xml](contrib/omnish-windows-task.xml); NSSM / WinSW advanced |
72
73
 
73
74
  ## Data directory
74
75
 
@@ -86,13 +87,13 @@ Per-chat shell cwd is in `sessions.json`; **user shortcuts** are stored in `shor
86
87
 
87
88
  Each **chat** (WhatsApp DM / Telegram DM) has its own shortcut map on disk (`shortcuts.json`).
88
89
 
89
- | Action | Example |
90
- |--------|--------|
91
- | Add / overwrite | `/shortcut add kidsync !cd ../../kidsync` |
92
- | List | `/shortcut list` or `/shortcuts` |
93
- | Show | `/shortcut show kidsync` |
94
- | Remove | `/shortcut remove kidsync` |
95
- | Help | `/shortcut help` — aliases: `/alias …`, `/aliases …` (same as `/shortcut …`) |
90
+ | Action | Example |
91
+ | --------------- | ---------------------------------------------------------------------------- |
92
+ | Add / overwrite | `/shortcut add kidsync !cd ../../kidsync` |
93
+ | List | `/shortcut list` or `/shortcuts` |
94
+ | Show | `/shortcut show kidsync` |
95
+ | Remove | `/shortcut remove kidsync` |
96
+ | Help | `/shortcut help` — aliases: `/alias …`, `/aliases …` (same as `/shortcut …`) |
96
97
 
97
98
  **Invoke:** send **`!kidsync`** or **`/kidsync`** (bare name), or **`!kidsync <text…>`** / **`/kidsync <text…>`** when the body contains **`$OMNISH_INPUT`**. The saved line runs once; if it is a standalone `!cd …`, the session working directory updates like a normal sync `cd`. Shortcut bodies are **not** expanded again (no nesting).
98
99
 
@@ -152,24 +153,24 @@ Output is **debounced** (`appsFlushMs`, default 300 ms), **throttled** (`appsMin
152
153
 
153
154
  ### `/apps` cheat sheet
154
155
 
155
- | Command | Action |
156
- |--------|--------|
157
- | `/apps start <name> <cmd…>` | Spawn app session in session cwd; **auto-attaches** `<name>`. |
158
- | `/apps attach <name>` | Focus plain DMs on that running session. |
159
- | `/apps detach` | Clear focus. |
160
- | `/apps list` | Sessions for this chat; `*` marks focus. Shows `attached: …` or `(no focus)`. |
161
- | `/apps info <name>` / `/apps get <name>` | Cmd, cwd, env key count, terminal size, ring bytes, log path/size, mute/raw. |
162
- | `/apps send <name> <text>` | Write `text` + newline (no attach). |
163
- | `>name text` | Same as `/apps send`. |
164
- | `/apps key <name> KEY[,KEY…]` | Special keys: `Enter`, `Tab`, `Esc`, arrows, `^C`, `ctrl+d`, `\x1b`, … |
165
- | `/apps tail <name> [lines]` | Last *lines* of log (default `appsLogTailLines`). |
166
- | `/apps since <name>` | New log bytes since your last `/apps since` for that name. |
167
- | `/apps mute <name>` / `/apps unmute <name>` | Pause / resume streaming to the chat (log still grows). |
168
- | `/apps raw <name> on\|off` | Keep ANSI in streamed messages when `on`. |
169
- | `/apps resize <name> <cols> <rows>` | Resize terminal. |
170
- | `/apps stop <name>` | SIGTERM; SIGKILL after 5 s if still alive. |
171
- | `/apps kill <name>` | SIGKILL immediately. |
172
- | `/apps rm <name>` | Only after the process has **exited**; removes metadata + log file. |
156
+ | Command | Action |
157
+ | ------------------------------------------- | ----------------------------------------------------------------------------- |
158
+ | `/apps start <name> <cmd…>` | Spawn app session in session cwd; **auto-attaches** `<name>`. |
159
+ | `/apps attach <name>` | Focus plain DMs on that running session. |
160
+ | `/apps detach` | Clear focus. |
161
+ | `/apps list` | Sessions for this chat; `*` marks focus. Shows `attached: …` or `(no focus)`. |
162
+ | `/apps info <name>` / `/apps get <name>` | Cmd, cwd, env key count, terminal size, ring bytes, log path/size, mute/raw. |
163
+ | `/apps send <name> <text>` | Write `text` + newline (no attach). |
164
+ | `>name text` | Same as `/apps send`. |
165
+ | `/apps key <name> KEY[,KEY…]` | Special keys: `Enter`, `Tab`, `Esc`, arrows, `^C`, `ctrl+d`, `\x1b`, … |
166
+ | `/apps tail <name> [lines]` | Last _lines_ of log (default `appsLogTailLines`). |
167
+ | `/apps since <name>` | New log bytes since your last `/apps since` for that name. |
168
+ | `/apps mute <name>` / `/apps unmute <name>` | Pause / resume streaming to the chat (log still grows). |
169
+ | `/apps raw <name> on\|off` | Keep ANSI in streamed messages when `on`. |
170
+ | `/apps resize <name> <cols> <rows>` | Resize terminal. |
171
+ | `/apps stop <name>` | SIGTERM; SIGKILL after 5 s if still alive. |
172
+ | `/apps kill <name>` | SIGKILL immediately. |
173
+ | `/apps rm <name>` | Only after the process has **exited**; removes metadata + log file. |
173
174
 
174
175
  To send a literal `!`, `/`, or `>` to the attached program, use **`/apps send <name> …`** or **`>name …`**.
175
176
 
@@ -187,21 +188,22 @@ To send a literal `!`, `/`, or `>` to the attached program, use **`/apps send <n
187
188
 
188
189
  ## CLI
189
190
 
190
- | Command | Description |
191
- |--------|-------------|
192
- | `omnish link` / `link --force` | Print QR; save session under `<data-dir>/auth/` (`--force` deletes old auth first). Telegram token mode: `omnish link --tg <token>` (alias: `--telegram`). |
193
- | `omnish run` | Start gateway (foreground). Background: `omnish run -d [--log-file <path>]`. |
194
- | `omnish stop` | Stop a background gateway (`omnish run -d`; uses `<data-dir>/gateway.pid`) |
195
- | `omnish i` / `interactive` | Chat-equivalent REPL on your terminal; **`omnish i --help`** · [interactive-cli.md](docs/guides/interactive-cli.md) |
196
- | `omnish service …` | Service status, logs, install/uninstall (same trust gate as **`/service`** in chat) |
197
- | `omnish logout` | Delete saved WhatsApp session |
198
- | `omnish allow +1555...` | Add WhatsApp number to allowlist |
199
- | `omnish allow tg:<id>` | Add Telegram user id |
200
- | `omnish deny …` | Remove allowlist entry |
201
- | `omnish status [--check-updates]` | Data dir, auth, allowlists, jobs, cluster (if enabled); optional live npm/update check |
202
- | `omnish commands` | Print chat command help on the host terminal (`/help` equivalent) + `/config`-editable keys |
203
- | `omnish security [--json]` | Local security posture report (`--json` for scripts; non-zero exit on error findings) |
204
- | `omnish cluster [status \| use <sender> <label-or-id>]` | Show cluster state or seed a sender machine binding |
191
+ | Command | Description |
192
+ | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
193
+ | `omnish link` / `link --force` | Print QR; save session under `<data-dir>/auth/` (`--force` deletes old auth first). Telegram token mode: `omnish link --tg <token>` (alias: `--telegram`). |
194
+ | `omnish run` | Start gateway in foreground; background: `omnish run -d [--log-file <path>]`. |
195
+ | `omnish start` | Start gateway in background (same as `run -d`); `-f` for foreground. Pair with `stop`. |
196
+ | `omnish stop` | Stop a background gateway (`start` or `run -d`; uses `<data-dir>/gateway.pid`) |
197
+ | `omnish i` / `interactive` | Chat-equivalent REPL on your terminal; **`omnish i --help`** · [interactive-cli.md](docs/guides/interactive-cli.md) |
198
+ | `omnish service …` | Service status, logs, install/uninstall (same trust gate as **`/service`** in chat) |
199
+ | `omnish logout` | Delete saved WhatsApp session |
200
+ | `omnish allow +1555...` | Add WhatsApp number to allowlist |
201
+ | `omnish allow tg:<id>` | Add Telegram user id |
202
+ | `omnish deny …` | Remove allowlist entry |
203
+ | `omnish status [--check-updates]` | Data dir, auth, allowlists, jobs, cluster (if enabled); optional live npm/update check |
204
+ | `omnish commands` | Print chat command help on the host terminal (`/help` equivalent) + `/config`-editable keys |
205
+ | `omnish security [--json]` | Local security posture report (`--json` for scripts; non-zero exit on error findings) |
206
+ | `omnish cluster [status \| use <sender> <label-or-id>]` | Show cluster state or seed a sender → machine binding |
205
207
 
206
208
  Config: `<data-dir>/config.json` (see [config.example.json](config.example.json)). Use `omnish status` for the resolved path.
207
209
 
@@ -243,28 +245,28 @@ What to expect:
243
245
 
244
246
  Index and curated paths: **[docs/README.md](docs/README.md)**.
245
247
 
246
- | Topic | Doc |
247
- |-------|-----|
248
- | Vision — local first, product direction | [docs/vision.md](docs/vision.md) |
249
- | Docker gateway (reference compose) | [docs/guides/docker-gateway-golden-path.md](docs/guides/docker-gateway-golden-path.md) |
250
- | Interactive terminal (`omnish i`, `/sendto` multi-target) | [docs/guides/interactive-cli.md](docs/guides/interactive-cli.md) |
251
- | Configuration (`config.json`) | [docs/guides/configuration.md](docs/guides/configuration.md) |
252
- | Browser setup UI (`omnish ui`) | [docs/guides/ui.md](docs/guides/ui.md) |
253
- | Cluster roster + `/config` from chat | [docs/features/cluster-and-chat-config.md](docs/features/cluster-and-chat-config.md) |
254
- | Interactive sessions (`/apps`) | [docs/features/sessions.md](docs/features/sessions.md) |
255
- | Background jobs | [docs/features/background-jobs.md](docs/features/background-jobs.md) |
256
- | Webhook receiver (CI/CD notifications) | [docs/features/webhook-receiver.md](docs/features/webhook-receiver.md) |
257
- | Message routing | [docs/architecture/routing.md](docs/architecture/routing.md) |
258
- | Security | [docs/architecture/security.md](docs/architecture/security.md) |
259
- | User guide | [docs/guides/user-guide.md](docs/guides/user-guide.md) |
260
- | Documentation search (`/docs`, `omnish docs`) | [docs/features/docs-search-from-chat.md](docs/features/docs-search-from-chat.md) |
261
- | System agents + `/run` | [docs/guides/system-agents-and-run.md](docs/guides/system-agents-and-run.md) |
262
- | MCP IDE spike (experimental) | [contrib/mcp-spike/README.md](contrib/mcp-spike/README.md) |
263
- | Telegram | [docs/telegram-integration-notes.md](docs/telegram-integration-notes.md) |
264
- | Send/receive files (`/send` selectors, `/sendto` destinations) | [docs/files-send-receive.md](docs/files-send-receive.md) |
265
- | Troubleshooting | [docs/advanced/troubleshooting.md](docs/advanced/troubleshooting.md) |
266
- | Implementation / contributors | [docs/advanced/implementation.md](docs/advanced/implementation.md) |
267
- | Architecture (legacy) | [docs/architecture-and-implementation.md](docs/architecture-and-implementation.md) |
248
+ | Topic | Doc |
249
+ | -------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
250
+ | Vision — local first, product direction | [docs/vision.md](docs/vision.md) |
251
+ | Docker gateway (reference compose) | [docs/guides/docker-gateway-golden-path.md](docs/guides/docker-gateway-golden-path.md) |
252
+ | Interactive terminal (`omnish i`, `/sendto` multi-target) | [docs/guides/interactive-cli.md](docs/guides/interactive-cli.md) |
253
+ | Configuration (`config.json`) | [docs/guides/configuration.md](docs/guides/configuration.md) |
254
+ | Browser setup UI (`omnish ui`) | [docs/guides/ui.md](docs/guides/ui.md) |
255
+ | Cluster roster + `/config` from chat | [docs/features/cluster-and-chat-config.md](docs/features/cluster-and-chat-config.md) |
256
+ | Interactive sessions (`/apps`) | [docs/features/sessions.md](docs/features/sessions.md) |
257
+ | Background jobs | [docs/features/background-jobs.md](docs/features/background-jobs.md) |
258
+ | Webhook receiver (CI/CD notifications) | [docs/features/webhook-receiver.md](docs/features/webhook-receiver.md) |
259
+ | Message routing | [docs/architecture/routing.md](docs/architecture/routing.md) |
260
+ | Security | [docs/architecture/security.md](docs/architecture/security.md) |
261
+ | User guide | [docs/guides/user-guide.md](docs/guides/user-guide.md) |
262
+ | Documentation search (`/s`, `omnish search`) | [docs/features/docs-search-from-chat.md](docs/features/docs-search-from-chat.md) |
263
+ | System agents + `/run` | [docs/guides/system-agents-and-run.md](docs/guides/system-agents-and-run.md) |
264
+ | MCP IDE spike (experimental) | [contrib/mcp-spike/README.md](contrib/mcp-spike/README.md) |
265
+ | Telegram | [docs/telegram-integration-notes.md](docs/telegram-integration-notes.md) |
266
+ | Send/receive files (`/send` selectors, `/sendto` destinations) | [docs/files-send-receive.md](docs/files-send-receive.md) |
267
+ | Troubleshooting | [docs/advanced/troubleshooting.md](docs/advanced/troubleshooting.md) |
268
+ | Implementation / contributors | [docs/advanced/implementation.md](docs/advanced/implementation.md) |
269
+ | Architecture (legacy) | [docs/architecture-and-implementation.md](docs/architecture-and-implementation.md) |
268
270
 
269
271
  ## Troubleshooting
270
272
 
@@ -32,6 +32,7 @@
32
32
  "recipesMaxTaskChars": 100000,
33
33
  "recipesMacroDefaultCommand": "claude -p \"$OMNISH_TASK\"",
34
34
  "recipesRunAttach": false,
35
+ "recipesNotifyEnabled": true,
35
36
  "clusterEnabled": false,
36
37
  "clusterLabel": "",
37
38
  "clusterRole": "secondary",
@@ -48,6 +49,10 @@
48
49
  "chatLlmMaxOutputChars": 24000,
49
50
  "chatLlmNeedsTty": false,
50
51
  "chatLlmWorkDir": "",
52
+ "chatAgentEnabled": false,
53
+ "chatAgentCommand": "",
54
+ "chatAgentPerPeer": true,
55
+ "chatAgentMaxQueue": 64,
51
56
  "tunnelEnabled": false,
52
57
  "tunnelRelayUrl": "https://tunnel.omnish.dev",
53
58
  "platformToken": "",
@@ -57,6 +62,18 @@
57
62
  "watchDebounceMs": 2000,
58
63
  "watchMaxEventsPerMinute": 30,
59
64
  "watchAutoRestore": true,
65
+ "boardCoordinatorEnabled": true,
66
+ "boardCoordinatorIntervalMs": 5000,
67
+ "boardMaxRework": 3,
68
+ "boardNotifyProgress": "milestones",
69
+ "boardNotifyJobStatus": true,
70
+ "boardPrimaryAgent": "",
71
+ "boardAgentPermissionMode": "safe",
72
+ "boardCoordinatorAgentEnabled": false,
73
+ "boardCoordinatorAgentCommand": "",
74
+ "boardCoordinatorFinetuneEnabled": false,
75
+ "boardSkillResearchEnabled": true,
76
+ "boardFeedbackReminderEnabled": false,
60
77
  "mediaSendFiles": true,
61
78
  "mediaUrlAutoDl": true,
62
79
  "mediaInstallFromChat": false,
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Mandatory employee harness — runs inner agent CLI after omnish seeds work-plan.json.
4
+ * Usage: node board-employee-run.mjs "<innerCommand>"
5
+ */
6
+ import { spawnSync } from "node:child_process";
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+
10
+ const innerCommand = process.argv[2];
11
+ if (!innerCommand || !innerCommand.trim()) {
12
+ console.error("board-employee-run: missing inner command argument");
13
+ process.exit(1);
14
+ }
15
+
16
+ const workDir = process.env.OMNISH_JOB_WORKDIR;
17
+ const jobId = process.env.OMNISH_JOB_ID;
18
+ const specialist =
19
+ process.env.OMNISH_BOARD_SPECIALIST ?? process.env.OMNISH_JOB_ASSIGNEE ?? "employee";
20
+
21
+ if (!workDir || !jobId) {
22
+ console.error("board-employee-run: OMNISH_JOB_WORKDIR and OMNISH_JOB_ID required");
23
+ process.exit(1);
24
+ }
25
+
26
+ const planPath = path.join(workDir, "work-plan.json");
27
+ if (!fs.existsSync(planPath)) {
28
+ console.error("board-employee-run: work-plan.json missing (harness should have seeded it)");
29
+ process.exit(1);
30
+ }
31
+
32
+ const shell = process.env.SHELL || "/bin/bash";
33
+ const result = spawnSync(shell, ["-lc", innerCommand], {
34
+ cwd: process.cwd(),
35
+ env: process.env,
36
+ encoding: "utf8",
37
+ maxBuffer: 32 * 1024 * 1024,
38
+ });
39
+
40
+ const reportPath = path.join(workDir, "report.json");
41
+ if (!fs.existsSync(reportPath)) {
42
+ const exitCode = result.status ?? 1;
43
+ const summary =
44
+ result.signal != null
45
+ ? `Harness: inner command signaled ${result.signal}`
46
+ : `Harness: inner command exited ${exitCode}; no report.json`;
47
+ const doc = {
48
+ jobId,
49
+ specialist,
50
+ summary,
51
+ stepsCompleted: [],
52
+ artifacts: ["work-plan.json"],
53
+ exitCode,
54
+ blockers: result.stderr?.trim()
55
+ ? [result.stderr.trim().slice(0, 500)]
56
+ : ["no report.json from inner command"],
57
+ selfAssessment: "Did not complete core handoff contract.",
58
+ workPlanPath: "work-plan.json",
59
+ planFollowed: false,
60
+ communicationSummary: "Harness stub — inner command did not complete handoff.",
61
+ handoffMessage: "No handoff message from inner command.",
62
+ };
63
+ fs.writeFileSync(reportPath, JSON.stringify(doc, null, 2) + "\n", { mode: 0o600 });
64
+ }
65
+
66
+ if (result.status !== 0) {
67
+ process.exit(result.status ?? 1);
68
+ }
69
+ process.exit(0);