@askexenow/exe-os 0.9.60 → 0.9.61

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.
Files changed (73) hide show
  1. package/dist/bin/backfill-conversations.js +72 -5
  2. package/dist/bin/backfill-responses.js +72 -5
  3. package/dist/bin/backfill-vectors.js +72 -5
  4. package/dist/bin/cc-doctor.js +376 -0
  5. package/dist/bin/cleanup-stale-review-tasks.js +72 -5
  6. package/dist/bin/cli.js +157 -55
  7. package/dist/bin/customer-readiness.js +33 -0
  8. package/dist/bin/exe-agent.js +1 -1
  9. package/dist/bin/exe-assign.js +72 -5
  10. package/dist/bin/exe-boot.js +78 -11
  11. package/dist/bin/exe-call.js +1 -1
  12. package/dist/bin/exe-dispatch.js +72 -5
  13. package/dist/bin/exe-doctor.js +72 -5
  14. package/dist/bin/exe-export-behaviors.js +72 -5
  15. package/dist/bin/exe-forget.js +72 -5
  16. package/dist/bin/exe-gateway.js +72 -5
  17. package/dist/bin/exe-heartbeat.js +72 -5
  18. package/dist/bin/exe-kill.js +72 -5
  19. package/dist/bin/exe-launch-agent.js +72 -5
  20. package/dist/bin/exe-link.js +74 -7
  21. package/dist/bin/exe-new-employee.js +48 -19
  22. package/dist/bin/exe-pending-messages.js +72 -5
  23. package/dist/bin/exe-pending-notifications.js +72 -5
  24. package/dist/bin/exe-pending-reviews.js +72 -5
  25. package/dist/bin/exe-rename.js +72 -5
  26. package/dist/bin/exe-review.js +72 -5
  27. package/dist/bin/exe-search.js +72 -5
  28. package/dist/bin/exe-session-cleanup.js +72 -5
  29. package/dist/bin/exe-start-codex.js +115 -18
  30. package/dist/bin/exe-start-opencode.js +93 -7
  31. package/dist/bin/exe-status.js +72 -5
  32. package/dist/bin/exe-team.js +72 -5
  33. package/dist/bin/git-sweep.js +72 -5
  34. package/dist/bin/graph-backfill.js +72 -5
  35. package/dist/bin/graph-export.js +72 -5
  36. package/dist/bin/install.js +56 -31
  37. package/dist/bin/intercom-check.js +72 -5
  38. package/dist/bin/pre-build-guard.js +98 -0
  39. package/dist/bin/scan-tasks.js +72 -5
  40. package/dist/bin/setup.js +75 -8
  41. package/dist/bin/shard-migrate.js +72 -5
  42. package/dist/gateway/index.js +78 -11
  43. package/dist/hooks/bug-report-worker.js +72 -5
  44. package/dist/hooks/codex-stop-task-finalizer.js +72 -5
  45. package/dist/hooks/commit-complete.js +72 -5
  46. package/dist/hooks/error-recall.js +72 -5
  47. package/dist/hooks/ingest.js +72 -5
  48. package/dist/hooks/instructions-loaded.js +72 -5
  49. package/dist/hooks/notification.js +72 -5
  50. package/dist/hooks/post-compact.js +72 -5
  51. package/dist/hooks/post-tool-combined.js +72 -5
  52. package/dist/hooks/pre-compact.js +72 -5
  53. package/dist/hooks/pre-tool-use.js +72 -5
  54. package/dist/hooks/prompt-submit.js +72 -5
  55. package/dist/hooks/session-end.js +72 -5
  56. package/dist/hooks/session-start.js +72 -5
  57. package/dist/hooks/stop.js +72 -5
  58. package/dist/hooks/subagent-stop.js +72 -5
  59. package/dist/hooks/summary-worker.js +78 -11
  60. package/dist/index.js +78 -11
  61. package/dist/lib/cloud-sync.js +74 -7
  62. package/dist/lib/database.js +68 -1
  63. package/dist/lib/db.js +68 -1
  64. package/dist/lib/device-registry.js +68 -1
  65. package/dist/lib/employee-templates.js +1 -1
  66. package/dist/lib/exe-daemon.js +103 -26
  67. package/dist/lib/hybrid-search.js +72 -5
  68. package/dist/lib/schedules.js +72 -5
  69. package/dist/lib/store.js +72 -5
  70. package/dist/mcp/server.js +103 -26
  71. package/dist/runtime/index.js +72 -5
  72. package/dist/tui/App.js +80 -13
  73. package/package.json +1 -1
@@ -2603,7 +2603,7 @@ async function ensureSchema() {
2603
2603
  ON session_kills(agent_id);
2604
2604
  `);
2605
2605
  await client.execute(`
2606
- CREATE TABLE IF NOT EXISTS global_procedures (
2606
+ CREATE TABLE IF NOT EXISTS company_procedures (
2607
2607
  id TEXT PRIMARY KEY,
2608
2608
  title TEXT NOT NULL,
2609
2609
  content TEXT NOT NULL,
@@ -2614,6 +2614,73 @@ async function ensureSchema() {
2614
2614
  updated_at TEXT NOT NULL
2615
2615
  )
2616
2616
  `);
2617
+ const legacyProcedureObject = await client.execute({
2618
+ sql: "SELECT type FROM sqlite_master WHERE name = 'global_procedures'",
2619
+ args: []
2620
+ });
2621
+ const legacyProcedureType = legacyProcedureObject.rows[0]?.type == null ? null : String(legacyProcedureObject.rows[0].type);
2622
+ if (legacyProcedureType === "table") {
2623
+ await client.execute(`
2624
+ INSERT OR IGNORE INTO company_procedures
2625
+ (id, title, content, priority, domain, active, created_at, updated_at)
2626
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
2627
+ FROM global_procedures
2628
+ `);
2629
+ await client.executeMultiple(`
2630
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_insert
2631
+ AFTER INSERT ON global_procedures
2632
+ BEGIN
2633
+ INSERT OR IGNORE INTO company_procedures
2634
+ (id, title, content, priority, domain, active, created_at, updated_at)
2635
+ VALUES
2636
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
2637
+ END;
2638
+
2639
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_update
2640
+ AFTER UPDATE ON global_procedures
2641
+ BEGIN
2642
+ UPDATE company_procedures
2643
+ SET title = NEW.title,
2644
+ content = NEW.content,
2645
+ priority = NEW.priority,
2646
+ domain = NEW.domain,
2647
+ active = NEW.active,
2648
+ created_at = NEW.created_at,
2649
+ updated_at = NEW.updated_at
2650
+ WHERE id = OLD.id;
2651
+ END;
2652
+ `);
2653
+ } else {
2654
+ await client.execute(`
2655
+ CREATE VIEW IF NOT EXISTS global_procedures AS
2656
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
2657
+ FROM company_procedures
2658
+ `);
2659
+ await client.executeMultiple(`
2660
+ CREATE TRIGGER IF NOT EXISTS global_procedures_insert
2661
+ INSTEAD OF INSERT ON global_procedures
2662
+ BEGIN
2663
+ INSERT INTO company_procedures
2664
+ (id, title, content, priority, domain, active, created_at, updated_at)
2665
+ VALUES
2666
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
2667
+ END;
2668
+
2669
+ CREATE TRIGGER IF NOT EXISTS global_procedures_update
2670
+ INSTEAD OF UPDATE ON global_procedures
2671
+ BEGIN
2672
+ UPDATE company_procedures
2673
+ SET title = NEW.title,
2674
+ content = NEW.content,
2675
+ priority = NEW.priority,
2676
+ domain = NEW.domain,
2677
+ active = NEW.active,
2678
+ created_at = NEW.created_at,
2679
+ updated_at = NEW.updated_at
2680
+ WHERE id = OLD.id;
2681
+ END;
2682
+ `);
2683
+ }
2617
2684
  await client.executeMultiple(`
2618
2685
  CREATE TABLE IF NOT EXISTS conversations (
2619
2686
  id TEXT PRIMARY KEY,
@@ -3962,7 +4029,7 @@ var init_platform_procedures = __esm({
3962
4029
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
3963
4030
  domain: "tool-use",
3964
4031
  priority: "p1",
3965
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
4032
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
3966
4033
  }
3967
4034
  ];
3968
4035
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -3983,7 +4050,7 @@ import { randomUUID as randomUUID2 } from "crypto";
3983
4050
  async function loadGlobalProcedures() {
3984
4051
  const client = getClient();
3985
4052
  const result = await client.execute({
3986
- sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
4053
+ sql: "SELECT * FROM company_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
3987
4054
  args: []
3988
4055
  });
3989
4056
  const allRows = result.rows;
@@ -4012,7 +4079,7 @@ async function storeGlobalProcedure(input) {
4012
4079
  const now = (/* @__PURE__ */ new Date()).toISOString();
4013
4080
  const client = getClient();
4014
4081
  await client.execute({
4015
- sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
4082
+ sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
4016
4083
  VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
4017
4084
  args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
4018
4085
  });
@@ -4023,7 +4090,7 @@ async function deactivateGlobalProcedure(id) {
4023
4090
  const now = (/* @__PURE__ */ new Date()).toISOString();
4024
4091
  const client = getClient();
4025
4092
  const result = await client.execute({
4026
- sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
4093
+ sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
4027
4094
  args: [now, id]
4028
4095
  });
4029
4096
  await loadGlobalProcedures();
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/bin/pre-build-guard.ts
4
+ import { execSync } from "child_process";
5
+ import { lstatSync } from "fs";
6
+ import path from "path";
7
+ function isSymlinked() {
8
+ try {
9
+ const npmRoot = execSync("npm root -g", { encoding: "utf8" }).trim();
10
+ const exeOsPath = path.join(npmRoot, "exe-os");
11
+ const stat = lstatSync(exeOsPath);
12
+ return stat.isSymbolicLink();
13
+ } catch {
14
+ return false;
15
+ }
16
+ }
17
+ function countMcpProcesses() {
18
+ try {
19
+ const result = execSync("pgrep -f 'node.*mcp/server.js' || true", {
20
+ encoding: "utf8"
21
+ });
22
+ return result.trim().split("\n").filter(Boolean).length;
23
+ } catch {
24
+ return 0;
25
+ }
26
+ }
27
+ function isWorktree() {
28
+ try {
29
+ const gitDir = execSync("git rev-parse --git-dir 2>/dev/null", {
30
+ encoding: "utf8"
31
+ }).trim();
32
+ return gitDir.includes(".git/worktrees/");
33
+ } catch {
34
+ return false;
35
+ }
36
+ }
37
+ function isBlockedAgent() {
38
+ const agentId = process.env.AGENT_ID?.toLowerCase();
39
+ if (!agentId) return null;
40
+ const agentRole = process.env.AGENT_ROLE?.toLowerCase();
41
+ if (agentRole === "coo" || agentRole === "cto") return null;
42
+ return agentId;
43
+ }
44
+ function main() {
45
+ if (isWorktree()) {
46
+ console.error(
47
+ "\n\u{1F6AB} [exe-os] BLOCKED: Cannot run deploy from a git worktree."
48
+ );
49
+ console.error(
50
+ " Deploying from a worktree re-registers all CC hooks pointing at the"
51
+ );
52
+ console.error(
53
+ " worktree dist/. When the worktree is deleted, every hook breaks."
54
+ );
55
+ console.error(
56
+ " Use `npm run build` only. Deploy runs from the main repo root.\n"
57
+ );
58
+ process.exit(1);
59
+ }
60
+ const blockedAgent = isBlockedAgent();
61
+ if (blockedAgent) {
62
+ console.error(
63
+ `
64
+ \u{1F6AB} [exe-os] BLOCKED: Agent "${blockedAgent}" cannot run deploy.`
65
+ );
66
+ console.error(
67
+ " Only the coordinator (COO) and CTO may deploy. Engineers and"
68
+ );
69
+ console.error(
70
+ " specialists use `npm run build` only.\n"
71
+ );
72
+ process.exit(1);
73
+ }
74
+ if (!isSymlinked()) {
75
+ return;
76
+ }
77
+ const mcpCount = countMcpProcesses();
78
+ if (mcpCount === 0) {
79
+ return;
80
+ }
81
+ console.error(
82
+ `
83
+ \u26A0\uFE0F [exe-os] DEV MODE: ${mcpCount} active MCP server process(es) detected.`
84
+ );
85
+ console.error(
86
+ " Rebuilding will overwrite dist/ files they reference, causing disconnections."
87
+ );
88
+ console.error(
89
+ " MCP servers will auto-reconnect on the next tool call, but in-flight"
90
+ );
91
+ console.error(
92
+ " operations may fail with SQLITE_BUSY during the reconnect storm."
93
+ );
94
+ console.error(
95
+ " Consider: wait for idle agents, or restart the MCP server after build.\n"
96
+ );
97
+ }
98
+ main();
@@ -3095,7 +3095,7 @@ async function ensureSchema() {
3095
3095
  ON session_kills(agent_id);
3096
3096
  `);
3097
3097
  await client.execute(`
3098
- CREATE TABLE IF NOT EXISTS global_procedures (
3098
+ CREATE TABLE IF NOT EXISTS company_procedures (
3099
3099
  id TEXT PRIMARY KEY,
3100
3100
  title TEXT NOT NULL,
3101
3101
  content TEXT NOT NULL,
@@ -3106,6 +3106,73 @@ async function ensureSchema() {
3106
3106
  updated_at TEXT NOT NULL
3107
3107
  )
3108
3108
  `);
3109
+ const legacyProcedureObject = await client.execute({
3110
+ sql: "SELECT type FROM sqlite_master WHERE name = 'global_procedures'",
3111
+ args: []
3112
+ });
3113
+ const legacyProcedureType = legacyProcedureObject.rows[0]?.type == null ? null : String(legacyProcedureObject.rows[0].type);
3114
+ if (legacyProcedureType === "table") {
3115
+ await client.execute(`
3116
+ INSERT OR IGNORE INTO company_procedures
3117
+ (id, title, content, priority, domain, active, created_at, updated_at)
3118
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
3119
+ FROM global_procedures
3120
+ `);
3121
+ await client.executeMultiple(`
3122
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_insert
3123
+ AFTER INSERT ON global_procedures
3124
+ BEGIN
3125
+ INSERT OR IGNORE INTO company_procedures
3126
+ (id, title, content, priority, domain, active, created_at, updated_at)
3127
+ VALUES
3128
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
3129
+ END;
3130
+
3131
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_update
3132
+ AFTER UPDATE ON global_procedures
3133
+ BEGIN
3134
+ UPDATE company_procedures
3135
+ SET title = NEW.title,
3136
+ content = NEW.content,
3137
+ priority = NEW.priority,
3138
+ domain = NEW.domain,
3139
+ active = NEW.active,
3140
+ created_at = NEW.created_at,
3141
+ updated_at = NEW.updated_at
3142
+ WHERE id = OLD.id;
3143
+ END;
3144
+ `);
3145
+ } else {
3146
+ await client.execute(`
3147
+ CREATE VIEW IF NOT EXISTS global_procedures AS
3148
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
3149
+ FROM company_procedures
3150
+ `);
3151
+ await client.executeMultiple(`
3152
+ CREATE TRIGGER IF NOT EXISTS global_procedures_insert
3153
+ INSTEAD OF INSERT ON global_procedures
3154
+ BEGIN
3155
+ INSERT INTO company_procedures
3156
+ (id, title, content, priority, domain, active, created_at, updated_at)
3157
+ VALUES
3158
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
3159
+ END;
3160
+
3161
+ CREATE TRIGGER IF NOT EXISTS global_procedures_update
3162
+ INSTEAD OF UPDATE ON global_procedures
3163
+ BEGIN
3164
+ UPDATE company_procedures
3165
+ SET title = NEW.title,
3166
+ content = NEW.content,
3167
+ priority = NEW.priority,
3168
+ domain = NEW.domain,
3169
+ active = NEW.active,
3170
+ created_at = NEW.created_at,
3171
+ updated_at = NEW.updated_at
3172
+ WHERE id = OLD.id;
3173
+ END;
3174
+ `);
3175
+ }
3109
3176
  await client.executeMultiple(`
3110
3177
  CREATE TABLE IF NOT EXISTS conversations (
3111
3178
  id TEXT PRIMARY KEY,
@@ -7640,7 +7707,7 @@ var init_platform_procedures = __esm({
7640
7707
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
7641
7708
  domain: "tool-use",
7642
7709
  priority: "p1",
7643
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
7710
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
7644
7711
  }
7645
7712
  ];
7646
7713
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -7661,7 +7728,7 @@ import { randomUUID as randomUUID3 } from "crypto";
7661
7728
  async function loadGlobalProcedures() {
7662
7729
  const client = getClient();
7663
7730
  const result = await client.execute({
7664
- sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
7731
+ sql: "SELECT * FROM company_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
7665
7732
  args: []
7666
7733
  });
7667
7734
  const allRows = result.rows;
@@ -7690,7 +7757,7 @@ async function storeGlobalProcedure(input) {
7690
7757
  const now = (/* @__PURE__ */ new Date()).toISOString();
7691
7758
  const client = getClient();
7692
7759
  await client.execute({
7693
- sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
7760
+ sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
7694
7761
  VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
7695
7762
  args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
7696
7763
  });
@@ -7701,7 +7768,7 @@ async function deactivateGlobalProcedure(id) {
7701
7768
  const now = (/* @__PURE__ */ new Date()).toISOString();
7702
7769
  const client = getClient();
7703
7770
  const result = await client.execute({
7704
- sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
7771
+ sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
7705
7772
  args: [now, id]
7706
7773
  });
7707
7774
  await loadGlobalProcedures();
package/dist/bin/setup.js CHANGED
@@ -3742,7 +3742,7 @@ async function ensureSchema() {
3742
3742
  ON session_kills(agent_id);
3743
3743
  `);
3744
3744
  await client.execute(`
3745
- CREATE TABLE IF NOT EXISTS global_procedures (
3745
+ CREATE TABLE IF NOT EXISTS company_procedures (
3746
3746
  id TEXT PRIMARY KEY,
3747
3747
  title TEXT NOT NULL,
3748
3748
  content TEXT NOT NULL,
@@ -3753,6 +3753,73 @@ async function ensureSchema() {
3753
3753
  updated_at TEXT NOT NULL
3754
3754
  )
3755
3755
  `);
3756
+ const legacyProcedureObject = await client.execute({
3757
+ sql: "SELECT type FROM sqlite_master WHERE name = 'global_procedures'",
3758
+ args: []
3759
+ });
3760
+ const legacyProcedureType = legacyProcedureObject.rows[0]?.type == null ? null : String(legacyProcedureObject.rows[0].type);
3761
+ if (legacyProcedureType === "table") {
3762
+ await client.execute(`
3763
+ INSERT OR IGNORE INTO company_procedures
3764
+ (id, title, content, priority, domain, active, created_at, updated_at)
3765
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
3766
+ FROM global_procedures
3767
+ `);
3768
+ await client.executeMultiple(`
3769
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_insert
3770
+ AFTER INSERT ON global_procedures
3771
+ BEGIN
3772
+ INSERT OR IGNORE INTO company_procedures
3773
+ (id, title, content, priority, domain, active, created_at, updated_at)
3774
+ VALUES
3775
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
3776
+ END;
3777
+
3778
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_update
3779
+ AFTER UPDATE ON global_procedures
3780
+ BEGIN
3781
+ UPDATE company_procedures
3782
+ SET title = NEW.title,
3783
+ content = NEW.content,
3784
+ priority = NEW.priority,
3785
+ domain = NEW.domain,
3786
+ active = NEW.active,
3787
+ created_at = NEW.created_at,
3788
+ updated_at = NEW.updated_at
3789
+ WHERE id = OLD.id;
3790
+ END;
3791
+ `);
3792
+ } else {
3793
+ await client.execute(`
3794
+ CREATE VIEW IF NOT EXISTS global_procedures AS
3795
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
3796
+ FROM company_procedures
3797
+ `);
3798
+ await client.executeMultiple(`
3799
+ CREATE TRIGGER IF NOT EXISTS global_procedures_insert
3800
+ INSTEAD OF INSERT ON global_procedures
3801
+ BEGIN
3802
+ INSERT INTO company_procedures
3803
+ (id, title, content, priority, domain, active, created_at, updated_at)
3804
+ VALUES
3805
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
3806
+ END;
3807
+
3808
+ CREATE TRIGGER IF NOT EXISTS global_procedures_update
3809
+ INSTEAD OF UPDATE ON global_procedures
3810
+ BEGIN
3811
+ UPDATE company_procedures
3812
+ SET title = NEW.title,
3813
+ content = NEW.content,
3814
+ priority = NEW.priority,
3815
+ domain = NEW.domain,
3816
+ active = NEW.active,
3817
+ created_at = NEW.created_at,
3818
+ updated_at = NEW.updated_at
3819
+ WHERE id = OLD.id;
3820
+ END;
3821
+ `);
3822
+ }
3756
3823
  await client.executeMultiple(`
3757
3824
  CREATE TABLE IF NOT EXISTS conversations (
3758
3825
  id TEXT PRIMARY KEY,
@@ -4815,12 +4882,12 @@ async function cloudSync(config) {
4815
4882
  try {
4816
4883
  await cloudPushGlobalProcedures(config);
4817
4884
  } catch (err) {
4818
- logError(`[cloud-sync] Global procedures push: ${err instanceof Error ? err.message : String(err)}`);
4885
+ logError(`[cloud-sync] Company procedures push: ${err instanceof Error ? err.message : String(err)}`);
4819
4886
  }
4820
4887
  try {
4821
4888
  await cloudPullGlobalProcedures(config);
4822
4889
  } catch (err) {
4823
- logError(`[cloud-sync] Global procedures pull: ${err instanceof Error ? err.message : String(err)}`);
4890
+ logError(`[cloud-sync] Company procedures pull: ${err instanceof Error ? err.message : String(err)}`);
4824
4891
  }
4825
4892
  const countRows = async (sql) => {
4826
4893
  try {
@@ -5229,12 +5296,12 @@ async function cloudPullBlob(route, config) {
5229
5296
  }
5230
5297
  async function cloudPushGlobalProcedures(config) {
5231
5298
  const client = getClient();
5232
- const result = await client.execute("SELECT * FROM global_procedures LIMIT 1000");
5299
+ const result = await client.execute("SELECT * FROM company_procedures LIMIT 1000");
5233
5300
  const rows = result.rows;
5234
5301
  const { ok } = await cloudPushBlob(
5235
5302
  "/sync/push-global-procedures",
5236
5303
  rows,
5237
- "last_global_procedures_push_version",
5304
+ "last_company_procedures_push_version",
5238
5305
  config
5239
5306
  );
5240
5307
  return ok;
@@ -5247,7 +5314,7 @@ async function cloudPullGlobalProcedures(config) {
5247
5314
  if (!remoteProcs || remoteProcs.length === 0) return { pulled: 0 };
5248
5315
  const client = getClient();
5249
5316
  const stmts = remoteProcs.map((p) => ({
5250
- sql: `INSERT INTO global_procedures
5317
+ sql: `INSERT INTO company_procedures
5251
5318
  (id, title, content, priority, domain, active, created_at, updated_at)
5252
5319
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
5253
5320
  ON CONFLICT(id) DO UPDATE SET
@@ -5257,7 +5324,7 @@ async function cloudPullGlobalProcedures(config) {
5257
5324
  domain = excluded.domain,
5258
5325
  active = excluded.active,
5259
5326
  updated_at = excluded.updated_at
5260
- WHERE excluded.updated_at > global_procedures.updated_at`,
5327
+ WHERE excluded.updated_at > company_procedures.updated_at`,
5261
5328
  args: [
5262
5329
  sqlSafe(p.id),
5263
5330
  sqlSafe(p.title),
@@ -5820,7 +5887,7 @@ var init_platform_procedures = __esm({
5820
5887
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
5821
5888
  domain: "tool-use",
5822
5889
  priority: "p1",
5823
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
5890
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
5824
5891
  }
5825
5892
  ];
5826
5893
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -2289,7 +2289,7 @@ async function ensureSchema() {
2289
2289
  ON session_kills(agent_id);
2290
2290
  `);
2291
2291
  await client.execute(`
2292
- CREATE TABLE IF NOT EXISTS global_procedures (
2292
+ CREATE TABLE IF NOT EXISTS company_procedures (
2293
2293
  id TEXT PRIMARY KEY,
2294
2294
  title TEXT NOT NULL,
2295
2295
  content TEXT NOT NULL,
@@ -2300,6 +2300,73 @@ async function ensureSchema() {
2300
2300
  updated_at TEXT NOT NULL
2301
2301
  )
2302
2302
  `);
2303
+ const legacyProcedureObject = await client.execute({
2304
+ sql: "SELECT type FROM sqlite_master WHERE name = 'global_procedures'",
2305
+ args: []
2306
+ });
2307
+ const legacyProcedureType = legacyProcedureObject.rows[0]?.type == null ? null : String(legacyProcedureObject.rows[0].type);
2308
+ if (legacyProcedureType === "table") {
2309
+ await client.execute(`
2310
+ INSERT OR IGNORE INTO company_procedures
2311
+ (id, title, content, priority, domain, active, created_at, updated_at)
2312
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
2313
+ FROM global_procedures
2314
+ `);
2315
+ await client.executeMultiple(`
2316
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_insert
2317
+ AFTER INSERT ON global_procedures
2318
+ BEGIN
2319
+ INSERT OR IGNORE INTO company_procedures
2320
+ (id, title, content, priority, domain, active, created_at, updated_at)
2321
+ VALUES
2322
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
2323
+ END;
2324
+
2325
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_update
2326
+ AFTER UPDATE ON global_procedures
2327
+ BEGIN
2328
+ UPDATE company_procedures
2329
+ SET title = NEW.title,
2330
+ content = NEW.content,
2331
+ priority = NEW.priority,
2332
+ domain = NEW.domain,
2333
+ active = NEW.active,
2334
+ created_at = NEW.created_at,
2335
+ updated_at = NEW.updated_at
2336
+ WHERE id = OLD.id;
2337
+ END;
2338
+ `);
2339
+ } else {
2340
+ await client.execute(`
2341
+ CREATE VIEW IF NOT EXISTS global_procedures AS
2342
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
2343
+ FROM company_procedures
2344
+ `);
2345
+ await client.executeMultiple(`
2346
+ CREATE TRIGGER IF NOT EXISTS global_procedures_insert
2347
+ INSTEAD OF INSERT ON global_procedures
2348
+ BEGIN
2349
+ INSERT INTO company_procedures
2350
+ (id, title, content, priority, domain, active, created_at, updated_at)
2351
+ VALUES
2352
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
2353
+ END;
2354
+
2355
+ CREATE TRIGGER IF NOT EXISTS global_procedures_update
2356
+ INSTEAD OF UPDATE ON global_procedures
2357
+ BEGIN
2358
+ UPDATE company_procedures
2359
+ SET title = NEW.title,
2360
+ content = NEW.content,
2361
+ priority = NEW.priority,
2362
+ domain = NEW.domain,
2363
+ active = NEW.active,
2364
+ created_at = NEW.created_at,
2365
+ updated_at = NEW.updated_at
2366
+ WHERE id = OLD.id;
2367
+ END;
2368
+ `);
2369
+ }
2303
2370
  await client.executeMultiple(`
2304
2371
  CREATE TABLE IF NOT EXISTS conversations (
2305
2372
  id TEXT PRIMARY KEY,
@@ -3176,7 +3243,7 @@ var init_platform_procedures = __esm({
3176
3243
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
3177
3244
  domain: "tool-use",
3178
3245
  priority: "p1",
3179
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
3246
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
3180
3247
  }
3181
3248
  ];
3182
3249
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -3197,7 +3264,7 @@ import { randomUUID as randomUUID2 } from "crypto";
3197
3264
  async function loadGlobalProcedures() {
3198
3265
  const client = getClient();
3199
3266
  const result = await client.execute({
3200
- sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
3267
+ sql: "SELECT * FROM company_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
3201
3268
  args: []
3202
3269
  });
3203
3270
  const allRows = result.rows;
@@ -3226,7 +3293,7 @@ async function storeGlobalProcedure(input) {
3226
3293
  const now = (/* @__PURE__ */ new Date()).toISOString();
3227
3294
  const client = getClient();
3228
3295
  await client.execute({
3229
- sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
3296
+ sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
3230
3297
  VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
3231
3298
  args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
3232
3299
  });
@@ -3237,7 +3304,7 @@ async function deactivateGlobalProcedure(id) {
3237
3304
  const now = (/* @__PURE__ */ new Date()).toISOString();
3238
3305
  const client = getClient();
3239
3306
  const result = await client.execute({
3240
- sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
3307
+ sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
3241
3308
  args: [now, id]
3242
3309
  });
3243
3310
  await loadGlobalProcedures();