@damian87/omp 0.13.0 → 0.14.0
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/.github/skills/schedule/SKILL.md +27 -2
- package/.github/skills/verify-byok/SKILL.md +50 -0
- package/README.md +88 -4
- package/catalog/capabilities.json +23 -0
- package/catalog/skills-general.json +25 -0
- package/dist/src/cli.js +34 -2
- package/dist/src/cli.js.map +1 -1
- package/dist/src/gateway/desktop-notify.d.ts +56 -0
- package/dist/src/gateway/desktop-notify.js +183 -0
- package/dist/src/gateway/desktop-notify.js.map +1 -0
- package/dist/src/schedule/commands.d.ts +13 -0
- package/dist/src/schedule/commands.js +24 -1
- package/dist/src/schedule/commands.js.map +1 -1
- package/dist/src/schedule/deep-link.d.ts +18 -0
- package/dist/src/schedule/deep-link.js +41 -0
- package/dist/src/schedule/deep-link.js.map +1 -0
- package/dist/src/schedule/runner.d.ts +10 -0
- package/dist/src/schedule/runner.js +36 -0
- package/dist/src/schedule/runner.js.map +1 -1
- package/dist/src/schedule/types.d.ts +16 -0
- package/docs/research/2026-06-22-schedule-desktop-notifications.md +193 -0
- package/package.json +4 -2
- package/plugin.json +1 -1
|
@@ -37,14 +37,39 @@ the `omp schedule …` commands on the user's behalf.
|
|
|
37
37
|
```bash
|
|
38
38
|
omp schedule add --id <id> --cron "<expr>" --prompt "<text>" \
|
|
39
39
|
[--allow-all-tools] [--cwd <dir>] [--model <m>] [--timeout <ms>] \
|
|
40
|
-
[--max-runs <n>] [--ttl-hours <h>]
|
|
40
|
+
[--max-runs <n>] [--ttl-hours <h>] \
|
|
41
|
+
[--notify-target slack:<ID>] [--notify-desktop] [--notify-open-omp] --json
|
|
41
42
|
```
|
|
42
43
|
Jobs auto-expire after 72h by default (`--ttl-hours`) — set a longer TTL or a
|
|
43
44
|
`--max-runs` cap as needed. Use `--dry-run` to preview the OS entry first.
|
|
45
|
+
|
|
46
|
+
**End-of-run notifications (all opt-in, default off; failures never affect the job):**
|
|
47
|
+
- `--notify-target slack:<C|G|D|U…>` — post the run summary to Slack (needs
|
|
48
|
+
`SLACK_BOT_TOKEN`; falls back to `SLACK_HOME_CHANNEL` when no target).
|
|
49
|
+
- `--notify-desktop` — fire a native desktop notification (job id + status +
|
|
50
|
+
one-line summary). Transport per OS: **macOS → `osascript`** (the only path
|
|
51
|
+
that reliably displays on Sequoia; shown under "Script Editor", **not
|
|
52
|
+
clickable**); **Linux/Windows → node-notifier** (notify-send / SnoreToast).
|
|
53
|
+
- `--notify-open-omp` — make the notification's click open an interactive `omp`
|
|
54
|
+
session in the schedule state root (the SessionStart banner then surfaces the
|
|
55
|
+
latest result). **Requires a click-capable transport**, which on macOS means a
|
|
56
|
+
system `terminal-notifier` enabled via `OMP_NOTIFY_USE_TERMINAL_NOTIFIER=1`
|
|
57
|
+
(`brew install terminal-notifier`). Note: terminal-notifier does **not**
|
|
58
|
+
display on some macOS Sequoia builds — if notifications stop appearing,
|
|
59
|
+
unset that env to fall back to osascript (display-only). Disable desktop
|
|
60
|
+
notifications entirely with `OMP_DISABLE_DESKTOP_NOTIFY=1`.
|
|
61
|
+
|
|
62
|
+
Slack and desktop are independent and can be combined on one job.
|
|
44
63
|
4. **Confirm** by listing: `omp schedule list --json`.
|
|
45
64
|
5. **Trigger now** to test it once: `omp schedule run-now --id <id>`.
|
|
46
65
|
6. **Inspect** results: `omp schedule status --id <id> --json` (recent results
|
|
47
|
-
are also surfaced automatically at the start of future sessions).
|
|
66
|
+
are also surfaced automatically at the start of future sessions). To pull up
|
|
67
|
+
the latest run with full context by id — e.g. after seeing a desktop
|
|
68
|
+
notification titled `schedule: <id>` — run `omp schedule open <id>`, which
|
|
69
|
+
prints the latest status, summary, and the full captured output. Add `--tmux`
|
|
70
|
+
to instead drop into an interactive `omp` session (auto-wrapped in tmux) rooted
|
|
71
|
+
at the project; the SessionStart banner surfaces *recent* scheduled runs there
|
|
72
|
+
(not pinned to `<id>`) — for this id's exact output, use plain `omp schedule open <id>`.
|
|
48
73
|
7. **Remove** when done: `omp schedule remove --id <id>` (fully uninstalls the OS
|
|
49
74
|
entry; do NOT delete `.omp/state/schedule/` by hand).
|
|
50
75
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verify-byok
|
|
3
|
+
description: Verify an omp change end-to-end — static gate (build/tsc/tests/lint/catalog) plus a live BYOK run that drives Copilot/teams on a real model and captures evidence. Use before merging any PR that touches hooks, comms, team, launch, or skills.
|
|
4
|
+
argument-hint: "<branch-or-PR to verify>"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# verify-byok — evidence-based verification for omp changes
|
|
8
|
+
|
|
9
|
+
**Invocation:** `/verify-byok <branch-or-PR>`
|
|
10
|
+
|
|
11
|
+
Prove a change actually works, not just that it compiles. Two gates: a **static** gate (cheap, always) and a **live BYOK** gate (drives real Copilot CLI sessions on a Bring-Your-Own-Key model so no GitHub quota is needed). Report **real command output**, never claims. Be honest about what you did NOT test.
|
|
12
|
+
|
|
13
|
+
## When to use
|
|
14
|
+
Before merging any PR — especially ones touching `hooks/`, `scripts/*.mjs`, `src/comms`, `src/team`, `src/copilot/launch`, `src/copilot/trust`, or `.github/skills`. Anything whose behavior only appears at runtime (tmux submit keys, hook firing, trust dialog, model tool-calls) needs the live gate.
|
|
15
|
+
|
|
16
|
+
## Prerequisites (one-time, persistent)
|
|
17
|
+
- `~/.omp/.env` holds BYOK: `COPILOT_PROVIDER_BASE_URL=https://openrouter.ai/api/v1`, `COPILOT_PROVIDER_TYPE=openai`, `COPILOT_PROVIDER_API_KEY=…`, `COPILOT_MODEL=…`, `COPILOT_PROVIDER_MODEL_ID=…`. omp auto-loads it; `~/.zshrc` sourcing it makes direct `copilot` BYOK too.
|
|
18
|
+
- Free model `openai/gpt-oss-120b:free` exercises plumbing but botches structured edits/`apply_patch` and narrates instead of acting — use a capable model (`anthropic/claude-sonnet-4.5` + `COPILOT_PROVIDER_MODEL_ID=claude-sonnet-4`) when verifying that real tasks complete.
|
|
19
|
+
- Folder trust: a session only skips the "Do you trust this folder?" dialog if the cwd is in `~/.copilot/config.json#trustedFolders` (`--yolo` does NOT skip it). `omp` auto-adds it on launch; `/private/tmp` is pre-trusted.
|
|
20
|
+
|
|
21
|
+
## Static gate (run from the branch worktree)
|
|
22
|
+
```bash
|
|
23
|
+
npm run build # tsc
|
|
24
|
+
npx tsc -p tsconfig.json --noEmit # type-clean
|
|
25
|
+
npx vitest run # ALL must pass — note the count
|
|
26
|
+
node dist/src/cli.js lint:skills --root . # 0 issues
|
|
27
|
+
node dist/src/cli.js catalog validate # PASS
|
|
28
|
+
```
|
|
29
|
+
A merged-overlap PR? Confirm the test count rose (new tests survived the rebase) and old behavior's tests still pass.
|
|
30
|
+
|
|
31
|
+
## Live BYOK gate
|
|
32
|
+
Build the branch CLI first (`npm run build`); installed `omp` may be older. Drive Copilot inside tmux (each pane is a pty). **Submit with the `Enter` key name, never `C-m`** — Copilot ≥1.0.61 ignores `C-m`.
|
|
33
|
+
|
|
34
|
+
1. **Launch + reach a model:** `tmux new-session -d -s vbyok -c <dir>` → send `omp` (or `omp --madmax` for bypass) → wait for `/ commands`. Confirm the model line shows your BYOK model and `Session: 0 AIC used` (0 AI Credits = not on GitHub quota). Send a prompt, send `Enter`, confirm a real reply.
|
|
35
|
+
2. **Exercise the changed surface** — pick the user-visible behavior the change claims:
|
|
36
|
+
- hooks → tail `<cwd>/.omp/state/hooks.log` for the events firing;
|
|
37
|
+
- team → run a 2-worker team, confirm files/artifacts on disk and the script's `🎉 All N agents completed!` (read the raw stdout, not the leader's summary);
|
|
38
|
+
- cost/minify → pipe a postToolUse payload to `scripts/post-tool-use.mjs` and check `modifiedResult` + raw preserved + ledger `savedTokens` + `omp cost`.
|
|
39
|
+
3. **Capture evidence**: `tmux capture-pane -p -t <session>` plus the on-disk artifact. Keep transcripts.
|
|
40
|
+
|
|
41
|
+
## Reporting (mandatory)
|
|
42
|
+
- PASS/FAIL table with the actual captured output (model line, reply, artifact contents, ledger numbers).
|
|
43
|
+
- State the model used and that no GitHub quota was consumed.
|
|
44
|
+
- **Honest limitations**: heuristics (e.g. pane-scrape completion detection), model-quality effects (free model botching edits), anything gated/conditional, and anything you did NOT exercise.
|
|
45
|
+
- Never report "works" without exercising the user-visible surface — verify before asserting.
|
|
46
|
+
|
|
47
|
+
## Anti-patterns
|
|
48
|
+
- Trusting a subagent's "Complete." — re-run the gate yourself.
|
|
49
|
+
- `C-m` to submit to Copilot (use `Enter`).
|
|
50
|
+
- Concluding from a green build alone — runtime bugs (env propagation, trust dialog, submit keys) pass the build and fail live.
|
package/README.md
CHANGED
|
@@ -60,6 +60,82 @@ That's it.
|
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
|
63
|
+
## Architecture
|
|
64
|
+
|
|
65
|
+
oh-my-copilot is two things working together: a **shell CLI** (`omp`) that wraps and scripts the GitHub Copilot CLI, and a **Copilot plugin** that ships in-session slash skills, custom agents, and native lifecycle hooks. Both feed the same orchestration modes, the same file-based memory, and the same `.omp` state — so whether you drive from the shell, an in-session `/skill`, Slack, or cron, you hit one coherent system.
|
|
66
|
+
|
|
67
|
+
```mermaid
|
|
68
|
+
flowchart TB
|
|
69
|
+
subgraph Surfaces["① Where you drive it"]
|
|
70
|
+
SH["Shell CLI<br/><code>omp</code> / <code>omp --madmax</code>"]
|
|
71
|
+
IDE["In-session <code>/skills</code><br/>(Copilot plugin)"]
|
|
72
|
+
GW["Gateway<br/>Slack / messaging"]
|
|
73
|
+
CRON["Cron<br/><code>omp schedule</code>"]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
subgraph Copilot["② GitHub Copilot CLI (wrapped)"]
|
|
77
|
+
CP["copilot session"]
|
|
78
|
+
HK["Lifecycle hooks<br/>sessionStart · sessionEnd · agentStop<br/>pre/postToolUse · userPromptSubmitted"]
|
|
79
|
+
PS["Plugin skills + agents<br/>ralph · ralplan · team · council<br/>code-review · tdd · research · …"]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
subgraph Orchestration["③ Orchestration modes"]
|
|
83
|
+
direction LR
|
|
84
|
+
RALPH["ralph<br/>PRD verify/fix loop"]
|
|
85
|
+
UW["ultrawork<br/>parallel fan-out"]
|
|
86
|
+
UQA["ultraqa<br/>QA cycles"]
|
|
87
|
+
AP["autopilot"]
|
|
88
|
+
TEAM["team<br/>tmux multi-agent"]
|
|
89
|
+
COUNCIL["council<br/>weighted consensus"]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
subgraph Learning["④ Memory & learning loop"]
|
|
93
|
+
direction LR
|
|
94
|
+
MR["memory-review<br/>cheap model, end-of-session"]
|
|
95
|
+
PM["project-memory<br/>directives + notes"]
|
|
96
|
+
SE["self-evolve<br/>skill drafts"]
|
|
97
|
+
DL["daily-log"]
|
|
98
|
+
IM["instructions-memory<br/>→ copilot-instructions.md"]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
subgraph Store["⑤ Config & state"]
|
|
102
|
+
direction LR
|
|
103
|
+
G["~/.omp<br/>global config + .env"]
|
|
104
|
+
P[".omp/<br/>project config · memory<br/>cost · trace · mode-state"]
|
|
105
|
+
SST["~/.copilot/session-state<br/>events.jsonl transcripts"]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
SH --> CP
|
|
109
|
+
GW --> CP
|
|
110
|
+
CRON --> CP
|
|
111
|
+
IDE --> PS
|
|
112
|
+
CP --> HK
|
|
113
|
+
PS --> Orchestration
|
|
114
|
+
SH --> Orchestration
|
|
115
|
+
HK -- "agentStop drives the loop" --> Orchestration
|
|
116
|
+
Orchestration --> P
|
|
117
|
+
|
|
118
|
+
HK -- "sessionEnd (detached)" --> MR
|
|
119
|
+
SH -- "wrapper fallback (headless -p)" --> MR
|
|
120
|
+
MR -- reads transcript --> SST
|
|
121
|
+
MR -- "facts" --> PM
|
|
122
|
+
MR -- "procedures" --> SE
|
|
123
|
+
MR -- "rules (gated)" --> PM
|
|
124
|
+
PM --> IM
|
|
125
|
+
DL --> IM
|
|
126
|
+
IM -- "injected next session" --> CP
|
|
127
|
+
|
|
128
|
+
G -. config .-> MR
|
|
129
|
+
P -. config .-> MR
|
|
130
|
+
Orchestration -. cost/trace .-> P
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**The flow:** you launch a Copilot session from any surface ①. It runs through the wrapped Copilot CLI ②, where plugin hooks and skills can spin up orchestration modes ③ (ralph/ultrawork/ultraqa/team/council). When the session ends, the **learning loop** ④ fires — a cheap model reviews the transcript and writes durable **notes**, gated **directives**, and **skill drafts**, which `instructions-memory` injects into the *next* session so it starts smarter. Everything persists in layered config/state ⑤: global `~/.omp`, per-project `.omp/`, and Copilot's own session transcripts.
|
|
134
|
+
|
|
135
|
+
> The learning loop is **opt-in** (`omp config set memory-mode on`) and runs on a cheap model (`gpt-5-mini` by default) — the expensive reasoning already happened in your main session. See [docs/memory-mode.md](docs/memory-mode.md).
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
63
139
|
## Features
|
|
64
140
|
|
|
65
141
|
### Orchestration Modes
|
|
@@ -205,9 +281,10 @@ omp gateway notify --text "<msg>" [--target slack:C…|G…|D…|U… [:thread_t
|
|
|
205
281
|
omp slack serve # deprecated alias of `gateway serve --only slack`
|
|
206
282
|
omp slack doctor [--json] # deprecated alias of `gateway status --only slack`
|
|
207
283
|
omp env init [--force] # write ~/.omp/.env (interactive Slack token setup)
|
|
208
|
-
omp schedule add --id <id> --cron "*/15 * * * *" --prompt "<text>" [--allow-all-tools] [--cwd <dir>] [--model <m>] [--timeout <ms>] [--max-runs N] [--ttl-hours H] [--notify-target slack:U0123ABCD] [--dry-run]
|
|
284
|
+
omp schedule add --id <id> --cron "*/15 * * * *" --prompt "<text>" [--allow-all-tools] [--cwd <dir>] [--model <m>] [--timeout <ms>] [--max-runs N] [--ttl-hours H] [--notify-target slack:U0123ABCD] [--notify-desktop] [--notify-open-omp] [--dry-run]
|
|
209
285
|
omp schedule list # registered jobs + OS-install status
|
|
210
286
|
omp schedule status <id> # last run + result summary
|
|
287
|
+
omp schedule open <id> [--tmux] # print this id's latest status + full output (--tmux: open an omp session)
|
|
211
288
|
omp schedule run-now <id> # trigger one run immediately
|
|
212
289
|
omp schedule remove <id> # uninstall the OS entry + delete the job
|
|
213
290
|
omp goal set "<objective>" | read [--json]
|
|
@@ -227,6 +304,8 @@ Environment overrides:
|
|
|
227
304
|
- `OMP_COPILOT_BIN` — alternate `copilot` binary
|
|
228
305
|
- `OMP_BIN` — absolute path to the `omp` wrapper written into OS-scheduler entries (overrides `which omp`)
|
|
229
306
|
- `OMP_SKIP_USER_ENV` — when `1`, skip auto-loading `~/.omp/.env` (useful for hermetic CI runs)
|
|
307
|
+
- `OMP_DISABLE_DESKTOP_NOTIFY` — when set, suppress all `--notify-desktop` notifications
|
|
308
|
+
- `OMP_NOTIFY_USE_TERMINAL_NOTIFIER` — when set (+ a system `terminal-notifier` on PATH), use it for desktop notifications so the click can open omp; otherwise macOS uses `osascript` (display-only)
|
|
230
309
|
|
|
231
310
|
**Scheduled jobs** register a durable per-job entry with the OS scheduler (macOS launchd,
|
|
232
311
|
Linux systemd-user timers, or a managed `crontab` block as a cross-platform fallback) that
|
|
@@ -234,8 +313,13 @@ invokes `omp schedule run --id <id>` on the cron schedule. Each tick spawns a fr
|
|
|
234
313
|
session; overlapping runs are locked out and every run is killed at its `--timeout`
|
|
235
314
|
(default 5 min). Jobs default to **read-only** (`--allow-all-tools` is opt-in and prints a
|
|
236
315
|
warning) and auto-expire after 72h unless `--ttl-hours`/`--max-runs` say otherwise. Recent
|
|
237
|
-
run results are surfaced automatically at the start of new Copilot sessions
|
|
238
|
-
`omp schedule
|
|
316
|
+
run results are surfaced automatically at the start of new Copilot sessions, and
|
|
317
|
+
`omp schedule open <id>` prints any job's latest status + full captured output on demand.
|
|
318
|
+
Opt into end-of-run **notifications** (default off; failures never affect the job): `--notify-target slack:…`
|
|
319
|
+
posts to Slack, and `--notify-desktop` fires a native notification (job id + status + one-line
|
|
320
|
+
summary) — on macOS via `osascript` (display-only; for a clickable notification that opens omp,
|
|
321
|
+
set `OMP_NOTIFY_USE_TERMINAL_NOTIFIER=1` with a system `terminal-notifier` and add `--notify-open-omp`).
|
|
322
|
+
Always use `omp schedule remove`, never delete `.omp/state/schedule/` by hand, so the OS entry is
|
|
239
323
|
uninstalled cleanly.
|
|
240
324
|
|
|
241
325
|
### Chat bridge: drive Copilot from Slack
|
|
@@ -269,7 +353,7 @@ omp grows in vertical slices. Items aren't pinned to specific semver versions
|
|
|
269
353
|
|
|
270
354
|
### Already shipped
|
|
271
355
|
|
|
272
|
-
- **Scheduled tasks** (v0.6.0) — durable local cron: `omp schedule add --id pr-watch --cron "*/15 * * * *" --prompt "…"` plus `/schedule` in-session. Each job registers an OS-scheduler entry (launchd / systemd-user / crontab fallback) that fires a fresh agent session, survives reboot, locks out overlap, and surfaces results at the next session start.
|
|
356
|
+
- **Scheduled tasks** (v0.6.0) — durable local cron: `omp schedule add --id pr-watch --cron "*/15 * * * *" --prompt "…"` plus `/schedule` in-session. Each job registers an OS-scheduler entry (launchd / systemd-user / crontab fallback) that fires a fresh agent session, survives reboot, locks out overlap, and surfaces results at the next session start. Opt-in end-of-run notifications (`--notify-target` Slack, `--notify-desktop` native) and `omp schedule open <id>` to pull up a run's full output by id.
|
|
273
357
|
- **Chat bridge — Slack inbound** (v0.8.0) — `omp gateway` runs long-lived chat connectors that forward messages into a running Copilot tmux session and post replies back. Slack is the first connector (Socket Mode, no public URL). `omp env init` walks you through one-time token setup; tokens live in `~/.omp/.env` (auto-loaded on every invocation). See [`docs/slack-setup.md`](docs/slack-setup.md).
|
|
274
358
|
- **Slack outbound — `omp gateway notify`** — stateless REST `chat.postMessage` from any process (cron `--notify-target`, in-session `/slack <message>`, ad-hoc `omp gateway notify --text "..."`). Default destination from `SLACK_HOME_CHANNEL`; explicit `--target slack:C…/G…/D…/U…` overrides; `U…` auto-resolves to a DM via `conversations.open`.
|
|
275
359
|
- **Weighted-consensus council** — multi-model council with role weights + minority report. Via `omp council` or `/weighted-consensus`.
|
|
@@ -908,6 +908,29 @@
|
|
|
908
908
|
"notes": "Use /slack from .github/skills/slack/SKILL.md."
|
|
909
909
|
}
|
|
910
910
|
}
|
|
911
|
+
},
|
|
912
|
+
{
|
|
913
|
+
"id": "verify-byok",
|
|
914
|
+
"name": "verify-byok",
|
|
915
|
+
"title": "BYOK verification",
|
|
916
|
+
"category": "verification",
|
|
917
|
+
"summary": "Static + live BYOK verification of omp changes with evidence capture.",
|
|
918
|
+
"notes": "Maintainer verification skill: static gate plus a live Copilot/team run on a BYOK model.",
|
|
919
|
+
"defaultCommand": "verify-byok",
|
|
920
|
+
"phase1": true,
|
|
921
|
+
"sourceSkill": "verify-byok",
|
|
922
|
+
"providers": {
|
|
923
|
+
"copilot": "supported"
|
|
924
|
+
},
|
|
925
|
+
"support": {
|
|
926
|
+
"copilot": "native"
|
|
927
|
+
},
|
|
928
|
+
"providerSupport": {
|
|
929
|
+
"copilot": {
|
|
930
|
+
"state": "native",
|
|
931
|
+
"notes": "Use /verify-byok from .github/skills/verify-byok/SKILL.md."
|
|
932
|
+
}
|
|
933
|
+
}
|
|
911
934
|
}
|
|
912
935
|
]
|
|
913
936
|
}
|
|
@@ -528,6 +528,31 @@
|
|
|
528
528
|
},
|
|
529
529
|
"projection": "project-skill",
|
|
530
530
|
"phase1": true
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"name": "verify-byok",
|
|
534
|
+
"capabilityId": "verify-byok",
|
|
535
|
+
"capabilityIds": [
|
|
536
|
+
"verify-byok"
|
|
537
|
+
],
|
|
538
|
+
"source": ".github/skills/verify-byok/SKILL.md",
|
|
539
|
+
"sourcePath": ".github/skills/verify-byok/SKILL.md",
|
|
540
|
+
"canonicalPath": ".github/skills/verify-byok/SKILL.md",
|
|
541
|
+
"description": "Verify an omp change with a static gate plus a live BYOK run.",
|
|
542
|
+
"summary": "Verify an omp change with a static gate plus a live BYOK run.",
|
|
543
|
+
"support": "project-skill",
|
|
544
|
+
"aliases": [],
|
|
545
|
+
"slashCommands": [
|
|
546
|
+
"verify-byok"
|
|
547
|
+
],
|
|
548
|
+
"projections": {
|
|
549
|
+
"copilot": {
|
|
550
|
+
"command": "/verify-byok",
|
|
551
|
+
"state": "supported"
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
"projection": "project-skill",
|
|
555
|
+
"phase1": true
|
|
531
556
|
}
|
|
532
557
|
]
|
|
533
558
|
}
|
package/dist/src/cli.js
CHANGED
|
@@ -26,7 +26,8 @@ function printResult(result, json) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
function help() {
|
|
29
|
-
return `oh-my-copilot\n\nRun \`omp\` with no arguments to launch copilot (permissions bypass OFF).\nUse \`omp help\` to show this list.\n\nCommands:\n (no args) launch copilot (bypass OFF by default)\n version [--json]\n list [--json]\n setup [--dry-run] [--scope project|user] [--plugin-root <dir>] [--json]\n doctor [--json] [--copilot-bin <path>] [--skip-copilot] [--hooks]\n cost [--json] [--session <id>] [--days <n>]\n launch -- <args...>\n --madmax [args...] (bare-flag launch with permissions bypass; alias of --yolo)\n team <N:role> "<task>" [--name <name>] [--json]\n team status <name> [--json]\n team shutdown <name> [--json]\n team api claim-task --input '<json>' [--json]\n team api transition-task-status --input '<json>' [--json]\n team api send-message --input '<json>' [--json]\n team api broadcast --input '<json>' [--json]\n team api mailbox-list --input '<json>' [--json]\n team api mailbox-mark-delivered --input '<json>' [--json]\n council "<question>" [--models a,b,c|m:role:weight] [--context <text|@file>] [--rubric <text|@file>] [--synth <model>] [--probe] [--timeout <ms>] [--synth-timeout <ms>] [--min-survivors <n>] [--max-concurrency <n>] [--tmp-dir <dir>] [--json]\n comms status [--session <name>] [--json] (is copilot on + online? auto-discovers session)\n comms send --text "<prompt>" [--force] [--session <name>] [--json]\n comms recv [--wait] [--lines <n>] [--timeout <ms>] [--session <name>] [--json]\n comms ask --text "<prompt>" [--force] [--lines <n>] [--timeout <ms>] [--session <name>] [--json]\n gateway serve [--only <name>[,<name>]] (run all configured connectors; today: slack)\n gateway status [--json] [--only <name>[,...]] (per-connector readiness; no sockets opened)\n gateway doctor [--json] [--only <name>[,...]] (alias for 'gateway status')\n gateway notify --text "<msg>" [--target slack:C\\|D\\|G\\|U... [:thread_ts]] [--thread-ts <ts>] [--json]\n (one-shot outbound Slack post; falls back to SLACK_HOME_CHANNEL)\n slack serve (deprecated alias for 'gateway serve --only slack')\n slack doctor [--json] (deprecated alias for 'gateway status --only slack')\n env init [--force] (interactive: write ~/.omp/.env with Slack tokens + optional SLACK_HOME_CHANNEL)\n non-interactive: set OMP_INIT_BOT_TOKEN/OMP_INIT_APP_TOKEN/OMP_INIT_HOME_CHANNEL\n (env vars preferred over --bot-token/--app-token/--home-channel flags)\n (--session is optional when exactly one omp-<digits> tmux session is running)\n${registeredCommandHelpLines().join("\n")}\n ralph start "<task>" [--max-iterations <n>] [--session-id <id>] [--json]\n ralph status [--json]\n ralph tick [--json]\n ralph cancel [--json]\n ultrawork start "<objective>" [--task-count <n>] [--summary <s>] [--json]\n ultrawork status [--json]\n ultrawork cancel [--json]\n ultraqa start "<goal>" [--max-cycles <n>] [--json]\n ultraqa cycle pass|fail|pending [--json]\n ultraqa status [--json]\n ultraqa cancel [--json]\n schedule add --id <id> --cron "<expr>" --prompt "<text>" [--bin copilot] [--model <m>] [--cwd <dir>] [--timeout <ms>] [--max-runs <n>] [--ttl-hours <h>] [--allow-all-tools] [--notify-target slack:<ID>] [--
|
|
29
|
+
return `oh-my-copilot\n\nRun \`omp\` with no arguments to launch copilot (permissions bypass OFF).\nUse \`omp help\` to show this list.\n\nCommands:\n (no args) launch copilot (bypass OFF by default)\n version [--json]\n list [--json]\n setup [--dry-run] [--scope project|user] [--plugin-root <dir>] [--json]\n doctor [--json] [--copilot-bin <path>] [--skip-copilot] [--hooks]\n cost [--json] [--session <id>] [--days <n>]\n launch -- <args...>\n --madmax [args...] (bare-flag launch with permissions bypass; alias of --yolo)\n team <N:role> "<task>" [--name <name>] [--json]\n team status <name> [--json]\n team shutdown <name> [--json]\n team api claim-task --input '<json>' [--json]\n team api transition-task-status --input '<json>' [--json]\n team api send-message --input '<json>' [--json]\n team api broadcast --input '<json>' [--json]\n team api mailbox-list --input '<json>' [--json]\n team api mailbox-mark-delivered --input '<json>' [--json]\n council "<question>" [--models a,b,c|m:role:weight] [--context <text|@file>] [--rubric <text|@file>] [--synth <model>] [--probe] [--timeout <ms>] [--synth-timeout <ms>] [--min-survivors <n>] [--max-concurrency <n>] [--tmp-dir <dir>] [--json]\n comms status [--session <name>] [--json] (is copilot on + online? auto-discovers session)\n comms send --text "<prompt>" [--force] [--session <name>] [--json]\n comms recv [--wait] [--lines <n>] [--timeout <ms>] [--session <name>] [--json]\n comms ask --text "<prompt>" [--force] [--lines <n>] [--timeout <ms>] [--session <name>] [--json]\n gateway serve [--only <name>[,<name>]] (run all configured connectors; today: slack)\n gateway status [--json] [--only <name>[,...]] (per-connector readiness; no sockets opened)\n gateway doctor [--json] [--only <name>[,...]] (alias for 'gateway status')\n gateway notify --text "<msg>" [--target slack:C\\|D\\|G\\|U... [:thread_ts]] [--thread-ts <ts>] [--json]\n (one-shot outbound Slack post; falls back to SLACK_HOME_CHANNEL)\n slack serve (deprecated alias for 'gateway serve --only slack')\n slack doctor [--json] (deprecated alias for 'gateway status --only slack')\n env init [--force] (interactive: write ~/.omp/.env with Slack tokens + optional SLACK_HOME_CHANNEL)\n non-interactive: set OMP_INIT_BOT_TOKEN/OMP_INIT_APP_TOKEN/OMP_INIT_HOME_CHANNEL\n (env vars preferred over --bot-token/--app-token/--home-channel flags)\n (--session is optional when exactly one omp-<digits> tmux session is running)\n${registeredCommandHelpLines().join("\n")}\n ralph start "<task>" [--max-iterations <n>] [--session-id <id>] [--json]\n ralph status [--json]\n ralph tick [--json]\n ralph cancel [--json]\n ultrawork start "<objective>" [--task-count <n>] [--summary <s>] [--json]\n ultrawork status [--json]\n ultrawork cancel [--json]\n ultraqa start "<goal>" [--max-cycles <n>] [--json]\n ultraqa cycle pass|fail|pending [--json]\n ultraqa status [--json]\n ultraqa cancel [--json]\n schedule add --id <id> --cron "<expr>" --prompt "<text>" [--bin copilot] [--model <m>] [--cwd <dir>] [--timeout <ms>] [--max-runs <n>] [--ttl-hours <h>] [--allow-all-tools] [--notify-target slack:<ID>] [--notify-desktop] [--notify-open-omp] [--dry-run] [--json]
|
|
30
|
+
(--notify-desktop: native OS notification on completion [macOS uses osascript]; --notify-open-omp: click opens an omp session in the state root — needs OMP_NOTIFY_USE_TERMINAL_NOTIFIER=1 + terminal-notifier on macOS)\n schedule list [--json]\n schedule status <id> [--json]\n schedule open <id> [--tmux] [--json] (show this id's latest status + full output; --tmux instead opens an interactive omp session in the project — recent runs show via the startup banner)\n schedule run-now <id> [--json]\n schedule remove <id> [--json]\n goal set "<objective>" [--json]\n goal read [--json]\n memory sync [--json] (render goal+directives into copilot-instructions.md)\n config get [--json] | config set memory-mode on|off | config set memory-review-model <slug> | config set memory-review-min-messages <n> [--global]\n (--global writes ~/.omp/config.json; applies to every project. project .omp/config.json overrides it)\n memory-review --session <uuid|latest> [--model <slug>] [--json] (cheap-model end-of-session review; opt-in via memory-mode)\n daily-log set-goal "<text>" [--json]\n daily-log add "<text>" [--json]\n daily-log read [--days <n>] [--json]\n daily-log prune [--keep-days <n>] [--json]\n state write <key> <val> [--ttl <s>] | read|delete|status <key> | list | cleanup [--json]\n project-memory read [<id>] | index | add-note "<title>" [--body "<text>"] | add-directive "<rule>" | prune-notes --keep <n>|--older-than <days> [--json]\n trace timeline [<sessionId>] [--limit <n>] | summary [<sessionId>] | add <sessionId> <event> [<json>] [--json]\n catalog list [--json]\n catalog validate [--json]\n catalog capability <id> [--json]\n project inspect [--json]\n skill install <skill-dir> [--root <repo>] [--scope project|user] [--dry-run] [--json]\n lint:skills [--root <repo>]\n sync:dry-run [--root <repo>]\n jira:dry-run [--root <repo>]\n jira render <plan-file> [--root <repo>] [--json]\n jira apply <ticket-key-or-plan-file> --comment|--update|--transition|--link [--dry-run] [--json]\n`;
|
|
30
31
|
}
|
|
31
32
|
async function resolveExistingInputPath(value) {
|
|
32
33
|
const { existsSync } = await import("node:fs");
|
|
@@ -1363,6 +1364,8 @@ async function handleScheduleCommand(argv, json) {
|
|
|
1363
1364
|
allowAllTools: hasFlag(argv, "--allow-all-tools"),
|
|
1364
1365
|
dryRun: hasFlag(argv, "--dry-run"),
|
|
1365
1366
|
notifyTarget,
|
|
1367
|
+
notifyDesktop: hasFlag(argv, "--notify-desktop"),
|
|
1368
|
+
notifyOpenOmp: hasFlag(argv, "--notify-open-omp"),
|
|
1366
1369
|
});
|
|
1367
1370
|
return json
|
|
1368
1371
|
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
@@ -1399,10 +1402,39 @@ async function handleScheduleCommand(argv, json) {
|
|
|
1399
1402
|
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
1400
1403
|
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: result.message };
|
|
1401
1404
|
}
|
|
1405
|
+
if (command === "open" && targetId) {
|
|
1406
|
+
const r = mod.openScheduleResult(cwd, targetId);
|
|
1407
|
+
if (!r.ok)
|
|
1408
|
+
return { ok: false, exitCode: 1, output: json ? r : undefined, message: r.error };
|
|
1409
|
+
// --tmux: drop into an interactive omp session (auto-wrapped in tmux by
|
|
1410
|
+
// launchCopilot) rooted at the project. The SessionStart [SCHEDULE RESULTS]
|
|
1411
|
+
// banner surfaces RECENT unseen results across all jobs (not pinned to <id>,
|
|
1412
|
+
// and cursor-gated) — for this id's exact output use `schedule open <id>`
|
|
1413
|
+
// without --tmux. We resolve <id> first only to fail fast on a bad id.
|
|
1414
|
+
if (hasFlag(argv, "--tmux")) {
|
|
1415
|
+
const { launchCopilot } = await import("./copilot/launch.js");
|
|
1416
|
+
const result = await launchCopilot({ args: [], cwd, env: { ...process.env, OMP_FORCE_TMUX_WRAP: "1" } });
|
|
1417
|
+
return {
|
|
1418
|
+
ok: result.ok,
|
|
1419
|
+
exitCode: result.exitCode,
|
|
1420
|
+
message: result.ok ? undefined : `failed to launch omp in tmux (exit ${result.exitCode})`,
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
if (json)
|
|
1424
|
+
return { ok: true, output: r };
|
|
1425
|
+
const j = r.job;
|
|
1426
|
+
const header = `${j.id} — ${j.lastStatus ?? "(never run)"} @ ${j.lastRunAt ?? "-"}\n${j.lastSummary ?? ""}`.trim();
|
|
1427
|
+
const body = r.logContent
|
|
1428
|
+
? `\n\n--- full output (${j.lastLogPath}) ---\n${r.logContent}`
|
|
1429
|
+
: j.lastRunAt
|
|
1430
|
+
? `\n(log not found: ${j.lastLogPath ?? "n/a"})`
|
|
1431
|
+
: "\n(no run recorded yet)";
|
|
1432
|
+
return { ok: true, message: header + body };
|
|
1433
|
+
}
|
|
1402
1434
|
return {
|
|
1403
1435
|
ok: false,
|
|
1404
1436
|
exitCode: 1,
|
|
1405
|
-
message: 'Unknown schedule subcommand. Try: schedule add --id <id> --cron "<expr>" --prompt "<text>" | list | status <id> | remove <id> | run-now <id>',
|
|
1437
|
+
message: 'Unknown schedule subcommand. Try: schedule add --id <id> --cron "<expr>" --prompt "<text>" | list | status <id> | open <id> | remove <id> | run-now <id>',
|
|
1406
1438
|
};
|
|
1407
1439
|
}
|
|
1408
1440
|
function isEntrypoint() {
|