@askexenow/exe-os 0.8.80 → 0.8.82
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/dist/bin/backfill-conversations.js +359 -267
- package/dist/bin/backfill-responses.js +357 -265
- package/dist/bin/backfill-vectors.js +339 -264
- package/dist/bin/cleanup-stale-review-tasks.js +315 -256
- package/dist/bin/cli.js +494 -240
- package/dist/bin/exe-agent.js +141 -46
- package/dist/bin/exe-assign.js +151 -63
- package/dist/bin/exe-boot.js +294 -115
- package/dist/bin/exe-call.js +76 -51
- package/dist/bin/exe-cloud.js +58 -45
- package/dist/bin/exe-dispatch.js +434 -277
- package/dist/bin/exe-doctor.js +317 -246
- package/dist/bin/exe-export-behaviors.js +328 -248
- package/dist/bin/exe-forget.js +314 -231
- package/dist/bin/exe-gateway.js +2676 -1402
- package/dist/bin/exe-heartbeat.js +329 -264
- package/dist/bin/exe-kill.js +324 -244
- package/dist/bin/exe-launch-agent.js +574 -463
- package/dist/bin/exe-link.js +1055 -95
- package/dist/bin/exe-new-employee.js +49 -54
- package/dist/bin/exe-pending-messages.js +310 -253
- package/dist/bin/exe-pending-notifications.js +299 -228
- package/dist/bin/exe-pending-reviews.js +314 -245
- package/dist/bin/exe-rename.js +259 -195
- package/dist/bin/exe-review.js +140 -64
- package/dist/bin/exe-search.js +543 -356
- package/dist/bin/exe-session-cleanup.js +463 -382
- package/dist/bin/exe-settings.js +129 -99
- package/dist/bin/exe-start.sh +6 -6
- package/dist/bin/exe-status.js +95 -36
- package/dist/bin/exe-team.js +116 -51
- package/dist/bin/git-sweep.js +482 -307
- package/dist/bin/graph-backfill.js +357 -245
- package/dist/bin/graph-export.js +324 -244
- package/dist/bin/install.js +33 -10
- package/dist/bin/scan-tasks.js +481 -307
- package/dist/bin/setup.js +1147 -140
- package/dist/bin/shard-migrate.js +321 -241
- package/dist/bin/update.js +1 -7
- package/dist/bin/wiki-sync.js +318 -238
- package/dist/gateway/index.js +2656 -1383
- package/dist/hooks/bug-report-worker.js +641 -472
- package/dist/hooks/commit-complete.js +482 -307
- package/dist/hooks/error-recall.js +363 -135
- package/dist/hooks/exe-heartbeat-hook.js +97 -27
- package/dist/hooks/ingest-worker.js +584 -397
- package/dist/hooks/ingest.js +123 -58
- package/dist/hooks/instructions-loaded.js +212 -82
- package/dist/hooks/notification.js +200 -70
- package/dist/hooks/post-compact.js +199 -81
- package/dist/hooks/pre-compact.js +352 -140
- package/dist/hooks/pre-tool-use.js +416 -278
- package/dist/hooks/prompt-ingest-worker.js +376 -299
- package/dist/hooks/prompt-submit.js +414 -188
- package/dist/hooks/response-ingest-worker.js +408 -338
- package/dist/hooks/session-end.js +209 -83
- package/dist/hooks/session-start.js +382 -158
- package/dist/hooks/stop.js +209 -83
- package/dist/hooks/subagent-stop.js +209 -85
- package/dist/hooks/summary-worker.js +606 -510
- package/dist/index.js +2133 -855
- package/dist/lib/cloud-sync.js +1175 -184
- package/dist/lib/config.js +1 -9
- package/dist/lib/consolidation.js +71 -34
- package/dist/lib/database.js +166 -14
- package/dist/lib/device-registry.js +189 -117
- package/dist/lib/embedder.js +6 -10
- package/dist/lib/employee-templates.js +134 -39
- package/dist/lib/employees.js +30 -7
- package/dist/lib/exe-daemon-client.js +5 -7
- package/dist/lib/exe-daemon.js +514 -152
- package/dist/lib/hybrid-search.js +543 -356
- package/dist/lib/identity-templates.js +15 -15
- package/dist/lib/identity.js +19 -15
- package/dist/lib/license.js +1 -7
- package/dist/lib/messaging.js +157 -135
- package/dist/lib/reminders.js +97 -0
- package/dist/lib/schedules.js +302 -231
- package/dist/lib/skill-learning.js +33 -27
- package/dist/lib/status-brief.js +11 -14
- package/dist/lib/store.js +326 -237
- package/dist/lib/task-router.js +105 -1
- package/dist/lib/tasks.js +233 -116
- package/dist/lib/tmux-routing.js +173 -56
- package/dist/lib/ws-client.js +13 -3
- package/dist/mcp/server.js +2009 -1015
- package/dist/mcp/tools/complete-reminder.js +97 -0
- package/dist/mcp/tools/create-reminder.js +97 -0
- package/dist/mcp/tools/create-task.js +426 -262
- package/dist/mcp/tools/deactivate-behavior.js +119 -44
- package/dist/mcp/tools/list-reminders.js +97 -0
- package/dist/mcp/tools/list-tasks.js +56 -57
- package/dist/mcp/tools/send-message.js +206 -143
- package/dist/mcp/tools/update-task.js +259 -85
- package/dist/runtime/index.js +495 -316
- package/dist/tui/App.js +1128 -919
- package/package.json +2 -10
- package/src/commands/exe/afk.md +8 -8
- package/src/commands/exe/assign.md +1 -1
- package/src/commands/exe/build-adv.md +1 -1
- package/src/commands/exe/call.md +10 -10
- package/src/commands/exe/employee-heartbeat.md +9 -6
- package/src/commands/exe/heartbeat.md +5 -5
- package/src/commands/exe/intercom.md +26 -15
- package/src/commands/exe/launch.md +2 -2
- package/src/commands/exe/new-employee.md +1 -1
- package/src/commands/exe/review.md +2 -2
- package/src/commands/exe/schedule.md +1 -1
- package/src/commands/exe/sessions.md +2 -2
- package/src/commands/exe.md +22 -20
package/dist/bin/exe-call.js
CHANGED
|
@@ -73,13 +73,7 @@ var init_config = __esm({
|
|
|
73
73
|
wikiUrl: "",
|
|
74
74
|
wikiApiKey: "",
|
|
75
75
|
wikiSyncIntervalMs: 30 * 60 * 1e3,
|
|
76
|
-
wikiWorkspaceMapping: {
|
|
77
|
-
exe: "Executive",
|
|
78
|
-
yoshi: "Engineering",
|
|
79
|
-
mari: "Marketing",
|
|
80
|
-
tom: "Engineering",
|
|
81
|
-
sasha: "Production"
|
|
82
|
-
},
|
|
76
|
+
wikiWorkspaceMapping: {},
|
|
83
77
|
wikiAutoUpdate: true,
|
|
84
78
|
wikiAutoUpdateThreshold: 0.5,
|
|
85
79
|
wikiAutoUpdateCreateNew: true,
|
|
@@ -109,15 +103,23 @@ var init_config = __esm({
|
|
|
109
103
|
// src/lib/employees.ts
|
|
110
104
|
var employees_exports = {};
|
|
111
105
|
__export(employees_exports, {
|
|
106
|
+
COORDINATOR_ROLE: () => COORDINATOR_ROLE,
|
|
107
|
+
DEFAULT_COORDINATOR_TEMPLATE_NAME: () => DEFAULT_COORDINATOR_TEMPLATE_NAME,
|
|
112
108
|
EMPLOYEES_PATH: () => EMPLOYEES_PATH,
|
|
113
109
|
addEmployee: () => addEmployee,
|
|
110
|
+
canCoordinate: () => canCoordinate,
|
|
111
|
+
getCoordinatorEmployee: () => getCoordinatorEmployee,
|
|
112
|
+
getCoordinatorName: () => getCoordinatorName,
|
|
114
113
|
getEmployee: () => getEmployee,
|
|
115
114
|
getEmployeeByRole: () => getEmployeeByRole,
|
|
116
115
|
getEmployeeNamesByRole: () => getEmployeeNamesByRole,
|
|
117
116
|
hasRole: () => hasRole,
|
|
117
|
+
isCoordinatorName: () => isCoordinatorName,
|
|
118
|
+
isCoordinatorRole: () => isCoordinatorRole,
|
|
118
119
|
isMultiInstance: () => isMultiInstance,
|
|
119
120
|
loadEmployees: () => loadEmployees,
|
|
120
121
|
loadEmployeesSync: () => loadEmployeesSync,
|
|
122
|
+
normalizeRole: () => normalizeRole,
|
|
121
123
|
normalizeRosterCase: () => normalizeRosterCase,
|
|
122
124
|
registerBinSymlinks: () => registerBinSymlinks,
|
|
123
125
|
saveEmployees: () => saveEmployees,
|
|
@@ -128,6 +130,25 @@ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as r
|
|
|
128
130
|
import { execSync } from "child_process";
|
|
129
131
|
import path2 from "path";
|
|
130
132
|
import os2 from "os";
|
|
133
|
+
function normalizeRole(role) {
|
|
134
|
+
return (role ?? "").trim().toLowerCase();
|
|
135
|
+
}
|
|
136
|
+
function isCoordinatorRole(role) {
|
|
137
|
+
return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
|
|
138
|
+
}
|
|
139
|
+
function getCoordinatorEmployee(employees) {
|
|
140
|
+
return employees.find((e) => isCoordinatorRole(e.role));
|
|
141
|
+
}
|
|
142
|
+
function getCoordinatorName(employees = loadEmployeesSync()) {
|
|
143
|
+
return getCoordinatorEmployee(employees)?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
|
|
144
|
+
}
|
|
145
|
+
function isCoordinatorName(agentName, employees = loadEmployeesSync()) {
|
|
146
|
+
if (!agentName) return false;
|
|
147
|
+
return agentName.toLowerCase() === getCoordinatorName(employees).toLowerCase();
|
|
148
|
+
}
|
|
149
|
+
function canCoordinate(agentName, agentRole, employees = loadEmployeesSync()) {
|
|
150
|
+
return agentName === "default" || isCoordinatorRole(agentRole) || isCoordinatorName(agentName, employees);
|
|
151
|
+
}
|
|
131
152
|
function validateEmployeeName(name) {
|
|
132
153
|
if (!name) {
|
|
133
154
|
return { valid: false, error: "Name is required" };
|
|
@@ -265,12 +286,14 @@ function registerBinSymlinks(name) {
|
|
|
265
286
|
}
|
|
266
287
|
return { created, skipped, errors };
|
|
267
288
|
}
|
|
268
|
-
var EMPLOYEES_PATH, MULTI_INSTANCE_ROLES;
|
|
289
|
+
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES;
|
|
269
290
|
var init_employees = __esm({
|
|
270
291
|
"src/lib/employees.ts"() {
|
|
271
292
|
"use strict";
|
|
272
293
|
init_config();
|
|
273
294
|
EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
295
|
+
DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
|
|
296
|
+
COORDINATOR_ROLE = "COO";
|
|
274
297
|
MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
|
|
275
298
|
}
|
|
276
299
|
});
|
|
@@ -288,6 +311,7 @@ var init_database = __esm({
|
|
|
288
311
|
"src/lib/database.ts"() {
|
|
289
312
|
"use strict";
|
|
290
313
|
init_db_retry();
|
|
314
|
+
init_employees();
|
|
291
315
|
}
|
|
292
316
|
});
|
|
293
317
|
|
|
@@ -302,26 +326,26 @@ var init_platform_procedures = __esm({
|
|
|
302
326
|
title: "What is exe-os \u2014 the operating model every agent must understand",
|
|
303
327
|
domain: "architecture",
|
|
304
328
|
priority: "p0",
|
|
305
|
-
content: "Exe OS is an AI employee operating system. A founder runs 5-10 AI agents as a real org: COO
|
|
329
|
+
content: "Exe OS is an AI employee operating system. A founder runs 5-10 AI agents as a real org: COO, CTO, CMO, engineers, and content production specialists. Each agent has identity, expertise, and experience layers \u2014 persistent memory that makes them better over time. All data is local-first, E2EE, owned by the user. The MCP server is the ONLY data interface \u2014 never access the DB directly."
|
|
306
330
|
},
|
|
307
331
|
{
|
|
308
332
|
title: "Mode 1 \u2014 how exe-os runs inside Claude Code",
|
|
309
333
|
domain: "architecture",
|
|
310
334
|
priority: "p0",
|
|
311
|
-
content: "Mode 1: exe-os runs AS hooks + MCP + skills inside Claude Code. The founder opens CC
|
|
335
|
+
content: "Mode 1: exe-os runs AS hooks + MCP + skills inside Claude Code. The founder opens CC and boots the COO. The COO manages employees in tmux sessions. Each coordinator session is a separate CC window/project. Employees run in their own tmux panes via create_task auto-spawn. The founder talks to the COO; the COO orchestrates the team. CC is the shell, exe-os is the brain."
|
|
312
336
|
},
|
|
313
337
|
{
|
|
314
|
-
title: "Sessions explained \u2014
|
|
338
|
+
title: "Sessions explained \u2014 coordinator session names and projects",
|
|
315
339
|
domain: "architecture",
|
|
316
340
|
priority: "p0",
|
|
317
|
-
content: "Each
|
|
341
|
+
content: "Each coordinator session is an isolated project session. One might be exe-os development, another might be exe-wiki. Each session spawns its own employees using {employee}-{coordinatorSession}. Sessions share the same memory DB but tasks are scoped to the session that created them. A founder can run multiple projects simultaneously. Sessions never interfere with each other."
|
|
318
342
|
},
|
|
319
343
|
// --- Hierarchy and dispatch ---
|
|
320
344
|
{
|
|
321
345
|
title: "Chain of command \u2014 who talks to whom",
|
|
322
346
|
domain: "workflow",
|
|
323
347
|
priority: "p0",
|
|
324
|
-
content: "Founder
|
|
348
|
+
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
|
|
325
349
|
},
|
|
326
350
|
{
|
|
327
351
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -331,30 +355,30 @@ var init_platform_procedures = __esm({
|
|
|
331
355
|
},
|
|
332
356
|
// --- Session isolation ---
|
|
333
357
|
{
|
|
334
|
-
title: "Session scoping \u2014 stay in your
|
|
358
|
+
title: "Session scoping \u2014 stay in your coordinator boundary",
|
|
335
359
|
domain: "security",
|
|
336
360
|
priority: "p0",
|
|
337
|
-
content: "Session scoping is mandatory. Managers dispatch to workers within their own
|
|
361
|
+
content: "Session scoping is mandatory. Managers dispatch to workers within their own coordinator session ONLY. Employee sessions use {employee}-{coordinatorSession}. Cross-session dispatch is blocked by the system. Verify session names before dispatch. Tasks are scoped to the creating coordinator session."
|
|
338
362
|
},
|
|
339
363
|
{
|
|
340
364
|
title: "Session isolation \u2014 never touch another session's work",
|
|
341
365
|
domain: "workflow",
|
|
342
366
|
priority: "p0",
|
|
343
|
-
content:
|
|
367
|
+
content: "Sessions are isolated. A coordinator session owns ONLY tasks it dispatched. (1) Never close/update/cancel tasks from another coordinator session. (2) Never review work from a different session \u2014 report that it belongs to another session and skip. (3) Ignore other sessions' items in list_tasks results. (4) Employees inherit session: employee sessions work ONLY on their parent coordinator session's tasks. Cross-session work is a system violation."
|
|
344
368
|
},
|
|
345
369
|
// --- Engineering: session scoping in code ---
|
|
346
370
|
{
|
|
347
371
|
title: "Three-dimensional scoping \u2014 session, project, role \u2014 enforced in every query",
|
|
348
372
|
domain: "architecture",
|
|
349
373
|
priority: "p0",
|
|
350
|
-
content: "Every DB query, notification, review count, and task operation MUST be scoped on 3 dimensions: (1) Session \u2014 filter by session_scope matching current
|
|
374
|
+
content: "Every DB query, notification, review count, and task operation MUST be scoped on 3 dimensions: (1) Session \u2014 filter by session_scope matching the current coordinator session. (2) Project \u2014 filter by project_name. (3) Role \u2014 agents only see data at their hierarchy level. When writing ANY function that touches tasks, reviews, messages, or notifications: always accept a sessionScope parameter and pass it to the SQL WHERE clause. Unscoped queries are bugs. Test by running 2+ coordinator sessions simultaneously."
|
|
351
375
|
},
|
|
352
376
|
// --- Hard constraints ---
|
|
353
377
|
{
|
|
354
378
|
title: "What you CANNOT do in exe-os \u2014 hard constraints",
|
|
355
379
|
domain: "security",
|
|
356
380
|
priority: "p0",
|
|
357
|
-
content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014
|
|
381
|
+
content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
|
|
358
382
|
},
|
|
359
383
|
// --- Operations ---
|
|
360
384
|
{
|
|
@@ -512,13 +536,13 @@ Ethos:
|
|
|
512
536
|
- Founder zero-ego. Distributors and customers are the loudest voice.
|
|
513
537
|
- Crypto values: big companies should not own consumer/SMB AI.
|
|
514
538
|
|
|
515
|
-
STOP AND REDIRECT: Any decision that compromises memory sovereignty, 3-layer cognition, MCP boundary, or AGPL boundary kills all three business paths. Surface the conflict to
|
|
539
|
+
STOP AND REDIRECT: Any decision that compromises memory sovereignty, 3-layer cognition, MCP boundary, or AGPL boundary kills all three business paths. Surface the conflict to the COO before proceeding.
|
|
516
540
|
|
|
517
541
|
Always reference .planning/ARCHITECTURE.md and .planning/PROJECT.md as source of truth for all architectural and product decisions.
|
|
518
542
|
|
|
519
543
|
OPERATING PROCEDURES (mandatory for all employees):
|
|
520
544
|
|
|
521
|
-
You report to the COO. All work flows through
|
|
545
|
+
You report to the COO. All work flows through the COO. These procedures are non-negotiable.
|
|
522
546
|
|
|
523
547
|
1. BEFORE starting work:
|
|
524
548
|
- Read exe/ARCHITECTURE.md (if it exists). This is the system map \u2014 what components exist, how they connect, what invariants to preserve. Understand the architecture before changing anything.
|
|
@@ -543,15 +567,15 @@ You report to the COO. All work flows through exe. These procedures are non-nego
|
|
|
543
567
|
- Include what was done, decisions made, and any issues
|
|
544
568
|
- If you're stuck, looping, confused, or running low on context \u2014 update_task(done) with whatever partial result you have. A partial result is infinitely better than no result.
|
|
545
569
|
- NEVER let a failed commit, a loop, or an error prevent you from calling update_task(done).
|
|
546
|
-
- Do NOT use close_task \u2014 that is reserved for reviewers
|
|
570
|
+
- Do NOT use close_task \u2014 that is reserved for reviewers to finalize after review.
|
|
547
571
|
|
|
548
572
|
4. AFTER update_task(done) \u2014 COMMIT (best-effort, do NOT let this block):
|
|
549
573
|
- If your task changed system structure, update exe/ARCHITECTURE.md first.
|
|
550
574
|
- Commit IF you are in a git repo (check: \`git rev-parse --git-dir 2>/dev/null\`). Stage only the files you changed, write a clear commit message.
|
|
551
575
|
- If you are NOT in a git repo, skip entirely. NEVER run \`git init\`.
|
|
552
576
|
- If the commit fails, note it but move on \u2014 the work is already marked done via update_task.
|
|
553
|
-
- Do NOT push \u2014
|
|
554
|
-
- NEVER run \`git checkout main\`. You work in your own git worktree on a feature branch.
|
|
577
|
+
- Do NOT push \u2014 the COO reviews commits and decides what to push.
|
|
578
|
+
- NEVER run \`git checkout main\`. You work in your own git worktree on a feature branch. The COO stays on main and merges PRs. Switching branches in a shared repo stomps other agents' work.
|
|
555
579
|
|
|
556
580
|
5. AFTER commit \u2014 REPORT (best-effort):
|
|
557
581
|
Use store_memory to write a structured summary. Include: project name, what was done,
|
|
@@ -565,7 +589,7 @@ You report to the COO. All work flows through exe. These procedures are non-nego
|
|
|
565
589
|
|
|
566
590
|
7. AFTER reporting \u2014 CHECK FOR NEXT WORK (mandatory):
|
|
567
591
|
- First: run list_tasks(status='needs_review') \u2014 check if YOU are the reviewer on any pending reviews. Reviews are work. Process them before anything else.
|
|
568
|
-
- Second: run list_tasks(status='blocked') \u2014 check if any tasks are blocked. For each blocked task: can YOU unblock it? If yes, unblock it now. If not, escalate to
|
|
592
|
+
- Second: run list_tasks(status='blocked') \u2014 check if any tasks are blocked. For each blocked task: can YOU unblock it? If yes, unblock it now. If not, escalate to the COO immediately. Blocked tasks sitting >24h without action is a pipeline failure.
|
|
569
593
|
- Then: re-read your task folder: exe/<your-name>/
|
|
570
594
|
- If there are more open tasks, start the next highest-priority one (go to step 1)
|
|
571
595
|
- If no more open tasks AND no pending reviews AND no blocked tasks you can fix, tell the user: "All tasks complete. Anything else?"
|
|
@@ -582,7 +606,7 @@ DO NOT keep working degraded. Instead:
|
|
|
582
606
|
Format the text as: "CONTEXT CHECKPOINT [<task-id>]: <summary>"
|
|
583
607
|
Include: task ID + title, what you completed, what's left, open decisions or blockers, key file paths.
|
|
584
608
|
|
|
585
|
-
2. Send intercom to
|
|
609
|
+
2. Send intercom to the COO session to trigger kill + relaunch:
|
|
586
610
|
MY_SESSION=$(tmux display-message -p '#{session_name}' 2>/dev/null)
|
|
587
611
|
EXE_SESSION="\${MY_SESSION#\${AGENT_ID}-}"
|
|
588
612
|
tmux send-keys -t "$EXE_SESSION" "/exe-intercom context-full: \${AGENT_ID} hit capacity. Checkpoint saved. Resume task <task-id>." Enter
|
|
@@ -590,8 +614,8 @@ DO NOT keep working degraded. Instead:
|
|
|
590
614
|
3. Stop working immediately. Do not attempt to continue with degraded context.
|
|
591
615
|
|
|
592
616
|
COMMUNICATION CHAIN \u2014 who you talk to:
|
|
593
|
-
- You report to the COO. Your completion reports, status updates, and questions go to
|
|
594
|
-
- Do NOT address the human user directly for decisions, permissions, or status updates. That's
|
|
617
|
+
- You report to the COO. Your completion reports, status updates, and questions go to the COO via store_memory and update_task.
|
|
618
|
+
- Do NOT address the human user directly for decisions, permissions, or status updates. That's the COO's job. The user talks to the COO; the COO talks to you.
|
|
595
619
|
- Exception: if the user sends you a direct message in your tmux window, respond to them. But default to reporting through exe.
|
|
596
620
|
|
|
597
621
|
SKILL CAPTURE (encouraged, not mandatory):
|
|
@@ -680,21 +704,21 @@ When you receive a large task (estimated 3+ subtasks):
|
|
|
680
704
|
6. Review engineer work as reviews arrive in your queue
|
|
681
705
|
7. When all subtasks pass review, mark the parent task done
|
|
682
706
|
|
|
683
|
-
PARALLEL
|
|
707
|
+
PARALLEL ENGINEER INSTANCES:
|
|
684
708
|
|
|
685
|
-
When implementation tasks can be parallelized (touching different files/modules), spin up multiple
|
|
709
|
+
When implementation tasks can be parallelized (touching different files/modules), spin up multiple engineer instances using git worktrees for isolation:
|
|
686
710
|
|
|
687
|
-
1. Set up git worktrees BEFORE assigning: git worktree add .worktrees/
|
|
688
|
-
2. Naming convention:
|
|
689
|
-
3.
|
|
690
|
-
4. Each
|
|
691
|
-
5. After all
|
|
692
|
-
6. Clean up worktrees after integration: git worktree remove .worktrees/
|
|
711
|
+
1. Set up git worktrees BEFORE assigning: git worktree add .worktrees/{engineer-name}1 -b {engineer-name}1-task-name
|
|
712
|
+
2. Naming convention: {engineer-name}1-{coordinator-session}, {engineer-name}2-{coordinator-session}
|
|
713
|
+
3. Parallel instances share that engineer's memory partition \u2014 knowledge compounds across instances
|
|
714
|
+
4. Each engineer instance works in its own worktree \u2014 no merge conflicts on parallel work
|
|
715
|
+
5. After all engineer instances complete, YOU integrate: merge worktree branches, resolve any conflicts, run tests
|
|
716
|
+
6. Clean up worktrees after integration: git worktree remove .worktrees/{engineer-name}1
|
|
693
717
|
|
|
694
|
-
Use this for any decomposable implementation work.
|
|
718
|
+
Use this for any decomposable implementation work. Use a single engineer for sequential or tightly coupled tasks.
|
|
695
719
|
|
|
696
720
|
Reviews route to the assigner: if you assign a task to an engineer, you review it.
|
|
697
|
-
If
|
|
721
|
+
If the COO assigns a task to you, the COO reviews it. The chain is:
|
|
698
722
|
COO \u2192 CTO (you review) \u2192 engineers (you review their work, COO reviews yours)
|
|
699
723
|
|
|
700
724
|
ROLE BOUNDARIES \u2014 stay in your lane:
|
|
@@ -770,17 +794,17 @@ USER RESEARCH
|
|
|
770
794
|
When reviewing work, prioritize brand consistency, audience resonance, and measurable impact. Every deliverable should serve a clear strategic goal \u2014 not just look good, but perform.
|
|
771
795
|
|
|
772
796
|
DELEGATION:
|
|
773
|
-
- For content production tasks (video rendering, image generation, asset creation with exe-create), delegate to
|
|
774
|
-
- You write the script/brief.
|
|
797
|
+
- For content production tasks (video rendering, image generation, asset creation with exe-create), delegate to a Content Production Specialist via create_task. Write a clear brief with: deliverable, format, platform specs, brand guidelines, and reference assets.
|
|
798
|
+
- You write the script/brief. The producer creates the assets. You review the output.
|
|
775
799
|
- For tasks within your own domain (copy, strategy, SEO, social posts), handle directly.
|
|
776
|
-
- When
|
|
800
|
+
- When the producer completes work, the review routes back to you automatically. Review it before marking done.`
|
|
777
801
|
},
|
|
778
802
|
tom: {
|
|
779
803
|
name: "tom",
|
|
780
804
|
role: "Principal Engineer",
|
|
781
805
|
systemPrompt: `You are tom, a principal engineer. You write production-grade code with zero shortcuts. You report to the CTO for technical tasks, and to the COO for organizational matters.
|
|
782
806
|
|
|
783
|
-
You are the hands.
|
|
807
|
+
You are the hands. The CTO architects and specs; you implement. You receive tasks with clear acceptance criteria and tests to pass. Your job is to make those tests green with code that a senior engineer would be proud to maintain.
|
|
784
808
|
|
|
785
809
|
STANDARDS \u2014 non-negotiable:
|
|
786
810
|
|
|
@@ -821,15 +845,15 @@ Velocity:
|
|
|
821
845
|
- You are optimized for throughput. Fast, correct, clean \u2014 in that order. But never sacrifice correct for fast.
|
|
822
846
|
|
|
823
847
|
Working with the CTO:
|
|
824
|
-
-
|
|
848
|
+
- The CTO writes specs and tests. You implement. If the spec is wrong, report it \u2014 don't silently deviate.
|
|
825
849
|
- If tests seem wrong, report it \u2014 don't modify them.
|
|
826
850
|
- Your review goes to whoever assigned the task (usually the CTO). The CTO reviews your code, not the COO.
|
|
827
|
-
- Multiple
|
|
851
|
+
- Multiple instances of your role can run in parallel. You may share a memory pool. If you discover something useful (a gotcha, a pattern, a workaround), store it \u2014 the next engineer session benefits.
|
|
828
852
|
|
|
829
853
|
What you do NOT do:
|
|
830
854
|
- Architecture decisions \u2014 that's the CTO
|
|
831
855
|
- Marketing, content, design \u2014 that's the CMO
|
|
832
|
-
- Prioritization, coordination \u2014 that's
|
|
856
|
+
- Prioritization, coordination \u2014 that's the COO
|
|
833
857
|
- Spec writing, test writing \u2014 that's the CTO (unless explicitly asked)
|
|
834
858
|
- You implement. That's it. Do it well.`
|
|
835
859
|
},
|
|
@@ -838,7 +862,7 @@ What you do NOT do:
|
|
|
838
862
|
role: "Content Production Specialist",
|
|
839
863
|
systemPrompt: `You are sasha, the content production specialist. You turn scripts and creative briefs into finished content using the exe-create platform. You report to the COO. For creative direction, you take input from the CMO.
|
|
840
864
|
|
|
841
|
-
You are the producer.
|
|
865
|
+
You are the producer. The CMO writes the script; you make it real. The CTO builds the tools; you use them. You know every tool in the exe-create pipeline and how to get the best output from each one.
|
|
842
866
|
|
|
843
867
|
YOUR TOOLS \u2014 exe-create platform:
|
|
844
868
|
|
|
@@ -876,7 +900,7 @@ PRODUCTION PRINCIPLES:
|
|
|
876
900
|
|
|
877
901
|
1. Check budget before generating. Never burn credits without knowing the cost.
|
|
878
902
|
2. Iterate in drafts. Use cheaper models for exploration, premium (Kling 3.0) for finals.
|
|
879
|
-
3. Follow the script.
|
|
903
|
+
3. Follow the script. The CMO's creative brief is your spec. Don't improvise on brand/tone.
|
|
880
904
|
4. Match the platform. 16:9 for YouTube, 9:16 for TikTok/Reels, 1:1 for Instagram feed.
|
|
881
905
|
5. Naming convention: {project}-{type}-{version}.{ext} (e.g., launch-hero-v2.png)
|
|
882
906
|
6. All final assets go to exe/output/ with clear naming.
|
|
@@ -885,7 +909,7 @@ PRODUCTION PRINCIPLES:
|
|
|
885
909
|
WHAT YOU DO NOT DO:
|
|
886
910
|
- Marketing strategy, brand decisions, copywriting \u2014 that's the CMO
|
|
887
911
|
- Architecture, tool development, debugging \u2014 that's the CTO
|
|
888
|
-
- Prioritization, coordination \u2014 that's
|
|
912
|
+
- Prioritization, coordination \u2014 that's the COO
|
|
889
913
|
- You produce. That's it. Do it well.`
|
|
890
914
|
},
|
|
891
915
|
gen: {
|
|
@@ -1068,7 +1092,7 @@ function isMainModule(importMetaUrl) {
|
|
|
1068
1092
|
// src/bin/exe-call.ts
|
|
1069
1093
|
init_employee_templates();
|
|
1070
1094
|
function resolveEmployee(name, employees) {
|
|
1071
|
-
const resolved = name ||
|
|
1095
|
+
const resolved = name || getCoordinatorName(employees);
|
|
1072
1096
|
const employee = getEmployee(employees, resolved);
|
|
1073
1097
|
if (!employee) {
|
|
1074
1098
|
throw new Error(
|
|
@@ -1097,19 +1121,20 @@ async function prepareSessionDir(name, systemPrompt, sessionsBase = path3.join(E
|
|
|
1097
1121
|
}
|
|
1098
1122
|
if (isMainModule(import.meta.url)) {
|
|
1099
1123
|
const name = process.argv[2];
|
|
1100
|
-
|
|
1124
|
+
const employees = await loadEmployees();
|
|
1125
|
+
const coordinatorName = getCoordinatorName(employees);
|
|
1126
|
+
if (!name || name === coordinatorName) {
|
|
1101
1127
|
const __dirname = path3.dirname(fileURLToPath2(import.meta.url));
|
|
1102
1128
|
const bootPath = path3.join(__dirname, "exe-boot.js");
|
|
1103
1129
|
try {
|
|
1104
1130
|
execSync2(`node "${bootPath}"`, { stdio: "inherit" });
|
|
1105
1131
|
} catch (err) {
|
|
1106
|
-
console.error(`Failed to boot
|
|
1132
|
+
console.error(`Failed to boot coordinator: ${err instanceof Error ? err.message : String(err)}`);
|
|
1107
1133
|
process.exit(1);
|
|
1108
1134
|
}
|
|
1109
1135
|
process.exit(0);
|
|
1110
1136
|
}
|
|
1111
1137
|
try {
|
|
1112
|
-
const employees = await loadEmployees();
|
|
1113
1138
|
if (employees.length === 0) {
|
|
1114
1139
|
console.error("No employees found. Run /exe first to initialize.");
|
|
1115
1140
|
process.exit(1);
|
package/dist/bin/exe-cloud.js
CHANGED
|
@@ -264,13 +264,7 @@ var init_config = __esm({
|
|
|
264
264
|
wikiUrl: "",
|
|
265
265
|
wikiApiKey: "",
|
|
266
266
|
wikiSyncIntervalMs: 30 * 60 * 1e3,
|
|
267
|
-
wikiWorkspaceMapping: {
|
|
268
|
-
exe: "Executive",
|
|
269
|
-
yoshi: "Engineering",
|
|
270
|
-
mari: "Marketing",
|
|
271
|
-
tom: "Engineering",
|
|
272
|
-
sasha: "Production"
|
|
273
|
-
},
|
|
267
|
+
wikiWorkspaceMapping: {},
|
|
274
268
|
wikiAutoUpdate: true,
|
|
275
269
|
wikiAutoUpdateThreshold: 0.5,
|
|
276
270
|
wikiAutoUpdateCreateNew: true,
|
|
@@ -307,6 +301,38 @@ var init_config = __esm({
|
|
|
307
301
|
}
|
|
308
302
|
});
|
|
309
303
|
|
|
304
|
+
// src/lib/db-retry.ts
|
|
305
|
+
var init_db_retry = __esm({
|
|
306
|
+
"src/lib/db-retry.ts"() {
|
|
307
|
+
"use strict";
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// src/lib/employees.ts
|
|
312
|
+
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
313
|
+
import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
|
|
314
|
+
import { execSync } from "child_process";
|
|
315
|
+
import path3 from "path";
|
|
316
|
+
import os3 from "os";
|
|
317
|
+
var EMPLOYEES_PATH;
|
|
318
|
+
var init_employees = __esm({
|
|
319
|
+
"src/lib/employees.ts"() {
|
|
320
|
+
"use strict";
|
|
321
|
+
init_config();
|
|
322
|
+
EMPLOYEES_PATH = path3.join(EXE_AI_DIR, "exe-employees.json");
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// src/lib/database.ts
|
|
327
|
+
import { createClient } from "@libsql/client";
|
|
328
|
+
var init_database = __esm({
|
|
329
|
+
"src/lib/database.ts"() {
|
|
330
|
+
"use strict";
|
|
331
|
+
init_db_retry();
|
|
332
|
+
init_employees();
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
310
336
|
// src/lib/license.ts
|
|
311
337
|
var license_exports = {};
|
|
312
338
|
__export(license_exports, {
|
|
@@ -324,9 +350,9 @@ __export(license_exports, {
|
|
|
324
350
|
stopLicenseRevalidation: () => stopLicenseRevalidation,
|
|
325
351
|
validateLicense: () => validateLicense
|
|
326
352
|
});
|
|
327
|
-
import { readFileSync as
|
|
353
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync4, mkdirSync } from "fs";
|
|
328
354
|
import { randomUUID } from "crypto";
|
|
329
|
-
import
|
|
355
|
+
import path4 from "path";
|
|
330
356
|
import { jwtVerify, importSPKI } from "jose";
|
|
331
357
|
async function fetchRetry(url, init) {
|
|
332
358
|
try {
|
|
@@ -337,37 +363,37 @@ async function fetchRetry(url, init) {
|
|
|
337
363
|
}
|
|
338
364
|
}
|
|
339
365
|
function loadDeviceId() {
|
|
340
|
-
const deviceJsonPath =
|
|
366
|
+
const deviceJsonPath = path4.join(EXE_AI_DIR, "device.json");
|
|
341
367
|
try {
|
|
342
|
-
if (
|
|
343
|
-
const data = JSON.parse(
|
|
368
|
+
if (existsSync4(deviceJsonPath)) {
|
|
369
|
+
const data = JSON.parse(readFileSync3(deviceJsonPath, "utf8"));
|
|
344
370
|
if (data.deviceId) return data.deviceId;
|
|
345
371
|
}
|
|
346
372
|
} catch {
|
|
347
373
|
}
|
|
348
374
|
try {
|
|
349
|
-
if (
|
|
350
|
-
const id2 =
|
|
375
|
+
if (existsSync4(DEVICE_ID_PATH)) {
|
|
376
|
+
const id2 = readFileSync3(DEVICE_ID_PATH, "utf8").trim();
|
|
351
377
|
if (id2) return id2;
|
|
352
378
|
}
|
|
353
379
|
} catch {
|
|
354
380
|
}
|
|
355
381
|
const id = randomUUID();
|
|
356
382
|
mkdirSync(EXE_AI_DIR, { recursive: true });
|
|
357
|
-
|
|
383
|
+
writeFileSync2(DEVICE_ID_PATH, id, "utf8");
|
|
358
384
|
return id;
|
|
359
385
|
}
|
|
360
386
|
function loadLicense() {
|
|
361
387
|
try {
|
|
362
|
-
if (!
|
|
363
|
-
return
|
|
388
|
+
if (!existsSync4(LICENSE_PATH)) return null;
|
|
389
|
+
return readFileSync3(LICENSE_PATH, "utf8").trim();
|
|
364
390
|
} catch {
|
|
365
391
|
return null;
|
|
366
392
|
}
|
|
367
393
|
}
|
|
368
394
|
function saveLicense(apiKey) {
|
|
369
395
|
mkdirSync(EXE_AI_DIR, { recursive: true });
|
|
370
|
-
|
|
396
|
+
writeFileSync2(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
|
|
371
397
|
}
|
|
372
398
|
async function verifyLicenseJwt(token) {
|
|
373
399
|
try {
|
|
@@ -393,8 +419,8 @@ async function verifyLicenseJwt(token) {
|
|
|
393
419
|
}
|
|
394
420
|
async function getCachedLicense() {
|
|
395
421
|
try {
|
|
396
|
-
if (!
|
|
397
|
-
const raw = JSON.parse(
|
|
422
|
+
if (!existsSync4(CACHE_PATH)) return null;
|
|
423
|
+
const raw = JSON.parse(readFileSync3(CACHE_PATH, "utf8"));
|
|
398
424
|
if (!raw.token || typeof raw.token !== "string") return null;
|
|
399
425
|
return await verifyLicenseJwt(raw.token);
|
|
400
426
|
} catch {
|
|
@@ -403,8 +429,8 @@ async function getCachedLicense() {
|
|
|
403
429
|
}
|
|
404
430
|
function readCachedToken() {
|
|
405
431
|
try {
|
|
406
|
-
if (!
|
|
407
|
-
const raw = JSON.parse(
|
|
432
|
+
if (!existsSync4(CACHE_PATH)) return null;
|
|
433
|
+
const raw = JSON.parse(readFileSync3(CACHE_PATH, "utf8"));
|
|
408
434
|
return typeof raw.token === "string" ? raw.token : null;
|
|
409
435
|
} catch {
|
|
410
436
|
return null;
|
|
@@ -438,7 +464,7 @@ function getRawCachedPlan() {
|
|
|
438
464
|
}
|
|
439
465
|
function cacheResponse(token) {
|
|
440
466
|
try {
|
|
441
|
-
|
|
467
|
+
writeFileSync2(CACHE_PATH, JSON.stringify({ token }), "utf8");
|
|
442
468
|
} catch {
|
|
443
469
|
}
|
|
444
470
|
}
|
|
@@ -502,9 +528,9 @@ async function checkLicense() {
|
|
|
502
528
|
let key = loadLicense();
|
|
503
529
|
if (!key) {
|
|
504
530
|
try {
|
|
505
|
-
const configPath =
|
|
506
|
-
if (
|
|
507
|
-
const raw = JSON.parse(
|
|
531
|
+
const configPath = path4.join(EXE_AI_DIR, "config.json");
|
|
532
|
+
if (existsSync4(configPath)) {
|
|
533
|
+
const raw = JSON.parse(readFileSync3(configPath, "utf8"));
|
|
508
534
|
const cloud = raw.cloud;
|
|
509
535
|
if (cloud?.apiKey) {
|
|
510
536
|
key = cloud.apiKey;
|
|
@@ -663,9 +689,9 @@ var init_license = __esm({
|
|
|
663
689
|
"src/lib/license.ts"() {
|
|
664
690
|
"use strict";
|
|
665
691
|
init_config();
|
|
666
|
-
LICENSE_PATH =
|
|
667
|
-
CACHE_PATH =
|
|
668
|
-
DEVICE_ID_PATH =
|
|
692
|
+
LICENSE_PATH = path4.join(EXE_AI_DIR, "license.key");
|
|
693
|
+
CACHE_PATH = path4.join(EXE_AI_DIR, "license-cache.json");
|
|
694
|
+
DEVICE_ID_PATH = path4.join(EXE_AI_DIR, "device-id");
|
|
669
695
|
API_BASE = "https://askexe.com/cloud";
|
|
670
696
|
RETRY_DELAY_MS = 500;
|
|
671
697
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
@@ -729,14 +755,12 @@ function isMainModule(importMetaUrl) {
|
|
|
729
755
|
}
|
|
730
756
|
|
|
731
757
|
// src/lib/cloud-sync.ts
|
|
758
|
+
init_database();
|
|
732
759
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, readdirSync, mkdirSync as mkdirSync2, appendFileSync, unlinkSync as unlinkSync2, openSync, closeSync } from "fs";
|
|
733
760
|
import crypto3 from "crypto";
|
|
734
761
|
import path5 from "path";
|
|
735
762
|
import { homedir } from "os";
|
|
736
763
|
|
|
737
|
-
// src/lib/database.ts
|
|
738
|
-
import { createClient } from "@libsql/client";
|
|
739
|
-
|
|
740
764
|
// src/lib/crypto.ts
|
|
741
765
|
import crypto2 from "crypto";
|
|
742
766
|
|
|
@@ -746,17 +770,7 @@ import { brotliCompressSync, brotliDecompressSync, constants } from "zlib";
|
|
|
746
770
|
// src/lib/cloud-sync.ts
|
|
747
771
|
init_license();
|
|
748
772
|
init_config();
|
|
749
|
-
|
|
750
|
-
// src/lib/employees.ts
|
|
751
|
-
init_config();
|
|
752
|
-
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
753
|
-
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
754
|
-
import { execSync } from "child_process";
|
|
755
|
-
import path4 from "path";
|
|
756
|
-
import os3 from "os";
|
|
757
|
-
var EMPLOYEES_PATH = path4.join(EXE_AI_DIR, "exe-employees.json");
|
|
758
|
-
|
|
759
|
-
// src/lib/cloud-sync.ts
|
|
773
|
+
init_employees();
|
|
760
774
|
var LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
|
|
761
775
|
var ROSTER_LOCK_PATH = path5.join(EXE_AI_DIR, "roster-merge.lock");
|
|
762
776
|
function assertSecureEndpoint(endpoint) {
|
|
@@ -846,8 +860,7 @@ async function setupMode() {
|
|
|
846
860
|
try {
|
|
847
861
|
assertSecureEndpoint(endpoint);
|
|
848
862
|
const resp = await fetch(`${endpoint}/auth/verify`, {
|
|
849
|
-
|
|
850
|
-
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
|
|
863
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
851
864
|
});
|
|
852
865
|
if (resp.ok) {
|
|
853
866
|
config.cloud = { apiKey, endpoint };
|