@askexenow/exe-os 0.9.111 → 0.9.113
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/README.md +9 -7
- package/dist/bin/agentic-ontology-backfill.js +62 -12
- package/dist/bin/agentic-reflection-backfill.js +37 -2
- package/dist/bin/agentic-semantic-label.js +37 -2
- package/dist/bin/backfill-conversations.js +61 -11
- package/dist/bin/backfill-responses.js +62 -12
- package/dist/bin/backfill-vectors.js +37 -2
- package/dist/bin/bulk-sync-postgres.js +63 -13
- package/dist/bin/cleanup-stale-review-tasks.js +83 -16
- package/dist/bin/cli.js +312 -80
- package/dist/bin/exe-agent-config.js +7 -1
- package/dist/bin/exe-agent.js +29 -3
- package/dist/bin/exe-assign.js +62 -12
- package/dist/bin/exe-boot.js +500 -151
- package/dist/bin/exe-call.js +46 -5
- package/dist/bin/exe-cloud.js +101 -16
- package/dist/bin/exe-dispatch.js +827 -27
- package/dist/bin/exe-doctor.js +61 -11
- package/dist/bin/exe-export-behaviors.js +67 -14
- package/dist/bin/exe-forget.js +62 -12
- package/dist/bin/exe-gateway.js +147 -27
- package/dist/bin/exe-heartbeat.js +83 -16
- package/dist/bin/exe-kill.js +62 -12
- package/dist/bin/exe-launch-agent.js +83 -15
- package/dist/bin/exe-new-employee.js +176 -8
- package/dist/bin/exe-pending-messages.js +83 -16
- package/dist/bin/exe-pending-notifications.js +83 -16
- package/dist/bin/exe-pending-reviews.js +83 -16
- package/dist/bin/exe-rename.js +62 -12
- package/dist/bin/exe-review.js +62 -12
- package/dist/bin/exe-search.js +62 -12
- package/dist/bin/exe-session-cleanup.js +949 -149
- package/dist/bin/exe-settings.js +10 -4
- package/dist/bin/exe-start-codex.js +537 -248
- package/dist/bin/exe-start-opencode.js +547 -168
- package/dist/bin/exe-status.js +83 -16
- package/dist/bin/exe-support.js +1 -1
- package/dist/bin/exe-team.js +62 -12
- package/dist/bin/git-sweep.js +827 -27
- package/dist/bin/graph-backfill.js +62 -12
- package/dist/bin/graph-export.js +62 -12
- package/dist/bin/install.js +62 -4
- package/dist/bin/intercom-check.js +949 -149
- package/dist/bin/pre-publish.js +14 -2
- package/dist/bin/scan-tasks.js +827 -27
- package/dist/bin/setup.js +99 -14
- package/dist/bin/shard-migrate.js +62 -12
- package/dist/bin/stack-update.js +1 -1
- package/dist/bin/update.js +3 -3
- package/dist/gateway/index.js +586 -26
- package/dist/hooks/bug-report-worker.js +586 -26
- package/dist/hooks/codex-stop-task-finalizer.js +977 -143
- package/dist/hooks/commit-complete.js +827 -27
- package/dist/hooks/error-recall.js +62 -12
- package/dist/hooks/ingest.js +4579 -249
- package/dist/hooks/instructions-loaded.js +62 -12
- package/dist/hooks/notification.js +62 -12
- package/dist/hooks/post-compact.js +83 -16
- package/dist/hooks/post-tool-combined.js +83 -16
- package/dist/hooks/pre-compact.js +907 -107
- package/dist/hooks/pre-tool-use.js +98 -16
- package/dist/hooks/prompt-submit.js +596 -30
- package/dist/hooks/session-end.js +909 -112
- package/dist/hooks/session-start.js +112 -17
- package/dist/hooks/stop.js +82 -15
- package/dist/hooks/subagent-stop.js +83 -16
- package/dist/hooks/summary-worker.js +81 -8
- package/dist/index.js +595 -29
- package/dist/lib/agent-config.js +16 -1
- package/dist/lib/cloud-sync.js +45 -1
- package/dist/lib/consolidation.js +16 -1
- package/dist/lib/database.js +23 -0
- package/dist/lib/db.js +23 -0
- package/dist/lib/device-registry.js +23 -0
- package/dist/lib/employee-templates.js +30 -4
- package/dist/lib/employees.js +16 -1
- package/dist/lib/exe-daemon.js +482 -52
- package/dist/lib/hybrid-search.js +62 -12
- package/dist/lib/license.js +3 -3
- package/dist/lib/messaging.js +21 -4
- package/dist/lib/schedules.js +37 -2
- package/dist/lib/skill-learning.js +910 -41
- package/dist/lib/status-brief.js +14 -1
- package/dist/lib/store.js +62 -12
- package/dist/lib/tasks.js +843 -93
- package/dist/lib/tmux-routing.js +766 -16
- package/dist/mcp/server.js +238 -41
- package/dist/mcp/tools/create-task.js +525 -15
- package/dist/mcp/tools/deactivate-behavior.js +33 -24
- package/dist/mcp/tools/list-tasks.js +21 -4
- package/dist/mcp/tools/send-message.js +21 -4
- package/dist/mcp/tools/update-task.js +840 -93
- package/dist/runtime/index.js +913 -107
- package/dist/tui/App.js +227 -58
- package/package.json +1 -1
|
@@ -2037,6 +2037,13 @@ async function ensureSchema() {
|
|
|
2037
2037
|
} catch (e) {
|
|
2038
2038
|
logCatchDebug("migration", e);
|
|
2039
2039
|
}
|
|
2040
|
+
for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
|
|
2041
|
+
try {
|
|
2042
|
+
await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
|
|
2043
|
+
} catch (e) {
|
|
2044
|
+
logCatchDebug("migration", e);
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2040
2047
|
try {
|
|
2041
2048
|
await client.execute({
|
|
2042
2049
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -3253,6 +3260,22 @@ async function ensureSchema() {
|
|
|
3253
3260
|
} catch (e) {
|
|
3254
3261
|
logCatchDebug("migration", e);
|
|
3255
3262
|
}
|
|
3263
|
+
try {
|
|
3264
|
+
await client.execute({
|
|
3265
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
3266
|
+
args: []
|
|
3267
|
+
});
|
|
3268
|
+
} catch (e) {
|
|
3269
|
+
logCatchDebug("migration", e);
|
|
3270
|
+
}
|
|
3271
|
+
try {
|
|
3272
|
+
await client.execute({
|
|
3273
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
3274
|
+
args: []
|
|
3275
|
+
});
|
|
3276
|
+
} catch (e) {
|
|
3277
|
+
logCatchDebug("migration", e);
|
|
3278
|
+
}
|
|
3256
3279
|
}
|
|
3257
3280
|
async function disposeDatabase() {
|
|
3258
3281
|
if (_walCheckpointTimer) {
|
|
@@ -3603,7 +3626,7 @@ var init_license = __esm({
|
|
|
3603
3626
|
LICENSE_PATH = path9.join(EXE_AI_DIR, "license.key");
|
|
3604
3627
|
CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
|
|
3605
3628
|
DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
|
|
3606
|
-
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
3629
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
3607
3630
|
}
|
|
3608
3631
|
});
|
|
3609
3632
|
|
|
@@ -3656,6 +3679,18 @@ function extractRootExe(name) {
|
|
|
3656
3679
|
const parts = name.split("-").filter(Boolean);
|
|
3657
3680
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
3658
3681
|
}
|
|
3682
|
+
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
3683
|
+
if (!existsSync12(SESSION_CACHE)) {
|
|
3684
|
+
mkdirSync6(SESSION_CACHE, { recursive: true });
|
|
3685
|
+
}
|
|
3686
|
+
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
3687
|
+
const filePath = path12.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
3688
|
+
writeFileSync6(filePath, JSON.stringify({
|
|
3689
|
+
parentExe: rootExe,
|
|
3690
|
+
dispatchedBy: dispatchedBy || rootExe,
|
|
3691
|
+
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3692
|
+
}));
|
|
3693
|
+
}
|
|
3659
3694
|
function getParentExe(sessionKey) {
|
|
3660
3695
|
try {
|
|
3661
3696
|
const data = JSON.parse(readFileSync9(path12.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
@@ -3665,11 +3700,12 @@ function getParentExe(sessionKey) {
|
|
|
3665
3700
|
}
|
|
3666
3701
|
}
|
|
3667
3702
|
function resolveExeSession() {
|
|
3703
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
3704
|
+
const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
3705
|
+
if (fromEnv) return fromEnv;
|
|
3706
|
+
}
|
|
3668
3707
|
const mySession = getMySession();
|
|
3669
3708
|
if (!mySession) {
|
|
3670
|
-
if (process.env.EXE_SESSION_NAME) {
|
|
3671
|
-
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
3672
|
-
}
|
|
3673
3709
|
return null;
|
|
3674
3710
|
}
|
|
3675
3711
|
const fromSessionName = extractRootExe(mySession);
|
|
@@ -3684,6 +3720,10 @@ function resolveExeSession() {
|
|
|
3684
3720
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
3685
3721
|
`
|
|
3686
3722
|
);
|
|
3723
|
+
try {
|
|
3724
|
+
registerParentExe(key, fromSessionName);
|
|
3725
|
+
} catch {
|
|
3726
|
+
}
|
|
3687
3727
|
candidate = fromSessionName;
|
|
3688
3728
|
} else {
|
|
3689
3729
|
candidate = fromCache;
|
|
@@ -4912,11 +4952,17 @@ var init_platform_procedures = __esm({
|
|
|
4912
4952
|
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator 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."
|
|
4913
4953
|
},
|
|
4914
4954
|
{
|
|
4915
|
-
title: "
|
|
4955
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
4916
4956
|
domain: "workflow",
|
|
4917
4957
|
priority: "p1",
|
|
4918
4958
|
content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
|
|
4919
4959
|
},
|
|
4960
|
+
{
|
|
4961
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
4962
|
+
domain: "identity",
|
|
4963
|
+
priority: "p0",
|
|
4964
|
+
content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
|
|
4965
|
+
},
|
|
4920
4966
|
{
|
|
4921
4967
|
title: "Single dispatch path \u2014 create_task only",
|
|
4922
4968
|
domain: "workflow",
|
|
@@ -4950,6 +4996,12 @@ var init_platform_procedures = __esm({
|
|
|
4950
4996
|
priority: "p0",
|
|
4951
4997
|
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."
|
|
4952
4998
|
},
|
|
4999
|
+
{
|
|
5000
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
5001
|
+
domain: "security",
|
|
5002
|
+
priority: "p0",
|
|
5003
|
+
content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
|
|
5004
|
+
},
|
|
4953
5005
|
{
|
|
4954
5006
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
4955
5007
|
domain: "support",
|
|
@@ -5101,7 +5153,7 @@ var init_platform_procedures = __esm({
|
|
|
5101
5153
|
title: "MCP tool dispatch \u2014 all tools use action parameter",
|
|
5102
5154
|
domain: "tool-use",
|
|
5103
5155
|
priority: "p0",
|
|
5104
|
-
content: 'exe-os MCP tools
|
|
5156
|
+
content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
|
|
5105
5157
|
},
|
|
5106
5158
|
{
|
|
5107
5159
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
@@ -5235,10 +5287,24 @@ function stableId(memoryId, type, content) {
|
|
|
5235
5287
|
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
5236
5288
|
}
|
|
5237
5289
|
function cleanText(text) {
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5290
|
+
let cleaned = text.replace(
|
|
5291
|
+
/```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
|
|
5292
|
+
(_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
|
|
5293
|
+
);
|
|
5294
|
+
cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
5295
|
+
return cleaned;
|
|
5296
|
+
}
|
|
5297
|
+
function splitSegments(text) {
|
|
5298
|
+
const cleaned = cleanText(text);
|
|
5299
|
+
const segments = cleaned.split(/(?<=[.!?:;])\s+|\n{2,}|(?<=\))\s+(?=[A-Z])|\s*[|│]\s*/).map((s) => s.trim()).filter((s) => s.length >= MIN_SEGMENT_CHARS && s.length <= MAX_SEGMENT_CHARS);
|
|
5300
|
+
if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
5301
|
+
const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
|
|
5302
|
+
if (lines.length > 0) return lines;
|
|
5303
|
+
if (cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
5304
|
+
return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5307
|
+
return segments;
|
|
5242
5308
|
}
|
|
5243
5309
|
function inferCardType(sentence, toolName) {
|
|
5244
5310
|
const lower = sentence.toLowerCase();
|
|
@@ -5270,12 +5336,12 @@ function predicateFor(type) {
|
|
|
5270
5336
|
}
|
|
5271
5337
|
}
|
|
5272
5338
|
function extractMemoryCards(row) {
|
|
5273
|
-
const
|
|
5339
|
+
const segments = splitSegments(row.raw_text);
|
|
5274
5340
|
const cards = [];
|
|
5275
|
-
for (const sentence of
|
|
5341
|
+
for (const sentence of segments) {
|
|
5276
5342
|
const type = inferCardType(sentence, row.tool_name);
|
|
5277
5343
|
const subject = extractSubject(sentence, row.agent_id);
|
|
5278
|
-
const content = sentence.length >
|
|
5344
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
5279
5345
|
cards.push({
|
|
5280
5346
|
id: stableId(row.id, type, content),
|
|
5281
5347
|
memory_id: row.id,
|
|
@@ -5371,13 +5437,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
5371
5437
|
last_accessed: String(row.timestamp)
|
|
5372
5438
|
}));
|
|
5373
5439
|
}
|
|
5374
|
-
var MAX_CARDS_PER_MEMORY,
|
|
5440
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
5375
5441
|
var init_memory_cards = __esm({
|
|
5376
5442
|
"src/lib/memory-cards.ts"() {
|
|
5377
5443
|
"use strict";
|
|
5378
5444
|
init_database();
|
|
5379
|
-
MAX_CARDS_PER_MEMORY =
|
|
5380
|
-
|
|
5445
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
5446
|
+
MAX_SEGMENT_CHARS = 500;
|
|
5447
|
+
MIN_SEGMENT_CHARS = 20;
|
|
5381
5448
|
}
|
|
5382
5449
|
});
|
|
5383
5450
|
|
|
@@ -2037,6 +2037,13 @@ async function ensureSchema() {
|
|
|
2037
2037
|
} catch (e) {
|
|
2038
2038
|
logCatchDebug("migration", e);
|
|
2039
2039
|
}
|
|
2040
|
+
for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
|
|
2041
|
+
try {
|
|
2042
|
+
await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
|
|
2043
|
+
} catch (e) {
|
|
2044
|
+
logCatchDebug("migration", e);
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2040
2047
|
try {
|
|
2041
2048
|
await client.execute({
|
|
2042
2049
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -3253,6 +3260,22 @@ async function ensureSchema() {
|
|
|
3253
3260
|
} catch (e) {
|
|
3254
3261
|
logCatchDebug("migration", e);
|
|
3255
3262
|
}
|
|
3263
|
+
try {
|
|
3264
|
+
await client.execute({
|
|
3265
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
3266
|
+
args: []
|
|
3267
|
+
});
|
|
3268
|
+
} catch (e) {
|
|
3269
|
+
logCatchDebug("migration", e);
|
|
3270
|
+
}
|
|
3271
|
+
try {
|
|
3272
|
+
await client.execute({
|
|
3273
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
3274
|
+
args: []
|
|
3275
|
+
});
|
|
3276
|
+
} catch (e) {
|
|
3277
|
+
logCatchDebug("migration", e);
|
|
3278
|
+
}
|
|
3256
3279
|
}
|
|
3257
3280
|
async function disposeDatabase() {
|
|
3258
3281
|
if (_walCheckpointTimer) {
|
|
@@ -3603,7 +3626,7 @@ var init_license = __esm({
|
|
|
3603
3626
|
LICENSE_PATH = path9.join(EXE_AI_DIR, "license.key");
|
|
3604
3627
|
CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
|
|
3605
3628
|
DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
|
|
3606
|
-
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
3629
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
3607
3630
|
}
|
|
3608
3631
|
});
|
|
3609
3632
|
|
|
@@ -3656,6 +3679,18 @@ function extractRootExe(name) {
|
|
|
3656
3679
|
const parts = name.split("-").filter(Boolean);
|
|
3657
3680
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
3658
3681
|
}
|
|
3682
|
+
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
3683
|
+
if (!existsSync12(SESSION_CACHE)) {
|
|
3684
|
+
mkdirSync6(SESSION_CACHE, { recursive: true });
|
|
3685
|
+
}
|
|
3686
|
+
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
3687
|
+
const filePath = path12.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
3688
|
+
writeFileSync6(filePath, JSON.stringify({
|
|
3689
|
+
parentExe: rootExe,
|
|
3690
|
+
dispatchedBy: dispatchedBy || rootExe,
|
|
3691
|
+
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3692
|
+
}));
|
|
3693
|
+
}
|
|
3659
3694
|
function getParentExe(sessionKey) {
|
|
3660
3695
|
try {
|
|
3661
3696
|
const data = JSON.parse(readFileSync9(path12.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
@@ -3665,11 +3700,12 @@ function getParentExe(sessionKey) {
|
|
|
3665
3700
|
}
|
|
3666
3701
|
}
|
|
3667
3702
|
function resolveExeSession() {
|
|
3703
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
3704
|
+
const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
3705
|
+
if (fromEnv) return fromEnv;
|
|
3706
|
+
}
|
|
3668
3707
|
const mySession = getMySession();
|
|
3669
3708
|
if (!mySession) {
|
|
3670
|
-
if (process.env.EXE_SESSION_NAME) {
|
|
3671
|
-
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
3672
|
-
}
|
|
3673
3709
|
return null;
|
|
3674
3710
|
}
|
|
3675
3711
|
const fromSessionName = extractRootExe(mySession);
|
|
@@ -3684,6 +3720,10 @@ function resolveExeSession() {
|
|
|
3684
3720
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
3685
3721
|
`
|
|
3686
3722
|
);
|
|
3723
|
+
try {
|
|
3724
|
+
registerParentExe(key, fromSessionName);
|
|
3725
|
+
} catch {
|
|
3726
|
+
}
|
|
3687
3727
|
candidate = fromSessionName;
|
|
3688
3728
|
} else {
|
|
3689
3729
|
candidate = fromCache;
|
|
@@ -4951,11 +4991,17 @@ var init_platform_procedures = __esm({
|
|
|
4951
4991
|
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator 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."
|
|
4952
4992
|
},
|
|
4953
4993
|
{
|
|
4954
|
-
title: "
|
|
4994
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
4955
4995
|
domain: "workflow",
|
|
4956
4996
|
priority: "p1",
|
|
4957
4997
|
content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
|
|
4958
4998
|
},
|
|
4999
|
+
{
|
|
5000
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
5001
|
+
domain: "identity",
|
|
5002
|
+
priority: "p0",
|
|
5003
|
+
content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
|
|
5004
|
+
},
|
|
4959
5005
|
{
|
|
4960
5006
|
title: "Single dispatch path \u2014 create_task only",
|
|
4961
5007
|
domain: "workflow",
|
|
@@ -4989,6 +5035,12 @@ var init_platform_procedures = __esm({
|
|
|
4989
5035
|
priority: "p0",
|
|
4990
5036
|
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."
|
|
4991
5037
|
},
|
|
5038
|
+
{
|
|
5039
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
5040
|
+
domain: "security",
|
|
5041
|
+
priority: "p0",
|
|
5042
|
+
content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
|
|
5043
|
+
},
|
|
4992
5044
|
{
|
|
4993
5045
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
4994
5046
|
domain: "support",
|
|
@@ -5140,7 +5192,7 @@ var init_platform_procedures = __esm({
|
|
|
5140
5192
|
title: "MCP tool dispatch \u2014 all tools use action parameter",
|
|
5141
5193
|
domain: "tool-use",
|
|
5142
5194
|
priority: "p0",
|
|
5143
|
-
content: 'exe-os MCP tools
|
|
5195
|
+
content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
|
|
5144
5196
|
},
|
|
5145
5197
|
{
|
|
5146
5198
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
@@ -5274,10 +5326,24 @@ function stableId(memoryId, type, content) {
|
|
|
5274
5326
|
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
5275
5327
|
}
|
|
5276
5328
|
function cleanText(text) {
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5329
|
+
let cleaned = text.replace(
|
|
5330
|
+
/```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
|
|
5331
|
+
(_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
|
|
5332
|
+
);
|
|
5333
|
+
cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
5334
|
+
return cleaned;
|
|
5335
|
+
}
|
|
5336
|
+
function splitSegments(text) {
|
|
5337
|
+
const cleaned = cleanText(text);
|
|
5338
|
+
const segments = cleaned.split(/(?<=[.!?:;])\s+|\n{2,}|(?<=\))\s+(?=[A-Z])|\s*[|│]\s*/).map((s) => s.trim()).filter((s) => s.length >= MIN_SEGMENT_CHARS && s.length <= MAX_SEGMENT_CHARS);
|
|
5339
|
+
if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
5340
|
+
const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
|
|
5341
|
+
if (lines.length > 0) return lines;
|
|
5342
|
+
if (cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
5343
|
+
return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
|
|
5344
|
+
}
|
|
5345
|
+
}
|
|
5346
|
+
return segments;
|
|
5281
5347
|
}
|
|
5282
5348
|
function inferCardType(sentence, toolName) {
|
|
5283
5349
|
const lower = sentence.toLowerCase();
|
|
@@ -5309,12 +5375,12 @@ function predicateFor(type) {
|
|
|
5309
5375
|
}
|
|
5310
5376
|
}
|
|
5311
5377
|
function extractMemoryCards(row) {
|
|
5312
|
-
const
|
|
5378
|
+
const segments = splitSegments(row.raw_text);
|
|
5313
5379
|
const cards = [];
|
|
5314
|
-
for (const sentence of
|
|
5380
|
+
for (const sentence of segments) {
|
|
5315
5381
|
const type = inferCardType(sentence, row.tool_name);
|
|
5316
5382
|
const subject = extractSubject(sentence, row.agent_id);
|
|
5317
|
-
const content = sentence.length >
|
|
5383
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
5318
5384
|
cards.push({
|
|
5319
5385
|
id: stableId(row.id, type, content),
|
|
5320
5386
|
memory_id: row.id,
|
|
@@ -5410,13 +5476,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
5410
5476
|
last_accessed: String(row.timestamp)
|
|
5411
5477
|
}));
|
|
5412
5478
|
}
|
|
5413
|
-
var MAX_CARDS_PER_MEMORY,
|
|
5479
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
5414
5480
|
var init_memory_cards = __esm({
|
|
5415
5481
|
"src/lib/memory-cards.ts"() {
|
|
5416
5482
|
"use strict";
|
|
5417
5483
|
init_database();
|
|
5418
|
-
MAX_CARDS_PER_MEMORY =
|
|
5419
|
-
|
|
5484
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
5485
|
+
MAX_SEGMENT_CHARS = 500;
|
|
5486
|
+
MIN_SEGMENT_CHARS = 20;
|
|
5420
5487
|
}
|
|
5421
5488
|
});
|
|
5422
5489
|
|
package/dist/bin/exe-rename.js
CHANGED
|
@@ -1881,6 +1881,13 @@ async function ensureSchema() {
|
|
|
1881
1881
|
} catch (e) {
|
|
1882
1882
|
logCatchDebug("migration", e);
|
|
1883
1883
|
}
|
|
1884
|
+
for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
|
|
1885
|
+
try {
|
|
1886
|
+
await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
|
|
1887
|
+
} catch (e) {
|
|
1888
|
+
logCatchDebug("migration", e);
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1884
1891
|
try {
|
|
1885
1892
|
await client.execute({
|
|
1886
1893
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -3097,6 +3104,22 @@ async function ensureSchema() {
|
|
|
3097
3104
|
} catch (e) {
|
|
3098
3105
|
logCatchDebug("migration", e);
|
|
3099
3106
|
}
|
|
3107
|
+
try {
|
|
3108
|
+
await client.execute({
|
|
3109
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
3110
|
+
args: []
|
|
3111
|
+
});
|
|
3112
|
+
} catch (e) {
|
|
3113
|
+
logCatchDebug("migration", e);
|
|
3114
|
+
}
|
|
3115
|
+
try {
|
|
3116
|
+
await client.execute({
|
|
3117
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
3118
|
+
args: []
|
|
3119
|
+
});
|
|
3120
|
+
} catch (e) {
|
|
3121
|
+
logCatchDebug("migration", e);
|
|
3122
|
+
}
|
|
3100
3123
|
}
|
|
3101
3124
|
async function disposeDatabase() {
|
|
3102
3125
|
if (_walCheckpointTimer) {
|
|
@@ -3199,11 +3222,17 @@ var init_platform_procedures = __esm({
|
|
|
3199
3222
|
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator 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."
|
|
3200
3223
|
},
|
|
3201
3224
|
{
|
|
3202
|
-
title: "
|
|
3225
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
3203
3226
|
domain: "workflow",
|
|
3204
3227
|
priority: "p1",
|
|
3205
3228
|
content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
|
|
3206
3229
|
},
|
|
3230
|
+
{
|
|
3231
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
3232
|
+
domain: "identity",
|
|
3233
|
+
priority: "p0",
|
|
3234
|
+
content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
|
|
3235
|
+
},
|
|
3207
3236
|
{
|
|
3208
3237
|
title: "Single dispatch path \u2014 create_task only",
|
|
3209
3238
|
domain: "workflow",
|
|
@@ -3237,6 +3266,12 @@ var init_platform_procedures = __esm({
|
|
|
3237
3266
|
priority: "p0",
|
|
3238
3267
|
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."
|
|
3239
3268
|
},
|
|
3269
|
+
{
|
|
3270
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
3271
|
+
domain: "security",
|
|
3272
|
+
priority: "p0",
|
|
3273
|
+
content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
|
|
3274
|
+
},
|
|
3240
3275
|
{
|
|
3241
3276
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
3242
3277
|
domain: "support",
|
|
@@ -3388,7 +3423,7 @@ var init_platform_procedures = __esm({
|
|
|
3388
3423
|
title: "MCP tool dispatch \u2014 all tools use action parameter",
|
|
3389
3424
|
domain: "tool-use",
|
|
3390
3425
|
priority: "p0",
|
|
3391
|
-
content: 'exe-os MCP tools
|
|
3426
|
+
content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
|
|
3392
3427
|
},
|
|
3393
3428
|
{
|
|
3394
3429
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
@@ -4543,10 +4578,24 @@ function stableId(memoryId, type, content) {
|
|
|
4543
4578
|
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
4544
4579
|
}
|
|
4545
4580
|
function cleanText(text) {
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4581
|
+
let cleaned = text.replace(
|
|
4582
|
+
/```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
|
|
4583
|
+
(_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
|
|
4584
|
+
);
|
|
4585
|
+
cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
4586
|
+
return cleaned;
|
|
4587
|
+
}
|
|
4588
|
+
function splitSegments(text) {
|
|
4589
|
+
const cleaned = cleanText(text);
|
|
4590
|
+
const segments = cleaned.split(/(?<=[.!?:;])\s+|\n{2,}|(?<=\))\s+(?=[A-Z])|\s*[|│]\s*/).map((s) => s.trim()).filter((s) => s.length >= MIN_SEGMENT_CHARS && s.length <= MAX_SEGMENT_CHARS);
|
|
4591
|
+
if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
4592
|
+
const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
|
|
4593
|
+
if (lines.length > 0) return lines;
|
|
4594
|
+
if (cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
4595
|
+
return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
|
|
4596
|
+
}
|
|
4597
|
+
}
|
|
4598
|
+
return segments;
|
|
4550
4599
|
}
|
|
4551
4600
|
function inferCardType(sentence, toolName) {
|
|
4552
4601
|
const lower = sentence.toLowerCase();
|
|
@@ -4578,12 +4627,12 @@ function predicateFor(type) {
|
|
|
4578
4627
|
}
|
|
4579
4628
|
}
|
|
4580
4629
|
function extractMemoryCards(row) {
|
|
4581
|
-
const
|
|
4630
|
+
const segments = splitSegments(row.raw_text);
|
|
4582
4631
|
const cards = [];
|
|
4583
|
-
for (const sentence of
|
|
4632
|
+
for (const sentence of segments) {
|
|
4584
4633
|
const type = inferCardType(sentence, row.tool_name);
|
|
4585
4634
|
const subject = extractSubject(sentence, row.agent_id);
|
|
4586
|
-
const content = sentence.length >
|
|
4635
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
4587
4636
|
cards.push({
|
|
4588
4637
|
id: stableId(row.id, type, content),
|
|
4589
4638
|
memory_id: row.id,
|
|
@@ -4679,13 +4728,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
4679
4728
|
last_accessed: String(row.timestamp)
|
|
4680
4729
|
}));
|
|
4681
4730
|
}
|
|
4682
|
-
var MAX_CARDS_PER_MEMORY,
|
|
4731
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
4683
4732
|
var init_memory_cards = __esm({
|
|
4684
4733
|
"src/lib/memory-cards.ts"() {
|
|
4685
4734
|
"use strict";
|
|
4686
4735
|
init_database();
|
|
4687
|
-
MAX_CARDS_PER_MEMORY =
|
|
4688
|
-
|
|
4736
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
4737
|
+
MAX_SEGMENT_CHARS = 500;
|
|
4738
|
+
MIN_SEGMENT_CHARS = 20;
|
|
4689
4739
|
}
|
|
4690
4740
|
});
|
|
4691
4741
|
|