@rubytech/create-maxy-code 0.1.75 → 0.1.80

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 (127) hide show
  1. package/dist/__tests__/plugin-install.test.js +2 -2
  2. package/dist/lib/plugin-install.js +1 -1
  3. package/package.json +1 -1
  4. package/payload/platform/config/brand.json +1 -1
  5. package/payload/platform/lib/graph-write/dist/index.js +1 -1
  6. package/payload/platform/lib/graph-write/src/index.ts +1 -1
  7. package/payload/platform/package.json +1 -1
  8. package/payload/platform/plugins/.claude-plugin/marketplace.json +101 -1
  9. package/payload/platform/plugins/admin/mcp/dist/index.js +1 -1
  10. package/payload/platform/plugins/admin/skills/commitment-followthrough/SKILL.md +1 -1
  11. package/payload/platform/plugins/admin/skills/session-management/SKILL.md +1 -1
  12. package/payload/platform/plugins/business-assistant/PLUGIN.md +1 -1
  13. package/payload/platform/plugins/business-assistant/references/task-management.md +13 -13
  14. package/payload/platform/plugins/docs/references/admin-session.md +7 -6
  15. package/payload/platform/plugins/docs/references/internals.md +2 -2
  16. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  17. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.d.ts +2 -0
  18. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.d.ts.map +1 -0
  19. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.js +57 -0
  20. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.js.map +1 -0
  21. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts.map +1 -1
  22. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +9 -1
  23. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js.map +1 -1
  24. package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -0
  25. package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +2 -2
  26. package/payload/platform/plugins/projects/PLUGIN.md +3 -3
  27. package/payload/platform/plugins/projects/references/sprint.md +2 -2
  28. package/payload/platform/plugins/scheduling/skills/briefing/SKILL.md +2 -2
  29. package/payload/platform/plugins/tasks/.claude-plugin/plugin.json +1 -1
  30. package/payload/platform/plugins/work/.claude-plugin/plugin.json +17 -0
  31. package/payload/platform/plugins/{tasks → work}/.mcp.json +2 -2
  32. package/payload/platform/plugins/work/PLUGIN.md +120 -0
  33. package/payload/platform/plugins/work/mcp/dist/index.d.ts +2 -0
  34. package/payload/platform/plugins/work/mcp/dist/index.d.ts.map +1 -0
  35. package/payload/platform/plugins/work/mcp/dist/index.js +543 -0
  36. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -0
  37. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.d.ts +7 -0
  38. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.d.ts.map +1 -0
  39. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.js +24 -0
  40. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.js.map +1 -0
  41. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.d.ts +5 -0
  42. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.d.ts.map +1 -0
  43. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.js +40 -0
  44. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.js.map +1 -0
  45. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.d.ts +17 -0
  46. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.d.ts.map +1 -0
  47. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.js +76 -0
  48. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.js.map +1 -0
  49. package/payload/platform/plugins/work/mcp/dist/tools/project-create.d.ts +29 -0
  50. package/payload/platform/plugins/work/mcp/dist/tools/project-create.d.ts.map +1 -0
  51. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js +235 -0
  52. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js.map +1 -0
  53. package/payload/platform/plugins/work/mcp/dist/tools/project-get.d.ts +40 -0
  54. package/payload/platform/plugins/work/mcp/dist/tools/project-get.d.ts.map +1 -0
  55. package/payload/platform/plugins/work/mcp/dist/tools/project-get.js +125 -0
  56. package/payload/platform/plugins/work/mcp/dist/tools/project-get.js.map +1 -0
  57. package/payload/platform/plugins/work/mcp/dist/tools/project-list.d.ts +26 -0
  58. package/payload/platform/plugins/work/mcp/dist/tools/project-list.d.ts.map +1 -0
  59. package/payload/platform/plugins/work/mcp/dist/tools/project-list.js +81 -0
  60. package/payload/platform/plugins/work/mcp/dist/tools/project-list.js.map +1 -0
  61. package/payload/platform/plugins/work/mcp/dist/tools/project-update.d.ts +19 -0
  62. package/payload/platform/plugins/work/mcp/dist/tools/project-update.d.ts.map +1 -0
  63. package/payload/platform/plugins/work/mcp/dist/tools/project-update.js +102 -0
  64. package/payload/platform/plugins/work/mcp/dist/tools/project-update.js.map +1 -0
  65. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts +20 -0
  66. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts.map +1 -0
  67. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js +37 -0
  68. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js.map +1 -0
  69. package/payload/platform/plugins/work/mcp/dist/tools/session-name.d.ts +12 -0
  70. package/payload/platform/plugins/work/mcp/dist/tools/session-name.d.ts.map +1 -0
  71. package/payload/platform/plugins/work/mcp/dist/tools/session-name.js +28 -0
  72. package/payload/platform/plugins/work/mcp/dist/tools/session-name.js.map +1 -0
  73. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.d.ts +16 -0
  74. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.d.ts.map +1 -0
  75. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.js +33 -0
  76. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.js.map +1 -0
  77. package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts +63 -0
  78. package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts.map +1 -0
  79. package/payload/platform/plugins/work/mcp/dist/tools/work-create.js +141 -0
  80. package/payload/platform/plugins/work/mcp/dist/tools/work-create.js.map +1 -0
  81. package/payload/platform/plugins/work/mcp/dist/tools/work-get.d.ts +19 -0
  82. package/payload/platform/plugins/work/mcp/dist/tools/work-get.d.ts.map +1 -0
  83. package/payload/platform/plugins/work/mcp/dist/tools/work-get.js +51 -0
  84. package/payload/platform/plugins/work/mcp/dist/tools/work-get.js.map +1 -0
  85. package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts +18 -0
  86. package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts.map +1 -0
  87. package/payload/platform/plugins/work/mcp/dist/tools/work-list.js +66 -0
  88. package/payload/platform/plugins/work/mcp/dist/tools/work-list.js.map +1 -0
  89. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.d.ts +21 -0
  90. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.d.ts.map +1 -0
  91. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.js +54 -0
  92. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.js.map +1 -0
  93. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.d.ts +12 -0
  94. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.d.ts.map +1 -0
  95. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.js +59 -0
  96. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.js.map +1 -0
  97. package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts +32 -0
  98. package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts.map +1 -0
  99. package/payload/platform/plugins/work/mcp/dist/tools/work-update.js +112 -0
  100. package/payload/platform/plugins/work/mcp/dist/tools/work-update.js.map +1 -0
  101. package/payload/platform/plugins/{tasks → work}/mcp/package.json +1 -1
  102. package/payload/platform/scripts/conversation-id-allowlist.txt +4 -4
  103. package/payload/platform/scripts/seed-neo4j.sh +1 -1
  104. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  105. package/payload/platform/services/claude-session-manager/dist/http-server.js +34 -5
  106. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  107. package/payload/platform/services/claude-session-manager/dist/index.js +32 -0
  108. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  109. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +33 -1
  110. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  111. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +202 -39
  112. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  113. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts.map +1 -1
  114. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js +10 -4
  115. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js.map +1 -1
  116. package/payload/platform/templates/agents/admin/IDENTITY.md +21 -37
  117. package/payload/platform/templates/specialists/agents/database-operator.md +2 -2
  118. package/payload/platform/templates/specialists/agents/librarian.md +1 -1
  119. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  120. package/payload/platform/templates/specialists/agents/project-manager.md +3 -3
  121. package/payload/premium-plugins/real-agent/plugins/leads/PLUGIN.md +1 -1
  122. package/payload/server/{chunk-ITQ55PCQ.js → chunk-TFEIFU7F.js} +1 -1
  123. package/payload/server/{chunk-HZ77KMTV.js → chunk-W33UUYYR.js} +1 -4
  124. package/payload/server/{cloudflare-task-tracker-PZBX7X3D.js → cloudflare-task-tracker-7P355PSD.js} +1 -1
  125. package/payload/server/maxy-edge.js +1 -1
  126. package/payload/server/server.js +50 -18
  127. package/payload/platform/plugins/tasks/PLUGIN.md +0 -120
@@ -0,0 +1,81 @@
1
+ import { int } from "neo4j-driver";
2
+ import { getSession } from "../lib/neo4j.js";
3
+ function computeHealthSignal(health) {
4
+ const { totalTasks, overdueTasks, blockedTasks, daysSinceLastProgress } = health;
5
+ // No due dates set — report completion count only
6
+ if (totalTasks === 0)
7
+ return "grey";
8
+ // Red: multiple overdue OR critical-path blocker OR no progress for 7+ days
9
+ if (overdueTasks > 1 || (daysSinceLastProgress !== null && daysSinceLastProgress >= 7)) {
10
+ return "red";
11
+ }
12
+ // Amber: at least one overdue OR at least one blocker
13
+ if (overdueTasks > 0 || blockedTasks > 0) {
14
+ return "amber";
15
+ }
16
+ return "green";
17
+ }
18
+ export async function projectList(params) {
19
+ const { accountId, status, limit = 20 } = params;
20
+ // Default: return pending + active projects
21
+ const statuses = status ? [status] : ["pending", "active"];
22
+ const session = getSession();
23
+ try {
24
+ const result = await session.run(`MATCH (p:Project {accountId: $accountId})
25
+ WHERE p.status IN $statuses
26
+ OPTIONAL MATCH (p)-[:HAS_TASK]->(child:Task)
27
+ WITH p,
28
+ count(child) AS totalTasks,
29
+ count(CASE WHEN child.status = 'completed' THEN 1 END) AS completedTasks,
30
+ count(CASE WHEN child.dueDate IS NOT NULL
31
+ AND date(child.dueDate) < date()
32
+ AND child.status <> 'completed' THEN 1 END) AS overdueTasks,
33
+ count(CASE WHEN EXISTS {
34
+ MATCH (blocker:Task)-[:BLOCKS]->(child)
35
+ WHERE blocker.status IN ['pending', 'active']
36
+ } THEN 1 END) AS blockedTasks,
37
+ max(CASE WHEN child.status = 'completed' THEN child.updatedAt END) AS lastCompletedAt
38
+ RETURN p, totalTasks, completedTasks, overdueTasks, blockedTasks, lastCompletedAt
39
+ ORDER BY p.updatedAt DESC
40
+ LIMIT $limit`, { accountId, statuses, limit: int(limit) });
41
+ const projects = result.records.map((rec) => {
42
+ const p = rec.get("p").properties;
43
+ const totalTasks = rec.get("totalTasks").toNumber?.() ?? Number(rec.get("totalTasks"));
44
+ const completedTasks = rec.get("completedTasks").toNumber?.() ?? Number(rec.get("completedTasks"));
45
+ const overdueTasks = rec.get("overdueTasks").toNumber?.() ?? Number(rec.get("overdueTasks"));
46
+ const blockedTasks = rec.get("blockedTasks").toNumber?.() ?? Number(rec.get("blockedTasks"));
47
+ const lastCompletedAt = rec.get("lastCompletedAt");
48
+ let daysSinceLastProgress = null;
49
+ if (lastCompletedAt) {
50
+ const ms = Date.now() - new Date(lastCompletedAt).getTime();
51
+ daysSinceLastProgress = Math.floor(ms / (1000 * 60 * 60 * 24));
52
+ }
53
+ const healthData = { totalTasks, completedTasks, overdueTasks, blockedTasks, daysSinceLastProgress };
54
+ const signal = computeHealthSignal(healthData);
55
+ const summary = {
56
+ projectId: p.taskId,
57
+ name: p.name,
58
+ tier: p.tier,
59
+ phase: p.phase,
60
+ status: p.status,
61
+ health: { signal, ...healthData },
62
+ updatedAt: p.updatedAt,
63
+ };
64
+ if (p.clientRef)
65
+ summary.clientRef = p.clientRef;
66
+ if (p.targetDate)
67
+ summary.targetDate = p.targetDate;
68
+ return summary;
69
+ });
70
+ console.error(`project-list: returned ${projects.length} projects`);
71
+ return projects;
72
+ }
73
+ catch (err) {
74
+ console.error(`project-list: failed — ${err instanceof Error ? err.message : String(err)}`);
75
+ throw err;
76
+ }
77
+ finally {
78
+ await session.close();
79
+ }
80
+ }
81
+ //# sourceMappingURL=project-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-list.js","sourceRoot":"","sources":["../../src/tools/project-list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface ProjectUpdateParams {
2
+ projectId: string;
3
+ accountId: string;
4
+ phase?: string;
5
+ tier?: string;
6
+ targetDate?: string;
7
+ clientRef?: string;
8
+ note?: string;
9
+ status?: string;
10
+ }
11
+ export interface ProjectUpdateResult {
12
+ phaseChanged?: {
13
+ from: string;
14
+ to: string;
15
+ };
16
+ fieldsUpdated: string[];
17
+ }
18
+ export declare function projectUpdate(params: ProjectUpdateParams): Promise<ProjectUpdateResult>;
19
+ //# sourceMappingURL=project-update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-update.d.ts","sourceRoot":"","sources":["../../src/tools/project-update.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAqH7F"}
@@ -0,0 +1,102 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ import { computeEmbedding } from "../lib/embeddings.js";
3
+ export async function projectUpdate(params) {
4
+ const { projectId, accountId, phase, tier, targetDate, clientRef, note, status } = params;
5
+ const session = getSession();
6
+ try {
7
+ // Fetch current project
8
+ const existing = await session.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId})
9
+ RETURN p.name AS name, p.description AS description, p.notes AS notes,
10
+ p.phase AS phase, p.tier AS tier, p.status AS status`, { projectId, accountId });
11
+ if (existing.records.length === 0) {
12
+ throw new Error(`ProjectNotFound: ${projectId}`);
13
+ }
14
+ const rec = existing.records[0];
15
+ const currentName = rec.get("name");
16
+ const currentDescription = rec.get("description");
17
+ const currentNotes = rec.get("notes") ?? "";
18
+ const currentPhase = rec.get("phase");
19
+ const currentTier = rec.get("tier");
20
+ const currentStatus = rec.get("status");
21
+ const setClauses = ["p.updatedAt = $updatedAt"];
22
+ const queryParams = {
23
+ projectId,
24
+ accountId,
25
+ updatedAt: new Date().toISOString(),
26
+ };
27
+ const fieldsUpdated = [];
28
+ let newNotes = currentNotes;
29
+ const timestamp = new Date().toISOString().slice(0, 16).replace("T", " ");
30
+ // Phase transition — auto-append lifecycle note
31
+ let phaseChanged;
32
+ if (phase && phase !== currentPhase) {
33
+ setClauses.push("p.phase = $phase");
34
+ queryParams.phase = phase;
35
+ fieldsUpdated.push("phase");
36
+ phaseChanged = { from: currentPhase, to: phase };
37
+ const phaseSummary = note ?? "Phase transition";
38
+ const phaseNote = `[${timestamp}] [PROJECT:PHASE] ${phase} — ${phaseSummary}`;
39
+ newNotes = newNotes ? `${newNotes}\n${phaseNote}` : phaseNote;
40
+ }
41
+ // Append explicit note (separate from phase note)
42
+ if (note && !phaseChanged) {
43
+ const noteEntry = `[${timestamp}] ${note}`;
44
+ newNotes = newNotes ? `${newNotes}\n${noteEntry}` : noteEntry;
45
+ }
46
+ if (tier) {
47
+ setClauses.push("p.tier = $tier");
48
+ queryParams.tier = tier;
49
+ fieldsUpdated.push("tier");
50
+ }
51
+ if (targetDate) {
52
+ setClauses.push("p.targetDate = $targetDate");
53
+ queryParams.targetDate = targetDate;
54
+ fieldsUpdated.push("targetDate");
55
+ }
56
+ if (clientRef) {
57
+ setClauses.push("p.clientRef = $clientRef");
58
+ queryParams.clientRef = clientRef;
59
+ fieldsUpdated.push("clientRef");
60
+ }
61
+ if (status) {
62
+ setClauses.push("p.status = $status");
63
+ queryParams.status = status;
64
+ fieldsUpdated.push("status");
65
+ }
66
+ // Always update notes (may have changed via phase note or explicit note)
67
+ setClauses.push("p.notes = $notes");
68
+ queryParams.notes = newNotes;
69
+ // Re-embed with updated values
70
+ const newTier = tier ?? currentTier;
71
+ const newStatus = status ?? currentStatus;
72
+ const embeddingText = `Project: ${currentName} — ${currentDescription} tier: ${newTier} status: ${newStatus}${newNotes ? " " + newNotes : ""}`;
73
+ const embedding = await computeEmbedding(embeddingText);
74
+ if (embedding.length > 0) {
75
+ setClauses.push("p.embedding = $embedding");
76
+ queryParams.embedding = embedding;
77
+ }
78
+ await session.run(`MATCH (p:Project {taskId: $projectId, accountId: $accountId})
79
+ SET ${setClauses.join(", ")}`, queryParams);
80
+ // Log
81
+ if (phaseChanged) {
82
+ console.error(`project-update: ${projectId} phase=${phaseChanged.from}→${phaseChanged.to}`);
83
+ }
84
+ else {
85
+ console.error(`project-update: ${projectId} updated ${fieldsUpdated.length > 0 ? fieldsUpdated.join(", ") : "notes"}`);
86
+ }
87
+ return { phaseChanged, fieldsUpdated };
88
+ }
89
+ catch (err) {
90
+ if (err instanceof Error && err.message.startsWith("ProjectNotFound:")) {
91
+ console.error(`project-update: failed — ${err.message}`);
92
+ }
93
+ else {
94
+ console.error(`project-update: failed — ${err instanceof Error ? err.message : String(err)}`);
95
+ }
96
+ throw err;
97
+ }
98
+ finally {
99
+ await session.close();
100
+ }
101
+ }
102
+ //# sourceMappingURL=project-update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-update.js","sourceRoot":"","sources":["../../src/tools/project-update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export interface SessionListParams {
2
+ accountId: string;
3
+ limit?: number;
4
+ }
5
+ export interface SessionSummary {
6
+ sessionKey: string;
7
+ conversationId: string;
8
+ name?: string;
9
+ agentType: string;
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ tasks: Array<{
13
+ taskId: string;
14
+ name: string;
15
+ status: string;
16
+ priority: string;
17
+ }>;
18
+ }
19
+ export declare function sessionList(params: SessionListParams): Promise<SessionSummary[]>;
20
+ //# sourceMappingURL=session-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-list.d.ts","sourceRoot":"","sources":["../../src/tools/session-list.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClF;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAoCtF"}
@@ -0,0 +1,37 @@
1
+ import { int } from "neo4j-driver";
2
+ import { getSession } from "../lib/neo4j.js";
3
+ export async function sessionList(params) {
4
+ const { accountId, limit = 20 } = params;
5
+ const neo4jSession = getSession();
6
+ try {
7
+ const result = await neo4jSession.run(`MATCH (c:Conversation {accountId: $accountId})
8
+ OPTIONAL MATCH (t:Task)-[:PART_OF]->(c)
9
+ RETURN c, collect(
10
+ CASE WHEN t IS NOT NULL
11
+ THEN { taskId: t.taskId, name: t.name, status: t.status, priority: t.priority }
12
+ ELSE null
13
+ END
14
+ ) AS tasks
15
+ ORDER BY c.updatedAt DESC
16
+ LIMIT $limit`, { accountId, limit: int(limit) });
17
+ return result.records.map(rec => {
18
+ const c = rec.get("c").properties;
19
+ const rawTasks = rec.get("tasks");
20
+ const summary = {
21
+ sessionKey: c.sessionKey,
22
+ conversationId: c.conversationId,
23
+ agentType: c.agentType,
24
+ createdAt: c.createdAt,
25
+ updatedAt: c.updatedAt,
26
+ tasks: rawTasks.filter(t => t !== null),
27
+ };
28
+ if (c.name)
29
+ summary.name = c.name;
30
+ return summary;
31
+ });
32
+ }
33
+ finally {
34
+ await neo4jSession.close();
35
+ }
36
+ }
37
+ //# sourceMappingURL=session-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-list.js","sourceRoot":"","sources":["../../src/tools/session-list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAiB7C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAyB;IACzD,MAAM,EAAE,SAAS,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC;IAEzC,MAAM,YAAY,GAAG,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,CACnC;;;;;;;;;oBASc,EACd,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,CACjC,CAAC;QAEF,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YAC9B,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YAClC,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAqF,CAAC;YACtH,MAAM,OAAO,GAAmB;gBAC9B,UAAU,EAAE,CAAC,CAAC,UAAoB;gBAClC,cAAc,EAAE,CAAC,CAAC,cAAwB;gBAC1C,SAAS,EAAE,CAAC,CAAC,SAAmB;gBAChC,SAAS,EAAE,CAAC,CAAC,SAAmB;gBAChC,SAAS,EAAE,CAAC,CAAC,SAAmB;gBAChC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAA4B;aACnE,CAAC;YACF,IAAI,CAAC,CAAC,IAAI;gBAAE,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,IAAc,CAAC;YAC5C,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,MAAM,YAAY,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface SessionNameParams {
2
+ sessionKey: string;
3
+ name: string;
4
+ }
5
+ export interface SessionNameResult {
6
+ /** Number of Conversation nodes whose name was updated. Zero on a webchat
7
+ * pre-flush turn — the Conversation node has not been created yet
8
+ * (deferred persistence). */
9
+ affected: number;
10
+ }
11
+ export declare function sessionName(params: SessionNameParams): Promise<SessionNameResult>;
12
+ //# sourceMappingURL=session-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-name.d.ts","sourceRoot":"","sources":["../../src/tools/session-name.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC;;kCAE8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA4BvF"}
@@ -0,0 +1,28 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ export async function sessionName(params) {
3
+ const { sessionKey, name } = params;
4
+ // Do NOT MERGE on sessionKey — MERGE on a webchat first turn creates a
5
+ // property-stub Conversation (no AdminConversation sublabel, no
6
+ // accountId / agentType / userId) and the sibling
7
+ // createNewAdminConversation's CREATE then collides at flush time on
8
+ // the unique-constraint on Conversation.sessionKey. The MATCH path
9
+ // mirrors task-create.ts: pre-resolve the Conversation, no-op when
10
+ // missing. The agent's intent ("title the session") is the only
11
+ // automatic source of `c.name`; otherwise the UI sidebar falls back
12
+ // to Claude Code's `aiTitle` from the JSONL.
13
+ const neo4jSession = getSession();
14
+ try {
15
+ const result = await neo4jSession.run(`MATCH (c:Conversation {sessionKey: $sessionKey})
16
+ SET c.name = $name, c.updatedAt = datetime()
17
+ RETURN count(c) AS affected`, { sessionKey, name });
18
+ const affectedRaw = result.records[0]?.get("affected");
19
+ const affected = typeof affectedRaw?.toNumber === "function"
20
+ ? affectedRaw.toNumber()
21
+ : Number(affectedRaw ?? 0);
22
+ return { affected };
23
+ }
24
+ finally {
25
+ await neo4jSession.close();
26
+ }
27
+ }
28
+ //# sourceMappingURL=session-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-name.js","sourceRoot":"","sources":["../../src/tools/session-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAc7C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAyB;IACzD,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IAEpC,uEAAuE;IACvE,gEAAgE;IAChE,kDAAkD;IAClD,qEAAqE;IACrE,mEAAmE;IACnE,mEAAmE;IACnE,gEAAgE;IAChE,oEAAoE;IACpE,6CAA6C;IAC7C,MAAM,YAAY,GAAG,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,CACnC;;mCAE6B,EAC7B,EAAE,UAAU,EAAE,IAAI,EAAE,CACrB,CAAC;QACF,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,OAAO,WAAW,EAAE,QAAQ,KAAK,UAAU;YAC1D,CAAC,CAAC,WAAW,CAAC,QAAQ,EAAE;YACxB,CAAC,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;QAC7B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,MAAM,YAAY,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface TaskCompleteParams {
2
+ taskId: string;
3
+ accountId: string;
4
+ /** Optional completion note appended to task history */
5
+ note?: string;
6
+ }
7
+ export interface UnblockedTask {
8
+ taskId: string;
9
+ name: string;
10
+ priority: string;
11
+ }
12
+ export interface TaskCompleteResult {
13
+ unblockedTasks: UnblockedTask[];
14
+ }
15
+ export declare function workComplete(params: TaskCompleteParams): Promise<TaskCompleteResult>;
16
+ //# sourceMappingURL=work-complete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-complete.d.ts","sourceRoot":"","sources":["../../src/tools/work-complete.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmC1F"}
@@ -0,0 +1,33 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ import { workUpdate } from "./work-update.js";
3
+ export async function workComplete(params) {
4
+ const { taskId, accountId, note } = params;
5
+ await workUpdate({
6
+ taskId,
7
+ accountId,
8
+ status: "completed",
9
+ note: note ?? "Task completed.",
10
+ });
11
+ // Find tasks that were BLOCKS-ed by this one and are now potentially ready
12
+ const session = getSession();
13
+ try {
14
+ const result = await session.run(`MATCH (completed:Task {taskId: $taskId, accountId: $accountId})-[:BLOCKS]->(candidate:Task {accountId: $accountId})
15
+ WHERE candidate.status = 'pending'
16
+ AND NOT EXISTS {
17
+ MATCH (otherBlocker:Task {accountId: $accountId})-[:BLOCKS]->(candidate)
18
+ WHERE otherBlocker.status IN ['pending', 'active']
19
+ AND otherBlocker.taskId <> $taskId
20
+ }
21
+ RETURN candidate.taskId AS taskId, candidate.name AS name, candidate.priority AS priority`, { taskId, accountId });
22
+ const unblockedTasks = result.records.map((rec) => ({
23
+ taskId: rec.get("taskId"),
24
+ name: rec.get("name"),
25
+ priority: rec.get("priority"),
26
+ }));
27
+ return { unblockedTasks };
28
+ }
29
+ finally {
30
+ await session.close();
31
+ }
32
+ }
33
+ //# sourceMappingURL=work-complete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-complete.js","sourceRoot":"","sources":["../../src/tools/work-complete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAmB9C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAA0B;IAC3D,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IAE3C,MAAM,UAAU,CAAC;QACf,MAAM;QACN,SAAS;QACT,MAAM,EAAE,WAAW;QACnB,IAAI,EAAE,IAAI,IAAI,iBAAiB;KAChC,CAAC,CAAC;IAEH,2EAA2E;IAC3E,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B;;;;;;;iGAO2F,EAC3F,EAAE,MAAM,EAAE,SAAS,EAAE,CACtB,CAAC;QAEF,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAClD,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAW;YACnC,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAW;YAC/B,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAW;SACxC,CAAC,CAAC,CAAC;QAEJ,OAAO,EAAE,cAAc,EAAE,CAAC;IAC5B,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { type CreatedBy } from "../../../../../lib/graph-write/dist/index.js";
2
+ import { type FormSchema, type JsonValue } from "../../../../../lib/task-secrets/dist/index.js";
3
+ export interface TaskCreateParams {
4
+ accountId: string;
5
+ name: string;
6
+ description: string;
7
+ /**
8
+ * Status enum. `running` is the process-provenance value: the
9
+ * Task represents an action currently mid-flight (distinct from `active`,
10
+ * which means the operator has accepted a commitment). When `running` is
11
+ * passed, `startedAt` is auto-set to now.
12
+ */
13
+ status?: "pending" | "active" | "running" | "completed" | "failed" | "cancelled";
14
+ priority?: "low" | "normal" | "high" | "urgent";
15
+ dueDate?: string;
16
+ sessionKey?: string;
17
+ /** Person elementId — creates a RAISED_BY relationship */
18
+ raisedBy?: string;
19
+ /** Entity elementIds — creates AFFECTS relationships */
20
+ affects?: string[];
21
+ /**
22
+ * process-provenance kind discriminator (e.g.
23
+ * "onboarding-establish-owner", "cloudflare-tunnel-login"). Optional;
24
+ * commitment-tracking callers omit it. When present, the Task is
25
+ * considered an action record with a lifecycle (started/step/done).
26
+ */
27
+ kind?: string;
28
+ /**
29
+ * Property names supplied at action start. Retained as the canonical
30
+ * "call shape" record alongside the value-bearing `inputs.*` props
31
+ * (outcome contract).
32
+ */
33
+ inputsProvided?: string[];
34
+ /**
35
+ * outcome contract — the action's form payload. Values are
36
+ * persisted as `inputs.<field>` props on the Task after `redactSecrets`
37
+ * strips fields the schema marks as secret. The agent's judgement decides
38
+ * what's meaningful to record (mode, emailProvided, resolved elementIds);
39
+ * the contract enforces no-secret leakage centrally via the schema.
40
+ */
41
+ inputs?: Record<string, JsonValue>;
42
+ /**
43
+ * Schema for `inputs` declaring which keys carry secret material that must
44
+ * never land on the Task. Declared at the form definition,
45
+ * passed through verbatim by the writer. Omit when the action records no
46
+ * secrets (e.g. onboarding step 9 mode select).
47
+ */
48
+ inputSchema?: FormSchema;
49
+ /**
50
+ * Conversation sessionKey for the RAISED_DURING edge. When the
51
+ * Conversation resolves, write `(:Task)-[:RAISED_DURING]->(:Conversation)`
52
+ * IN ADDITION TO the existing PART_OF edge (different semantics:
53
+ * RAISED_DURING is action-provenance; PART_OF is commitment-tracking).
54
+ * Falls back to params.sessionKey when omitted.
55
+ */
56
+ raisedDuringConversationKey?: string;
57
+ createdBy: CreatedBy;
58
+ }
59
+ export interface TaskCreateResult {
60
+ taskId: string;
61
+ }
62
+ export declare function workCreate(params: TaskCreateParams): Promise<TaskCreateResult>;
63
+ //# sourceMappingURL=work-create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-create.d.ts","sourceRoot":"","sources":["../../src/tools/work-create.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,+CAA+C,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IACjF,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB;;;;;;OAMG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4KpF"}
@@ -0,0 +1,141 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { getSession } from "../lib/neo4j.js";
3
+ import { computeEmbedding } from "../lib/embeddings.js";
4
+ import { writeNodeWithEdges, } from "../../../../../lib/graph-write/dist/index.js";
5
+ import { redactSecrets, } from "../../../../../lib/task-secrets/dist/index.js";
6
+ export async function workCreate(params) {
7
+ const { accountId, name, description, status = "pending", priority = "normal", dueDate, sessionKey, raisedBy, affects, kind, inputsProvided, inputs, inputSchema, raisedDuringConversationKey, createdBy, } = params;
8
+ const taskId = randomUUID();
9
+ const now = new Date().toISOString();
10
+ const props = {
11
+ taskId,
12
+ accountId,
13
+ name,
14
+ description,
15
+ status,
16
+ priority,
17
+ createdAt: now,
18
+ updatedAt: now,
19
+ };
20
+ if (dueDate)
21
+ props.dueDate = dueDate;
22
+ if (kind)
23
+ props.kind = kind;
24
+ if (inputsProvided && inputsProvided.length > 0)
25
+ props.inputsProvided = inputsProvided;
26
+ if (status === "running")
27
+ props.startedAt = now;
28
+ // outcome contract — persist the form payload as `inputs.<field>`
29
+ // props after stripping any secret-tagged keys via redactSecrets. Schema
30
+ // is the form definition's authority; writers never re-classify.
31
+ if (inputs) {
32
+ if (!inputSchema) {
33
+ process.stderr.write(`[task] redact-no-schema kind=${kind ?? "unknown"} taskId=${taskId} fieldsCount=${Object.keys(inputs).length}\n`);
34
+ }
35
+ const { redacted, droppedFields, droppedFieldNames } = redactSecrets(inputs, inputSchema);
36
+ for (const [key, value] of Object.entries(redacted)) {
37
+ props[`inputs.${key}`] = value;
38
+ }
39
+ if (droppedFields > 0) {
40
+ process.stderr.write(`[task] redacted kind=${kind ?? "unknown"} taskId=${taskId} droppedFields=${droppedFields} fields=${droppedFieldNames.join(",")}\n`);
41
+ }
42
+ }
43
+ const embeddingText = `Task: ${name} — ${description} status: ${status} priority: ${priority}`;
44
+ const embedding = await computeEmbedding(embeddingText);
45
+ if (embedding.length > 0)
46
+ props.embedding = embedding;
47
+ // Build the relationships list that satisfies the write doctrine. The
48
+ // task's linking sources are, in priority order: the current
49
+ // Conversation (via sessionKey), the raising Person, and any entities
50
+ // the task will affect. At least one must resolve — a Task that affects
51
+ // nothing and was raised by no one and belongs to no session is noise,
52
+ // not knowledge (see .docs/neo4j.md Write doctrine).
53
+ const relationships = [];
54
+ const neo4jSession = getSession();
55
+ try {
56
+ let conversationElementId = null;
57
+ if (sessionKey) {
58
+ // Do NOT MERGE (c:Conversation {sessionKey}) — the original
59
+ // implementation created a Conversation with no edges when the
60
+ // session didn't already exist, spawning an orphan to avoid
61
+ // spawning an orphan. Pre-resolve via MATCH; skip the PART_OF
62
+ // edge if the Conversation is missing (caller may still have
63
+ // raisedBy/affects).
64
+ const r = await neo4jSession.run(`MATCH (c:Conversation {sessionKey: $sessionKey}) RETURN elementId(c) AS id LIMIT 1`, { sessionKey });
65
+ if (r.records.length > 0) {
66
+ conversationElementId = r.records[0].get("id");
67
+ relationships.push({
68
+ type: "PART_OF",
69
+ direction: "outgoing",
70
+ targetNodeId: conversationElementId,
71
+ });
72
+ }
73
+ }
74
+ // process-provenance edge — written ALONGSIDE PART_OF, not in
75
+ // place of it. PART_OF carries commitment-tracking semantics for the
76
+ // existing :Task callers (workflow runner, agent commitment); the new
77
+ // RAISED_DURING edge carries action-provenance semantics (what
78
+ // conversation initiated this action). Resolves the same Conversation
79
+ // when raisedDuringConversationKey === sessionKey, or a different one
80
+ // when the Task was raised in a different surface (e.g. cloudflare
81
+ // setup endpoint) but still belongs to a separate session.
82
+ const raisedDuringKey = raisedDuringConversationKey ?? sessionKey;
83
+ if (raisedDuringKey) {
84
+ const targetId = raisedDuringKey === sessionKey && conversationElementId
85
+ ? conversationElementId
86
+ : await (async () => {
87
+ const r = await neo4jSession.run(`MATCH (c:Conversation {sessionKey: $sessionKey}) RETURN elementId(c) AS id LIMIT 1`, { sessionKey: raisedDuringKey });
88
+ return r.records.length > 0 ? r.records[0].get("id") : null;
89
+ })();
90
+ if (targetId) {
91
+ relationships.push({
92
+ type: "RAISED_DURING",
93
+ direction: "outgoing",
94
+ targetNodeId: targetId,
95
+ });
96
+ }
97
+ }
98
+ if (raisedBy) {
99
+ relationships.push({
100
+ type: "RAISED_BY",
101
+ direction: "outgoing",
102
+ targetNodeId: raisedBy,
103
+ });
104
+ }
105
+ if (affects) {
106
+ for (const entityId of affects) {
107
+ relationships.push({
108
+ type: "AFFECTS",
109
+ direction: "outgoing",
110
+ targetNodeId: entityId,
111
+ });
112
+ }
113
+ }
114
+ if (relationships.length === 0) {
115
+ throw new Error("Write doctrine violated: task-create requires at least one link — a valid session with an existing Conversation, a raisedBy Person, or at least one affects entity. Pass raisedBy or affects, or call within an admin session.");
116
+ }
117
+ await writeNodeWithEdges({
118
+ session: neo4jSession,
119
+ labels: ["Task"],
120
+ props,
121
+ relationships,
122
+ createdBy,
123
+ });
124
+ // Process-provenance lifecycle signal. Only emitted when the
125
+ // caller declared a `kind` — commitment-tracking callers stay silent on
126
+ // this channel. `raisedDuring` reports whether the RAISED_DURING edge
127
+ // resolved so operators can grep "kind=X raisedDuring=none" to find
128
+ // actions that fired outside any conversation context.
129
+ if (kind) {
130
+ const raisedDuringNote = relationships.some((r) => r.type === "RAISED_DURING")
131
+ ? (raisedDuringConversationKey ?? sessionKey ?? "unknown")
132
+ : "none";
133
+ process.stderr.write(`[task] action-start kind=${kind} taskId=${taskId} raisedDuring=${raisedDuringNote}\n`);
134
+ }
135
+ return { taskId };
136
+ }
137
+ finally {
138
+ await neo4jSession.close();
139
+ }
140
+ }
141
+ //# sourceMappingURL=work-create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-create.js","sourceRoot":"","sources":["../../src/tools/work-create.ts"],"names":[],"mappings":"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"}