@damian87/omp 0.1.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/agents/architect.md +25 -0
- package/.github/agents/code-reviewer.md +25 -0
- package/.github/agents/designer.md +26 -0
- package/.github/agents/executor.md +24 -0
- package/.github/agents/planner.md +26 -0
- package/.github/agents/researcher.md +26 -0
- package/.github/agents/verifier.md +26 -0
- package/.github/copilot-instructions.md +20 -0
- package/.github/plugin/marketplace.json +30 -0
- package/.github/skills/caveman/SKILL.md +20 -0
- package/.github/skills/code-review/SKILL.md +22 -0
- package/.github/skills/codebase-research/SKILL.md +20 -0
- package/.github/skills/create-skill/SKILL.md +78 -0
- package/.github/skills/create-skill/references/best-practices.md +449 -0
- package/.github/skills/create-skill/references/examples.md +69 -0
- package/.github/skills/create-skill/references/progressive-disclosure.md +25 -0
- package/.github/skills/create-skill/references/skill-structure.md +55 -0
- package/.github/skills/debug/SKILL.md +22 -0
- package/.github/skills/grill-me/SKILL.md +16 -0
- package/.github/skills/jira-ticket/SKILL.md +21 -0
- package/.github/skills/omp-autopilot/SKILL.md +20 -0
- package/.github/skills/prototype/SKILL.md +21 -0
- package/.github/skills/ralph/SKILL.md +20 -0
- package/.github/skills/ralplan/SKILL.md +21 -0
- package/.github/skills/self-evolve/SKILL.md +157 -0
- package/.github/skills/tdd/SKILL.md +19 -0
- package/.github/skills/team/SKILL.md +20 -0
- package/.github/skills/ultraqa/SKILL.md +20 -0
- package/.github/skills/ultrawork/SKILL.md +20 -0
- package/.github/skills/verify/SKILL.md +20 -0
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/catalog/capabilities.json +729 -0
- package/catalog/skills-general.json +427 -0
- package/dist/src/catalog.d.ts +79 -0
- package/dist/src/catalog.js +113 -0
- package/dist/src/catalog.js.map +1 -0
- package/dist/src/cli.d.ts +9 -0
- package/dist/src/cli.js +475 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/copilot/config.d.ts +7 -0
- package/dist/src/copilot/config.js +24 -0
- package/dist/src/copilot/config.js.map +1 -0
- package/dist/src/copilot/doctor.d.ts +18 -0
- package/dist/src/copilot/doctor.js +85 -0
- package/dist/src/copilot/doctor.js.map +1 -0
- package/dist/src/copilot/launch.d.ts +14 -0
- package/dist/src/copilot/launch.js +64 -0
- package/dist/src/copilot/launch.js.map +1 -0
- package/dist/src/copilot/list.d.ts +17 -0
- package/dist/src/copilot/list.js +82 -0
- package/dist/src/copilot/list.js.map +1 -0
- package/dist/src/copilot/paths.d.ts +21 -0
- package/dist/src/copilot/paths.js +36 -0
- package/dist/src/copilot/paths.js.map +1 -0
- package/dist/src/copilot/setup.d.ts +20 -0
- package/dist/src/copilot/setup.js +90 -0
- package/dist/src/copilot/setup.js.map +1 -0
- package/dist/src/copilot/version.d.ts +13 -0
- package/dist/src/copilot/version.js +34 -0
- package/dist/src/copilot/version.js.map +1 -0
- package/dist/src/jira.d.ts +149 -0
- package/dist/src/jira.js +492 -0
- package/dist/src/jira.js.map +1 -0
- package/dist/src/lint.d.ts +11 -0
- package/dist/src/lint.js +85 -0
- package/dist/src/lint.js.map +1 -0
- package/dist/src/mcp/server.d.ts +10 -0
- package/dist/src/mcp/server.js +44 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/mcp/tools/index.d.ts +9 -0
- package/dist/src/mcp/tools/index.js +15 -0
- package/dist/src/mcp/tools/index.js.map +1 -0
- package/dist/src/mcp/tools/notepad.d.ts +2 -0
- package/dist/src/mcp/tools/notepad.js +135 -0
- package/dist/src/mcp/tools/notepad.js.map +1 -0
- package/dist/src/mcp/tools/project-memory.d.ts +2 -0
- package/dist/src/mcp/tools/project-memory.js +91 -0
- package/dist/src/mcp/tools/project-memory.js.map +1 -0
- package/dist/src/mcp/tools/shared-memory.d.ts +2 -0
- package/dist/src/mcp/tools/shared-memory.js +148 -0
- package/dist/src/mcp/tools/shared-memory.js.map +1 -0
- package/dist/src/mcp/tools/state.d.ts +2 -0
- package/dist/src/mcp/tools/state.js +107 -0
- package/dist/src/mcp/tools/state.js.map +1 -0
- package/dist/src/mcp/tools/trace.d.ts +10 -0
- package/dist/src/mcp/tools/trace.js +102 -0
- package/dist/src/mcp/tools/trace.js.map +1 -0
- package/dist/src/mcp/types.d.ts +29 -0
- package/dist/src/mcp/types.js +7 -0
- package/dist/src/mcp/types.js.map +1 -0
- package/dist/src/mode-state/index.d.ts +4 -0
- package/dist/src/mode-state/index.js +5 -0
- package/dist/src/mode-state/index.js.map +1 -0
- package/dist/src/mode-state/paths.d.ts +5 -0
- package/dist/src/mode-state/paths.js +29 -0
- package/dist/src/mode-state/paths.js.map +1 -0
- package/dist/src/mode-state/ralph.d.ts +25 -0
- package/dist/src/mode-state/ralph.js +44 -0
- package/dist/src/mode-state/ralph.js.map +1 -0
- package/dist/src/mode-state/ultraqa.d.ts +26 -0
- package/dist/src/mode-state/ultraqa.js +51 -0
- package/dist/src/mode-state/ultraqa.js.map +1 -0
- package/dist/src/mode-state/ultrawork.d.ts +20 -0
- package/dist/src/mode-state/ultrawork.js +34 -0
- package/dist/src/mode-state/ultrawork.js.map +1 -0
- package/dist/src/project.d.ts +29 -0
- package/dist/src/project.js +101 -0
- package/dist/src/project.js.map +1 -0
- package/dist/src/skills.d.ts +17 -0
- package/dist/src/skills.js +61 -0
- package/dist/src/skills.js.map +1 -0
- package/dist/src/sync.d.ts +6 -0
- package/dist/src/sync.js +27 -0
- package/dist/src/sync.js.map +1 -0
- package/dist/src/team/api.d.ts +20 -0
- package/dist/src/team/api.js +55 -0
- package/dist/src/team/api.js.map +1 -0
- package/dist/src/team/heartbeat.d.ts +4 -0
- package/dist/src/team/heartbeat.js +27 -0
- package/dist/src/team/heartbeat.js.map +1 -0
- package/dist/src/team/idle-nudge.d.ts +27 -0
- package/dist/src/team/idle-nudge.js +60 -0
- package/dist/src/team/idle-nudge.js.map +1 -0
- package/dist/src/team/inbox.d.ts +3 -0
- package/dist/src/team/inbox.js +16 -0
- package/dist/src/team/inbox.js.map +1 -0
- package/dist/src/team/index.d.ts +11 -0
- package/dist/src/team/index.js +12 -0
- package/dist/src/team/index.js.map +1 -0
- package/dist/src/team/outbox.d.ts +14 -0
- package/dist/src/team/outbox.js +82 -0
- package/dist/src/team/outbox.js.map +1 -0
- package/dist/src/team/runtime.d.ts +84 -0
- package/dist/src/team/runtime.js +243 -0
- package/dist/src/team/runtime.js.map +1 -0
- package/dist/src/team/state-paths.d.ts +31 -0
- package/dist/src/team/state-paths.js +54 -0
- package/dist/src/team/state-paths.js.map +1 -0
- package/dist/src/team/task-store.d.ts +41 -0
- package/dist/src/team/task-store.js +153 -0
- package/dist/src/team/task-store.js.map +1 -0
- package/dist/src/team/tmux.d.ts +26 -0
- package/dist/src/team/tmux.js +87 -0
- package/dist/src/team/tmux.js.map +1 -0
- package/dist/src/team/types.d.ts +45 -0
- package/dist/src/team/types.js +2 -0
- package/dist/src/team/types.js.map +1 -0
- package/dist/src/team/worker-bootstrap.d.ts +8 -0
- package/dist/src/team/worker-bootstrap.js +52 -0
- package/dist/src/team/worker-bootstrap.js.map +1 -0
- package/docs/copilot-distribution.md +100 -0
- package/docs/general-skills.md +76 -0
- package/docs/jira.md +64 -0
- package/docs/self-evolve.md +22 -0
- package/hooks/hooks.json +74 -0
- package/package.json +58 -0
- package/plugin.json +14 -0
- package/scripts/error.mjs +31 -0
- package/scripts/lib/hook-output.mjs +30 -0
- package/scripts/lib/stdin.mjs +29 -0
- package/scripts/post-tool-use.mjs +31 -0
- package/scripts/pre-tool-use.mjs +30 -0
- package/scripts/prompt-submit.mjs +66 -0
- package/scripts/session-end.mjs +29 -0
- package/scripts/session-start.mjs +33 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
export function taskFilePath(tasksDir, taskId) {
|
|
4
|
+
return join(tasksDir, `${taskId}.json`);
|
|
5
|
+
}
|
|
6
|
+
export function taskLockPath(tasksDir, taskId) {
|
|
7
|
+
return join(tasksDir, `${taskId}.lock`);
|
|
8
|
+
}
|
|
9
|
+
export function writeTask(taskPath, task) {
|
|
10
|
+
mkdirSync(dirname(taskPath), { recursive: true });
|
|
11
|
+
const tmp = `${taskPath}.tmp.${process.pid}.${Date.now()}`;
|
|
12
|
+
writeFileSync(tmp, JSON.stringify(task, null, 2), "utf8");
|
|
13
|
+
renameSync(tmp, taskPath);
|
|
14
|
+
}
|
|
15
|
+
export function readTask(taskPath) {
|
|
16
|
+
if (!existsSync(taskPath))
|
|
17
|
+
return undefined;
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(readFileSync(taskPath, "utf8"));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function listTasks(tasksDir) {
|
|
26
|
+
if (!existsSync(tasksDir))
|
|
27
|
+
return [];
|
|
28
|
+
const out = [];
|
|
29
|
+
for (const entry of readdirSync(tasksDir, { withFileTypes: true })) {
|
|
30
|
+
if (!entry.isFile() || !entry.name.endsWith(".json"))
|
|
31
|
+
continue;
|
|
32
|
+
const t = readTask(join(tasksDir, entry.name));
|
|
33
|
+
if (t)
|
|
34
|
+
out.push(t);
|
|
35
|
+
}
|
|
36
|
+
return out.sort((a, b) => a.id.localeCompare(b.id));
|
|
37
|
+
}
|
|
38
|
+
function openLockExclusive(lockPath, worker) {
|
|
39
|
+
try {
|
|
40
|
+
const fd = openSync(lockPath, "wx");
|
|
41
|
+
try {
|
|
42
|
+
writeFileSync(lockPath, JSON.stringify({ owner: worker, pid: process.pid, claimedAt: new Date().toISOString() }));
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
closeSync(fd);
|
|
46
|
+
}
|
|
47
|
+
return fd;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function tryClaimTask(opts) {
|
|
54
|
+
const path = taskFilePath(opts.tasksDir, opts.taskId);
|
|
55
|
+
const task = readTask(path);
|
|
56
|
+
if (!task)
|
|
57
|
+
return { ok: false, reason: `task ${opts.taskId} not found` };
|
|
58
|
+
if (task.status !== "pending") {
|
|
59
|
+
return { ok: false, reason: `task ${opts.taskId} status=${task.status}` };
|
|
60
|
+
}
|
|
61
|
+
const lockPath = taskLockPath(opts.tasksDir, opts.taskId);
|
|
62
|
+
let fd = openLockExclusive(lockPath, opts.worker);
|
|
63
|
+
if (fd === undefined) {
|
|
64
|
+
// Lock exists. Re-read task status: if still pending, the lock is orphan
|
|
65
|
+
// (previous worker crashed between lock-acquire and task-write). Force-claim.
|
|
66
|
+
const recheck = readTask(path);
|
|
67
|
+
if (recheck?.status !== "pending") {
|
|
68
|
+
return { ok: false, reason: `task ${opts.taskId} status=${recheck?.status ?? "missing"}` };
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
unlinkSync(lockPath);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// ignore: race with another claimer; the second openSync will arbitrate
|
|
75
|
+
}
|
|
76
|
+
fd = openLockExclusive(lockPath, opts.worker);
|
|
77
|
+
if (fd === undefined)
|
|
78
|
+
return { ok: false, reason: "concurrent claim race" };
|
|
79
|
+
}
|
|
80
|
+
const claimToken = `${opts.worker}-${Date.now()}-${Math.floor(Math.random() * 1_000_000)}`;
|
|
81
|
+
const updated = {
|
|
82
|
+
...task,
|
|
83
|
+
status: "in_progress",
|
|
84
|
+
owner: opts.worker,
|
|
85
|
+
startedAt: new Date().toISOString(),
|
|
86
|
+
claimToken,
|
|
87
|
+
};
|
|
88
|
+
writeTask(path, updated);
|
|
89
|
+
// Optimistic CAS verification: re-read the task and confirm OUR claimToken
|
|
90
|
+
// landed. If a concurrent orphan-stealer raced us, their writeTask may have
|
|
91
|
+
// overwritten ours (writeTask is rename-atomic, so the last writer wins).
|
|
92
|
+
// Both workers' lock-acquire could succeed if B unlinks A's freshly-created
|
|
93
|
+
// lock between A's openSync and A's writeTask. The verify is the
|
|
94
|
+
// ground-truth tiebreaker — only the worker whose claimToken is currently
|
|
95
|
+
// persisted owns the task.
|
|
96
|
+
const verified = readTask(path);
|
|
97
|
+
if (verified?.claimToken !== claimToken) {
|
|
98
|
+
return { ok: false, reason: "concurrent claim overwrote ours; retry" };
|
|
99
|
+
}
|
|
100
|
+
return { ok: true, task: updated, claimToken };
|
|
101
|
+
}
|
|
102
|
+
export function clearAllLocks(tasksDir) {
|
|
103
|
+
return clearAllLocksDetailed(tasksDir).removed;
|
|
104
|
+
}
|
|
105
|
+
export function clearAllLocksDetailed(tasksDir) {
|
|
106
|
+
if (!existsSync(tasksDir))
|
|
107
|
+
return { removed: 0, failures: [] };
|
|
108
|
+
const failures = [];
|
|
109
|
+
let removed = 0;
|
|
110
|
+
for (const entry of readdirSync(tasksDir)) {
|
|
111
|
+
if (!entry.endsWith(".lock"))
|
|
112
|
+
continue;
|
|
113
|
+
const target = join(tasksDir, entry);
|
|
114
|
+
try {
|
|
115
|
+
unlinkSync(target);
|
|
116
|
+
removed++;
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
failures.push({ path: target, error: err instanceof Error ? err.message : String(err) });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { removed, failures };
|
|
123
|
+
}
|
|
124
|
+
const TERMINAL = ["completed", "failed"];
|
|
125
|
+
export function transitionTask(opts) {
|
|
126
|
+
const path = taskFilePath(opts.tasksDir, opts.taskId);
|
|
127
|
+
const task = readTask(path);
|
|
128
|
+
if (!task)
|
|
129
|
+
return { ok: false, reason: `task ${opts.taskId} not found` };
|
|
130
|
+
if (task.status !== opts.from) {
|
|
131
|
+
return { ok: false, reason: `task ${opts.taskId} status=${task.status}, expected ${opts.from}` };
|
|
132
|
+
}
|
|
133
|
+
if (task.claimToken && task.claimToken !== opts.claimToken) {
|
|
134
|
+
return { ok: false, reason: "claim token mismatch" };
|
|
135
|
+
}
|
|
136
|
+
const updated = {
|
|
137
|
+
...task,
|
|
138
|
+
status: opts.to,
|
|
139
|
+
result: opts.result ?? task.result,
|
|
140
|
+
finishedAt: TERMINAL.includes(opts.to) ? new Date().toISOString() : task.finishedAt,
|
|
141
|
+
};
|
|
142
|
+
writeTask(path, updated);
|
|
143
|
+
if (TERMINAL.includes(opts.to)) {
|
|
144
|
+
try {
|
|
145
|
+
unlinkSync(taskLockPath(opts.tasksDir, opts.taskId));
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// ignore: lock may already be gone
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return { ok: true, task: updated };
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=task-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-store.js","sourceRoot":"","sources":["../../../src/team/task-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface TmuxResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
status: number;
|
|
5
|
+
}
|
|
6
|
+
export type TmuxRunner = (args: string[]) => TmuxResult;
|
|
7
|
+
export declare function tmuxExec(args: string[]): TmuxResult;
|
|
8
|
+
export declare function paneLooksReady(captured: string): boolean;
|
|
9
|
+
export declare function paneHasActiveTask(captured: string): boolean;
|
|
10
|
+
export interface TmuxApi {
|
|
11
|
+
newSession(session: string, cwd: string): TmuxResult;
|
|
12
|
+
splitWindow(target: string, cwd: string): TmuxResult;
|
|
13
|
+
sendKeys(target: string, ...keys: string[]): TmuxResult;
|
|
14
|
+
sendText(target: string, text: string): TmuxResult;
|
|
15
|
+
capturePane(target: string, lines?: number): TmuxResult;
|
|
16
|
+
killPane(target: string): TmuxResult;
|
|
17
|
+
killSession(session: string): TmuxResult;
|
|
18
|
+
paneDead(target: string): boolean;
|
|
19
|
+
sessionExists(session: string): boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function makeTmux(runner?: TmuxRunner): TmuxApi;
|
|
22
|
+
export interface SendToWorkerOptions {
|
|
23
|
+
rounds?: number;
|
|
24
|
+
delayMs?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function sendToWorker(api: TmuxApi, target: string, text: string, options?: SendToWorkerOptions): Promise<boolean>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
export function tmuxExec(args) {
|
|
3
|
+
const r = spawnSync("tmux", args, { encoding: "utf8" });
|
|
4
|
+
return {
|
|
5
|
+
stdout: r.stdout ?? "",
|
|
6
|
+
stderr: r.stderr ?? "",
|
|
7
|
+
status: r.status ?? 1,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
const PROMPT_RE = /(?:^|\s)(?:[│┃║▌▐▏▕╎┆┊]\s*)?[›>❯$#%]\s*$/;
|
|
11
|
+
const ACTIVE_HINTS = [
|
|
12
|
+
/esc to interrupt/i,
|
|
13
|
+
/running\s*[…\.]/,
|
|
14
|
+
/background terminal/i,
|
|
15
|
+
/tool call in progress/i,
|
|
16
|
+
];
|
|
17
|
+
export function paneLooksReady(captured) {
|
|
18
|
+
if (!captured.trim())
|
|
19
|
+
return false;
|
|
20
|
+
const lines = captured.split("\n");
|
|
21
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
22
|
+
const line = lines[i];
|
|
23
|
+
if (line.trim().length === 0)
|
|
24
|
+
continue;
|
|
25
|
+
return PROMPT_RE.test(line);
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
export function paneHasActiveTask(captured) {
|
|
30
|
+
return ACTIVE_HINTS.some((re) => re.test(captured));
|
|
31
|
+
}
|
|
32
|
+
export function makeTmux(runner = tmuxExec) {
|
|
33
|
+
return {
|
|
34
|
+
newSession(session, cwd) {
|
|
35
|
+
return runner(["new-session", "-d", "-P", "-F", "#S:0 #{pane_id}", "-s", session, "-c", cwd]);
|
|
36
|
+
},
|
|
37
|
+
splitWindow(target, cwd) {
|
|
38
|
+
return runner(["split-window", "-h", "-t", target, "-d", "-P", "-F", "#{pane_id}", "-c", cwd]);
|
|
39
|
+
},
|
|
40
|
+
sendKeys(target, ...keys) {
|
|
41
|
+
return runner(["send-keys", "-t", target, ...keys]);
|
|
42
|
+
},
|
|
43
|
+
sendText(target, text) {
|
|
44
|
+
return runner(["send-keys", "-t", target, "-l", "--", text]);
|
|
45
|
+
},
|
|
46
|
+
capturePane(target, lines = 80) {
|
|
47
|
+
return runner(["capture-pane", "-t", target, "-p", "-S", `-${lines}`]);
|
|
48
|
+
},
|
|
49
|
+
killPane(target) {
|
|
50
|
+
return runner(["kill-pane", "-t", target]);
|
|
51
|
+
},
|
|
52
|
+
killSession(session) {
|
|
53
|
+
return runner(["kill-session", "-t", session]);
|
|
54
|
+
},
|
|
55
|
+
paneDead(target) {
|
|
56
|
+
const r = runner(["display-message", "-t", target, "-p", "#{pane_dead}"]);
|
|
57
|
+
return r.stdout.trim() === "1";
|
|
58
|
+
},
|
|
59
|
+
sessionExists(session) {
|
|
60
|
+
const r = runner(["has-session", "-t", session]);
|
|
61
|
+
return r.status === 0;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function sleep(ms) {
|
|
66
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
67
|
+
}
|
|
68
|
+
export async function sendToWorker(api, target, text, options = {}) {
|
|
69
|
+
const rounds = options.rounds ?? 6;
|
|
70
|
+
const delayMs = options.delayMs ?? 150;
|
|
71
|
+
const payload = text.length > 200 ? text.slice(0, 200) : text;
|
|
72
|
+
api.sendText(target, payload);
|
|
73
|
+
for (let i = 0; i < rounds; i++) {
|
|
74
|
+
api.sendKeys(target, "C-m");
|
|
75
|
+
await sleep(delayMs);
|
|
76
|
+
const captured = api.capturePane(target, 5).stdout;
|
|
77
|
+
if (!captured.includes(payload))
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
// adaptive fallback: kill-line then retry once
|
|
81
|
+
api.sendKeys(target, "C-u");
|
|
82
|
+
await sleep(delayMs);
|
|
83
|
+
api.sendText(target, payload);
|
|
84
|
+
api.sendKeys(target, "C-m");
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=tmux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux.js","sourceRoot":"","sources":["../../../src/team/tmux.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAU/C,MAAM,UAAU,QAAQ,CAAC,IAAc;IACrC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACxD,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;QACtB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;QACtB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;KACtB,CAAC;AACJ,CAAC;AAED,MAAM,SAAS,GAAG,0CAA0C,CAAC;AAC7D,MAAM,YAAY,GAAG;IACnB,mBAAmB;IACnB,iBAAiB;IACjB,sBAAsB;IACtB,wBAAwB;CACzB,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACvC,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtD,CAAC;AAcD,MAAM,UAAU,QAAQ,CAAC,SAAqB,QAAQ;IACpD,OAAO;QACL,UAAU,CAAC,OAAO,EAAE,GAAG;YACrB,OAAO,MAAM,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAChG,CAAC;QACD,WAAW,CAAC,MAAM,EAAE,GAAG;YACrB,OAAO,MAAM,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACjG,CAAC;QACD,QAAQ,CAAC,MAAM,EAAE,GAAG,IAAI;YACtB,OAAO,MAAM,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QACtD,CAAC;QACD,QAAQ,CAAC,MAAM,EAAE,IAAI;YACnB,OAAO,MAAM,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,WAAW,CAAC,MAAM,EAAE,KAAK,GAAG,EAAE;YAC5B,OAAO,MAAM,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC;QACD,QAAQ,CAAC,MAAM;YACb,OAAO,MAAM,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,WAAW,CAAC,OAAO;YACjB,OAAO,MAAM,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,QAAQ,CAAC,MAAM;YACb,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,iBAAiB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;YAC1E,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC;QACjC,CAAC;QACD,aAAa,CAAC,OAAO;YACnB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;YACjD,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAY,EACZ,MAAc,EACd,IAAY,EACZ,UAA+B,EAAE;IAEjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC5B,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACnD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;IAC/C,CAAC;IACD,+CAA+C;IAC/C,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5B,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;IACrB,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type WorkerRole = "claude" | "codex" | "gemini" | string;
|
|
2
|
+
export type TaskStatus = "pending" | "in_progress" | "completed" | "failed";
|
|
3
|
+
export interface Task {
|
|
4
|
+
id: string;
|
|
5
|
+
description: string;
|
|
6
|
+
status: TaskStatus;
|
|
7
|
+
owner?: string;
|
|
8
|
+
result?: string;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
startedAt?: string;
|
|
11
|
+
finishedAt?: string;
|
|
12
|
+
claimToken?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface Worker {
|
|
15
|
+
name: string;
|
|
16
|
+
role: WorkerRole;
|
|
17
|
+
paneId?: string;
|
|
18
|
+
taskId?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface TeamConfig {
|
|
21
|
+
name: string;
|
|
22
|
+
task: string;
|
|
23
|
+
role: WorkerRole;
|
|
24
|
+
workerCount: number;
|
|
25
|
+
tmuxSession: string;
|
|
26
|
+
workers: Worker[];
|
|
27
|
+
cwd: string;
|
|
28
|
+
createdAt: string;
|
|
29
|
+
}
|
|
30
|
+
export interface Heartbeat {
|
|
31
|
+
pid: number;
|
|
32
|
+
workerName: string;
|
|
33
|
+
teamName: string;
|
|
34
|
+
lastPollAt: string;
|
|
35
|
+
turnCount: number;
|
|
36
|
+
alive: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface OutboxMessage {
|
|
39
|
+
type: "task_complete" | "task_failed" | "progress" | string;
|
|
40
|
+
taskId?: string;
|
|
41
|
+
status?: TaskStatus;
|
|
42
|
+
result?: string;
|
|
43
|
+
detail?: string;
|
|
44
|
+
timestamp: string;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/team/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export function buildInboxMarkdown(opts) {
|
|
2
|
+
const claimInput = JSON.stringify({
|
|
3
|
+
team_name: opts.teamName,
|
|
4
|
+
task_id: opts.task.id,
|
|
5
|
+
worker: opts.workerName,
|
|
6
|
+
cwd: opts.cwd,
|
|
7
|
+
});
|
|
8
|
+
const completeInputTemplate = JSON.stringify({
|
|
9
|
+
team_name: opts.teamName,
|
|
10
|
+
task_id: opts.task.id,
|
|
11
|
+
worker: opts.workerName,
|
|
12
|
+
cwd: opts.cwd,
|
|
13
|
+
from: "in_progress",
|
|
14
|
+
to: "completed",
|
|
15
|
+
claim_token: "<claim_token>",
|
|
16
|
+
result: "Summary: ...",
|
|
17
|
+
});
|
|
18
|
+
const failInputTemplate = JSON.stringify({
|
|
19
|
+
team_name: opts.teamName,
|
|
20
|
+
task_id: opts.task.id,
|
|
21
|
+
worker: opts.workerName,
|
|
22
|
+
cwd: opts.cwd,
|
|
23
|
+
from: "in_progress",
|
|
24
|
+
to: "failed",
|
|
25
|
+
claim_token: "<claim_token>",
|
|
26
|
+
});
|
|
27
|
+
return [
|
|
28
|
+
"## REQUIRED: Task Lifecycle Commands",
|
|
29
|
+
"You MUST run these commands. Do NOT skip any step.",
|
|
30
|
+
"",
|
|
31
|
+
"1. Claim your task:",
|
|
32
|
+
` omp team api claim-task --input '${claimInput}' --json`,
|
|
33
|
+
" Save the claim_token from the response.",
|
|
34
|
+
"",
|
|
35
|
+
"2. Do the work described below.",
|
|
36
|
+
"",
|
|
37
|
+
"3. On completion (use claim_token from step 1):",
|
|
38
|
+
` omp team api transition-task-status --input '${completeInputTemplate}' --json`,
|
|
39
|
+
"",
|
|
40
|
+
"4. On failure:",
|
|
41
|
+
` omp team api transition-task-status --input '${failInputTemplate}' --json`,
|
|
42
|
+
"",
|
|
43
|
+
"## Task Assignment",
|
|
44
|
+
`Task ID: ${opts.task.id}`,
|
|
45
|
+
`Worker: ${opts.workerName}`,
|
|
46
|
+
"",
|
|
47
|
+
"## Description",
|
|
48
|
+
opts.task.description,
|
|
49
|
+
"",
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=worker-bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-bootstrap.js","sourceRoot":"","sources":["../../../src/team/worker-bootstrap.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,kBAAkB,CAAC,IAAkB;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,SAAS,EAAE,IAAI,CAAC,QAAQ;QACxB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;QACrB,MAAM,EAAE,IAAI,CAAC,UAAU;QACvB,GAAG,EAAE,IAAI,CAAC,GAAG;KACd,CAAC,CAAC;IACH,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,CAAC;QAC3C,SAAS,EAAE,IAAI,CAAC,QAAQ;QACxB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;QACrB,MAAM,EAAE,IAAI,CAAC,UAAU;QACvB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,IAAI,EAAE,aAAa;QACnB,EAAE,EAAE,WAAW;QACf,WAAW,EAAE,eAAe;QAC5B,MAAM,EAAE,cAAc;KACvB,CAAC,CAAC;IACH,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC;QACvC,SAAS,EAAE,IAAI,CAAC,QAAQ;QACxB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;QACrB,MAAM,EAAE,IAAI,CAAC,UAAU;QACvB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,IAAI,EAAE,aAAa;QACnB,EAAE,EAAE,QAAQ;QACZ,WAAW,EAAE,eAAe;KAC7B,CAAC,CAAC;IACH,OAAO;QACL,sCAAsC;QACtC,oDAAoD;QACpD,EAAE;QACF,qBAAqB;QACrB,uCAAuC,UAAU,UAAU;QAC3D,4CAA4C;QAC5C,EAAE;QACF,iCAAiC;QACjC,EAAE;QACF,iDAAiD;QACjD,mDAAmD,qBAAqB,UAAU;QAClF,EAAE;QACF,gBAAgB;QAChB,mDAAmD,iBAAiB,UAAU;QAC9E,EAAE;QACF,oBAAoB;QACpB,YAAY,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;QAC1B,WAAW,IAAI,CAAC,UAAU,EAAE;QAC5B,EAAE;QACF,gBAAgB;QAChB,IAAI,CAAC,IAAI,CAAC,WAAW;QACrB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Copilot skill distribution
|
|
2
|
+
|
|
3
|
+
## Bundle install (Copilot CLI plugin)
|
|
4
|
+
|
|
5
|
+
The future-proof path: register the marketplace once, then install the bundled 17-skill plugin.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
copilot plugin marketplace add damian87x/oh-my-copilot
|
|
9
|
+
copilot plugin install oh-my-copilot@oh-my-copilot
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Backed by root `plugin.json` with `"skills": ".github/skills/"` — no skills moved, no duplication. Backed by `.github/plugin/marketplace.json` listing the single self-hosted plugin. Requires Copilot CLI v1.0.48+.
|
|
13
|
+
|
|
14
|
+
The shorter `owner/repo` form also works today but Copilot CLI prints a deprecation notice and will remove it in a future release:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
copilot plugin install damian87x/oh-my-copilot # works today, deprecated
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The per-skill flows below remain valid for cases where you only want one skill or are on an older Copilot CLI.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Per-skill install
|
|
25
|
+
|
|
26
|
+
Use the agent-skill package shape as the default install surface:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
skills/<skill-name>/SKILL.md
|
|
30
|
+
skills/<skill-name>/references/*
|
|
31
|
+
skills/<skill-name>/scripts/*
|
|
32
|
+
skills/<skill-name>/assets/*
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For Copilot project install, copy the skill directory to:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
.github/skills/<skill-name>/SKILL.md
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For Copilot personal install, copy the skill directory to:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
~/.copilot/skills/<skill-name>/SKILL.md
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The catalog is optional metadata for this repository's built-in general skill list. Copilot discovers skills from the skill directories themselves.
|
|
48
|
+
|
|
49
|
+
## Native oh-my-copilot installer
|
|
50
|
+
|
|
51
|
+
Use `omcc skill install` when you want the same simple OMC-style copy flow, or as a fallback on machines without a new enough GitHub CLI. The bin is `omcc` (not `omc`) to avoid colliding with the `oh-my-claudecode` global command:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
omcc skill install ./skills/my-skill --dry-run
|
|
55
|
+
omcc skill install ./skills/my-skill --root /path/to/repo
|
|
56
|
+
omcc skill install ./skills/my-skill --scope user
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The installer validates `SKILL.md` frontmatter, previews copied files with `--dry-run`, preserves optional resource folders, and writes to `.github/skills/<name>` by default.
|
|
60
|
+
|
|
61
|
+
## GitHub CLI path
|
|
62
|
+
|
|
63
|
+
GitHub documents `gh skill` for searching, previewing, installing, updating, and publishing skills. It requires GitHub CLI `2.90.0` or newer.
|
|
64
|
+
|
|
65
|
+
Useful commands:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
gh skill preview OWNER/REPOSITORY SKILL
|
|
69
|
+
gh skill install OWNER/REPOSITORY SKILL
|
|
70
|
+
gh skill install OWNER/REPOSITORY SKILL --scope user
|
|
71
|
+
gh skill publish --dry-run
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Local note: this machine has `gh 2.92.0`, so `gh skill` is available. Do not make `gh skill` the only install path; keep `omcc skill install` as the fallback and repo-native dry-run surface.
|
|
75
|
+
|
|
76
|
+
## OMC-like installer shape
|
|
77
|
+
|
|
78
|
+
The `oh-my-copilot` installer should stay thin:
|
|
79
|
+
|
|
80
|
+
1. Fetch a skill directory from a GitHub repository.
|
|
81
|
+
2. Validate `SKILL.md` frontmatter: `name` and `description`.
|
|
82
|
+
3. Preview the file tree before writing.
|
|
83
|
+
4. Copy the directory unchanged to `.github/skills/<name>` for project scope or `~/.copilot/skills/<name>` for user scope.
|
|
84
|
+
5. Preserve optional `references/`, `scripts/`, and `assets/`.
|
|
85
|
+
6. Write provenance metadata only if needed for updates; do not require catalog entries.
|
|
86
|
+
|
|
87
|
+
Dry-run output should show the target path and files that would be written.
|
|
88
|
+
|
|
89
|
+
## Not a GitHub App Copilot Extension
|
|
90
|
+
|
|
91
|
+
GitHub App-based Copilot Extensions are not the right path for this repo. GitHub sunset that extension type in favor of MCP servers: new creation was blocked in September 2025 and existing GitHub App-based Copilot Extensions were disabled in November 2025.
|
|
92
|
+
|
|
93
|
+
If this project later needs live tools beyond static skills, prefer an MCP server. If it needs IDE UI integration, consider a VS Code extension. Keep project skills as plain skill packages.
|
|
94
|
+
|
|
95
|
+
## References
|
|
96
|
+
|
|
97
|
+
- GitHub Docs: Adding agent skills for GitHub Copilot — https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/create-skills
|
|
98
|
+
- GitHub Docs: About agent skills — https://docs.github.com/en/copilot/concepts/agents/about-agent-skills
|
|
99
|
+
- GitHub Docs: Running GitHub Copilot CLI programmatically — https://docs.github.com/en/copilot/how-tos/copilot-cli/automate-copilot-cli/run-cli-programmatically
|
|
100
|
+
- GitHub Changelog: Sunset notice for GitHub App-based Copilot Extensions — https://github.blog/changelog/2025-09-24-deprecate-github-copilot-extensions-github-apps/
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# General Skills MVP
|
|
2
|
+
|
|
3
|
+
The canonical skill source is the repo-local `.github/skills` directory. This is the GitHub Copilot project-skill location, so no `.agents` or `.claude` compatibility layer is needed.
|
|
4
|
+
|
|
5
|
+
## Canonical lite skills
|
|
6
|
+
|
|
7
|
+
| Skill | Capability IDs | Purpose |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `/codebase-research` | `codebase-research`, `research.codebase` | Read repo evidence before planning or asking. |
|
|
10
|
+
| `/grill-me` | `grill-me`, `planning.challenge` | Ask one sharp clarification question when ambiguity remains. |
|
|
11
|
+
| `/ralplan` | `ralplan`, `planning.consensus` | Produce implementation-ready plan, tests, and risks. |
|
|
12
|
+
| `/team` | `team`, `execution.parallel` | Split approved work into parallel lanes. |
|
|
13
|
+
| `/ralph` | `ralph`, `execution.single-owner` | Single-owner execute-fix-verify loop. |
|
|
14
|
+
| `/ultrawork` | `ultrawork`, `execution.parallel` | Batch many independent small tasks. |
|
|
15
|
+
| `/ultraqa` | `ultraqa`, `qa.behavioral` | Adversarial behavior and regression QA. |
|
|
16
|
+
| `/omc-autopilot` | `omc-autopilot`, `execution.autonomous` | Lightweight end-to-end flow across the other skills. (Renamed from `/autopilot` to avoid Copilot CLI built-in collision.) |
|
|
17
|
+
| `/code-review` | `code-review`, `review.independent` | Review completed changes before merge or handoff. |
|
|
18
|
+
| `/verify` | `verify`, `verification.evidence` | Prove completion claims with evidence. |
|
|
19
|
+
| `/jira-ticket` | `jira-ticket`, `tracker.ticket` | Render Jira create/comment/safe-update payloads. |
|
|
20
|
+
| `/prototype` | `prototype`, `design.prototype` | Build disposable experiments for design questions. |
|
|
21
|
+
| `/caveman` | `caveman`, `communication.compact` | Ultra-compact response mode. |
|
|
22
|
+
| `/debug` | `debug`, `debug.systematic` | Reproduce, diagnose, fix, and regression-test bugs. |
|
|
23
|
+
| `/tdd` | `tdd`, `testing.tdd` | Red-green-refactor for behavior changes. |
|
|
24
|
+
|
|
25
|
+
## Repo-local layout
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
oh-my-copilot/
|
|
29
|
+
.github/skills/<skill>/SKILL.md # Copilot project skill source of truth
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Rules:
|
|
33
|
+
|
|
34
|
+
- Edit `.github/skills/*/SKILL.md` first.
|
|
35
|
+
- Use `/skill-name` invocation language.
|
|
36
|
+
- Do not create `.agents` or `.claude` skill roots in this repo.
|
|
37
|
+
- Do not generate `.github/copilot/...` wrappers; Copilot reads project skills directly.
|
|
38
|
+
- Keep each `SKILL.md` small: YAML frontmatter (`name`, `description`) plus focused Markdown instructions.
|
|
39
|
+
- Optional `references/`, `scripts/`, or `assets/` may live beside `SKILL.md` when a fetched skill needs progressive disclosure.
|
|
40
|
+
- Do not add runtime state to the lite skills.
|
|
41
|
+
|
|
42
|
+
## Fetched skills
|
|
43
|
+
|
|
44
|
+
Skills fetched in the common `skills/<name>/SKILL.md` package shape can be moved directly to `.github/skills/<name>/SKILL.md`.
|
|
45
|
+
The catalog is optional metadata for the built-in general skill list; Copilot discovery uses `.github/skills` itself.
|
|
46
|
+
|
|
47
|
+
## Capability semantics
|
|
48
|
+
|
|
49
|
+
`providerSupport.copilot.state = native` means Copilot can read the repo-local slash skill from `.github/skills`.
|
|
50
|
+
It does not imply a durable execution runtime. Phase 1 execution skills such as `/team`, `/ralph`, `/ultrawork`, and `/omc-autopilot` are plain project-skill instructions, not persisted runtimes.
|
|
51
|
+
|
|
52
|
+
## Phase 1 flow
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
/codebase-research
|
|
56
|
+
-> /grill-me when unclear or risky
|
|
57
|
+
-> /ralplan
|
|
58
|
+
-> /team if lanes are independent, otherwise /ralph or /ultrawork
|
|
59
|
+
-> /code-review
|
|
60
|
+
-> /verify or /ultraqa
|
|
61
|
+
-> /jira-ticket when tracking is requested
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Portability rules
|
|
65
|
+
|
|
66
|
+
Canonical `.github/skills/*/SKILL.md` bodies should avoid runtime coupling:
|
|
67
|
+
|
|
68
|
+
- Do not require tmux panes, external agent team state, local orchestration state, or GitHub Issues.
|
|
69
|
+
- Do not embed secrets or Jira credentials.
|
|
70
|
+
- Do not use `$skill` invocation syntax in Copilot project skills.
|
|
71
|
+
- Prefer slash-skill language and plain Markdown instructions over long framework-specific prompt text.
|
|
72
|
+
|
|
73
|
+
## Migration notes
|
|
74
|
+
|
|
75
|
+
- `/grill` was folded into `/grill-me` to keep one clarification entrypoint.
|
|
76
|
+
- `/qa` was folded into `/ultraqa` for the adversarial QA pass.
|
package/docs/jira.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Jira MVP Adapter
|
|
2
|
+
|
|
3
|
+
The Jira adapter turns a resolved plan or handoff into Jira-ready payloads. It supports credential-free dry-runs and only performs live writes when configuration is present and a Jira action is requested by the user or workflow.
|
|
4
|
+
|
|
5
|
+
## Configuration discovery
|
|
6
|
+
|
|
7
|
+
Configuration is resolved in this order:
|
|
8
|
+
|
|
9
|
+
1. External/global Jira setup available to the host environment.
|
|
10
|
+
2. Repository `.env` and process environment variables.
|
|
11
|
+
3. Explicit CLI/session flags as overrides.
|
|
12
|
+
|
|
13
|
+
Supported environment names include:
|
|
14
|
+
|
|
15
|
+
| Variable | Purpose |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `JIRA_BASE_URL` or `JIRA_SITE_URL` | Jira site URL. |
|
|
18
|
+
| `JIRA_EMAIL` | Account email for API auth. |
|
|
19
|
+
| `JIRA_API_TOKEN` | API token. Never commit this value. |
|
|
20
|
+
| `JIRA_PROJECT_KEY` | Default project key for new issues. |
|
|
21
|
+
| `JIRA_DEFAULT_ISSUE_TYPE` | Optional issue type, defaulting to `Task`. |
|
|
22
|
+
| `JIRA_COMPONENTS` | Optional comma-separated components for safe updates. |
|
|
23
|
+
| `JIRA_PRIORITY` | Optional priority name for create/update payloads. |
|
|
24
|
+
|
|
25
|
+
If required config is missing, commands print fallback payloads instead of guessing or failing silently.
|
|
26
|
+
|
|
27
|
+
## Supported operations
|
|
28
|
+
|
|
29
|
+
Phase 1 supports these safe operations:
|
|
30
|
+
|
|
31
|
+
- Create issue payloads from plans/handoffs.
|
|
32
|
+
- Add comments to existing issues.
|
|
33
|
+
- Safely update summary, description, labels, configured components, configured priority, and acceptance criteria in the description.
|
|
34
|
+
|
|
35
|
+
Dry-runs must work without credentials.
|
|
36
|
+
|
|
37
|
+
## Transition and link guardrails
|
|
38
|
+
|
|
39
|
+
Transitions and issue links are project-specific. The adapter may only perform them live after discovery confirms the exact transition ID/name or link type for the target ticket/project.
|
|
40
|
+
|
|
41
|
+
If discovery is unavailable or no exact match exists, the adapter emits fallback text:
|
|
42
|
+
|
|
43
|
+
```md
|
|
44
|
+
## Jira fallback: <operation>
|
|
45
|
+
Reason: <why live operation was not run>
|
|
46
|
+
Target: <ticket key or new issue>
|
|
47
|
+
Payload:
|
|
48
|
+
```json
|
|
49
|
+
{ ...exact Jira REST-style payload... }
|
|
50
|
+
```
|
|
51
|
+
Human action:
|
|
52
|
+
<one concise instruction>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This no-guessing rule keeps workflow changes safe while still giving a human an exact payload to apply.
|
|
56
|
+
|
|
57
|
+
## Dry-run examples
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm run jira:dry-run
|
|
61
|
+
npx tsx src/cli.ts jira render ../.omx/plans/oh-my-copilot-general-skills-ralplan-handoff.md
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Expected dry-run evidence includes create/comment/safe-update support and transition/link discovery fallback state.
|