@graph-tl/graph 0.1.16 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-O4ZUX2AB.js → chunk-M5QOJN7D.js} +6 -1
- package/dist/chunk-M5QOJN7D.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/{init-WSSOJX4W.js → init-74TF4PX3.js} +26 -3
- package/dist/init-74TF4PX3.js.map +1 -0
- package/dist/{server-77JQI7CU.js → server-XSKUM3G5.js} +100 -3
- package/dist/server-XSKUM3G5.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-O4ZUX2AB.js.map +0 -1
- package/dist/init-WSSOJX4W.js.map +0 -1
- package/dist/server-77JQI7CU.js.map +0 -1
|
@@ -32,6 +32,11 @@ Read the \`hint\` field first \u2014 it tells you exactly what to do next. Then
|
|
|
32
32
|
|
|
33
33
|
This catches work done ad-hoc or through plan files that bypassed the graph. It's cheap to run and prevents silent context loss.
|
|
34
34
|
|
|
35
|
+
**Continuity confidence:** \`graph_onboard\` returns a \`continuity_confidence\` signal (\`high\`/\`medium\`/\`low\`) with a score and reasons. This tells you how reliable the inherited context is.
|
|
36
|
+
- **high** (70-100): proceed normally
|
|
37
|
+
- **medium** (40-69): surface reasons to the user, proceed with caution
|
|
38
|
+
- **low** (0-39): STOP. Show the reasons. Ask the user to confirm before working. Low confidence means critical context may be missing.
|
|
39
|
+
|
|
35
40
|
## 2. DISCOVER (when discovery is pending)
|
|
36
41
|
If the project root or a task node has \`discovery: "pending"\`, you must complete discovery before decomposing it. Discovery is an interview with the user to understand what needs to happen.
|
|
37
42
|
|
|
@@ -171,4 +176,4 @@ function handleAgentConfig(version) {
|
|
|
171
176
|
export {
|
|
172
177
|
handleAgentConfig
|
|
173
178
|
};
|
|
174
|
-
//# sourceMappingURL=chunk-
|
|
179
|
+
//# sourceMappingURL=chunk-M5QOJN7D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/agent-config.ts"],"sourcesContent":["// [sl:fV9I7Vel3xT5d_Ws2YHul] Subagent delivery — free for all (retention hook)\n\nfunction agentPrompt(version: string): string {\n return `---\nname: graph\nversion: ${version}\ndescription: Use this agent for tasks tracked in Graph. Enforces the claim-work-resolve workflow — always checks graph_next before working, adds new work to the graph before executing, and resolves with evidence.\ntools: Read, Edit, Write, Bash, Glob, Grep, Task(Explore), AskUserQuestion\nmodel: sonnet\n---\n\nYou are a graph-optimized agent. You execute tasks tracked in a Graph project. Follow this workflow strictly. The human directs, you execute through the graph.\n\n# Workflow\n\n## 1. ORIENT\nOn your first call, orient yourself:\n\\`\\`\\`\ngraph_onboard({ project: \"<project-name>\" })\n\\`\\`\\`\nRead the \\`hint\\` field first — it tells you exactly what to do next. Then read the summary, evidence, knowledge, and actionable tasks.\n\n**First-run:** If the tree is empty and discovery is \\`\"pending\"\\`, this is a brand new project. Jump directly to DISCOVER below. Do not call graph_next on an empty project.\n\n**Drift check:** After onboarding, check for work done outside the graph:\n1. Run \\`git log --oneline -10\\` to see recent commits\n2. Compare against git evidence in the graph (commit hashes from resolved tasks)\n3. If there are commits not tracked in the graph, surface them to the user:\n - \"Found N commits not linked to any graph task: <list>\"\n - Ask: add retroactively (create node + evidence), or acknowledge and move on?\n\nThis catches work done ad-hoc or through plan files that bypassed the graph. It's cheap to run and prevents silent context loss.\n\n**Continuity confidence:** \\`graph_onboard\\` returns a \\`continuity_confidence\\` signal (\\`high\\`/\\`medium\\`/\\`low\\`) with a score and reasons. This tells you how reliable the inherited context is.\n- **high** (70-100): proceed normally\n- **medium** (40-69): surface reasons to the user, proceed with caution\n- **low** (0-39): STOP. Show the reasons. Ask the user to confirm before working. Low confidence means critical context may be missing.\n\n## 2. DISCOVER (when discovery is pending)\nIf the project root or a task node has \\`discovery: \"pending\"\\`, you must complete discovery before decomposing it. Discovery is an interview with the user to understand what needs to happen.\n\nUse AskUserQuestion to cover these areas (adapt to what's relevant — skip what's obvious):\n- **Scope** — What exactly needs to happen? What's explicitly out of scope?\n- **Existing patterns** — How does the codebase currently handle similar things? (explore first, then confirm)\n- **Technical approach** — What libraries, APIs, or patterns should we use?\n- **Acceptance criteria** — How will we know it's done? What does success look like?\n\nAfter the interview:\n1. Write findings as knowledge: \\`graph_knowledge_write({ project, key: \"discovery-<topic>\", content: \"...\" })\\`\n2. Flip discovery to done: \\`graph_update({ updates: [{ node_id: \"<id>\", discovery: \"done\" }] })\\`\n3. NOW decompose with graph_plan\n\nDo NOT skip discovery. If you try to add children to a node with \\`discovery: \"pending\"\\`, graph_plan will reject it.\n\n## 3. CLAIM\nGet your next task:\n\\`\\`\\`\ngraph_next({ project: \"<project-name>\", claim: true })\n\\`\\`\\`\nRead the task summary, ancestor chain (for scope), resolved dependencies (for context on what was done before you), and context links (for files to look at).\n\n## 4. PLAN\nIf you discover work that isn't in the graph, add it BEFORE executing:\n\\`\\`\\`\ngraph_plan({ nodes: [{ ref: \"new-work\", parent_ref: \"<parent-id>\", summary: \"...\" }] })\n\\`\\`\\`\nNever execute ad-hoc work. The graph is the source of truth.\n\nWhen decomposing work:\n- Set dependencies on LEAF nodes, not parent nodes. If \"Page A\" depends on \"Layout\", the dependency is from \"Page A\" to \"Layout\", not from the \"Pages\" parent to \"Layout\".\n- Keep tasks small and specific. A task should be completable in one session.\n- Parent nodes are organizational — they resolve when all children resolve. Don't put work in parent nodes.\n\n## 5. WORK\nExecute the claimed task. While working:\n- Annotate key code changes with \\`// [sl:nodeId]\\` where nodeId is the task you're working on\n- This creates a traceable link from code back to the task, its evidence, and its history\n- Build and run tests before considering a task done\n\n## 6. RESOLVE\nWhen done, resolve the task with a structured handoff. Every resolution should answer these questions for the next agent:\n\n- **What changed** — what was modified or created\n- **Why** — reasoning behind the approach taken\n- **Evidence** — commits, test results, implementation notes\n- **Next action** — what should happen next (if applicable)\n\n\\`\\`\\`\ngraph_update({ updates: [{\n node_id: \"<task-id>\",\n resolved: true,\n add_evidence: [\n { type: \"note\", ref: \"Implemented X using Y because Z. Next: wire up the API endpoint.\" },\n { type: \"git\", ref: \"<commit-hash> — <summary>\" },\n { type: \"test\", ref: \"All 155 tests passing\" }\n ],\n add_context_links: [\"path/to/files/you/touched\"]\n}] })\n\\`\\`\\`\n\nEvidence is mandatory. Write notes as if briefing an agent who has never seen the codebase — they should understand what was done and why without reading the code.\n\n## 7. PAUSE\nAfter resolving a task, STOP. Show the user the project status using \\`graph_status\\`, then wait for them to say \"continue\" before claiming the next task.\n\nThe user controls the pace. Do not auto-claim the next task.\n\n## Presenting status\nWhen showing project state to the user, always use \\`graph_status({ project: \"...\" })\\` and output the \\`formatted\\` field directly. This gives a consistent, readable view. Never format graph data manually — use the tool.\n\n# Rules\n\n- NEVER start work without a claimed task\n- NEVER resolve without evidence\n- NEVER execute ad-hoc work — add it to the graph first via graph_plan\n- NEVER auto-continue to the next task — pause and let the user decide\n- ALWAYS build and test before resolving\n- ALWAYS include context_links for files you modified when resolving\n- Parent nodes auto-resolve when all their children are resolved — you don't need to manually resolve them\n- NEVER skip discovery on nodes with discovery:pending — the system will block you from decomposing\n- NEVER delete resolved projects — they are the historical record. Completed projects are lightweight and preserve traceability across sessions\n- If you're approaching context limits, ensure your current task's state is captured (update with evidence even if not fully resolved) so the next agent can pick up where you left off\n\n# Record observations proactively\n\nGraph is the project memory across sessions. If something isn't in Graph, it's effectively forgotten. While working, record things you notice — even if they're not part of your current task:\n\n- **Warnings & errors**: CI failures, deprecation warnings, security vulnerabilities, linter issues\n- **Tech debt**: Code smells, outdated dependencies, missing tests, hardcoded values\n- **Broken things**: Flaky tests, dead links, misconfigured environments\n- **Ideas & improvements**: Performance opportunities, UX issues, missing features\n\nUse \\`graph_plan\\` to add observation nodes under the project root. Keep them lightweight — a clear summary is enough. They can always be dropped later if irrelevant.\n\nDefault to \"if in doubt, add a node.\" It's cheap to create and the next session will thank you.\n\n# Blocked status\n\nNodes can be manually blocked (separate from dependency-blocked). Use this for external blockers:\n\n\\`\\`\\`\ngraph_update({ updates: [{\n node_id: \"<id>\",\n blocked: true,\n blocked_reason: \"Waiting on API key from client\"\n}] })\n\\`\\`\\`\n\nTo unblock: \\`graph_update({ updates: [{ node_id: \"<id>\", blocked: false }] })\\`\n\n- \\`blocked_reason\\` is required when setting \\`blocked: true\\`\n- Blocked nodes won't appear in \\`graph_next\\` results\n- Unblocking auto-clears the reason\n- Use this for things like: waiting on external input, upstream API down, needs design review\n\n# Common mistakes to avoid\n\n- Setting dependencies on parent nodes instead of leaf nodes\n- Running project scaffolding tools (create-next-app, etc.) before planning in the graph\n- Resolving tasks without running tests\n- Doing work that isn't tracked in the graph\n- Continuing to the next task without pausing for user review\n- Trying to decompose a node without completing discovery first\n- Not writing knowledge entries during discovery — future agents need this context\n`;\n}\n\nexport interface AgentConfigResult {\n agent_file: string;\n install_path: string;\n instructions: string;\n}\n\nexport function handleAgentConfig(version: string): AgentConfigResult {\n return {\n agent_file: agentPrompt(version),\n install_path: \".claude/agents/graph.md\",\n instructions:\n \"Save the agent_file content to .claude/agents/graph.md in your project root. \" +\n \"Claude Code will automatically discover it and use it when tasks match the agent description.\",\n };\n}\n"],"mappings":";;;AAEA,SAAS,YAAY,SAAyB;AAC5C,SAAO;AAAA;AAAA,WAEE,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgKlB;AAQO,SAAS,kBAAkB,SAAoC;AACpE,SAAO;AAAA,IACL,YAAY,YAAY,OAAO;AAAA,IAC/B,cAAc;AAAA,IACd,cACE;AAAA,EAEJ;AACF;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -6,10 +6,10 @@ if (args[0] === "activate") {
|
|
|
6
6
|
const { activate } = await import("./activate-DSDTR2EJ.js");
|
|
7
7
|
activate(args[1]);
|
|
8
8
|
} else if (args[0] === "init") {
|
|
9
|
-
const { init } = await import("./init-
|
|
9
|
+
const { init } = await import("./init-74TF4PX3.js");
|
|
10
10
|
init();
|
|
11
11
|
} else {
|
|
12
|
-
const { startServer } = await import("./server-
|
|
12
|
+
const { startServer } = await import("./server-XSKUM3G5.js");
|
|
13
13
|
startServer().catch((error) => {
|
|
14
14
|
console.error("Failed to start graph:", error);
|
|
15
15
|
process.exit(1);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
handleAgentConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-M5QOJN7D.js";
|
|
5
5
|
|
|
6
6
|
// src/init.ts
|
|
7
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync } from "fs";
|
|
8
8
|
import { join, dirname } from "path";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
10
10
|
var PKG_VERSION = "0.0.0";
|
|
@@ -63,6 +63,29 @@ function init() {
|
|
|
63
63
|
console.log("\u2713 .claude/agents/graph.md \u2014 created graph workflow agent");
|
|
64
64
|
wrote = true;
|
|
65
65
|
}
|
|
66
|
+
const claudeMdPath = join(cwd, "CLAUDE.md");
|
|
67
|
+
const graphSection = `
|
|
68
|
+
## Graph workflow
|
|
69
|
+
|
|
70
|
+
This project uses Graph for task tracking across sessions. Start every session with \`graph_onboard\` to see project state, actionable tasks, and continuity confidence. Follow the claim-work-resolve loop: \`graph_next\` (claim) \u2192 do work \u2192 \`graph_update\` (resolve with evidence). Don't execute ad-hoc work \u2014 add it to the graph first via \`graph_plan\`.
|
|
71
|
+
`;
|
|
72
|
+
if (existsSync(claudeMdPath)) {
|
|
73
|
+
const current = readFileSync(claudeMdPath, "utf8");
|
|
74
|
+
if (current.includes("graph_onboard")) {
|
|
75
|
+
console.log("\u2713 CLAUDE.md \u2014 graph workflow instructions already present");
|
|
76
|
+
} else {
|
|
77
|
+
appendFileSync(claudeMdPath, graphSection, "utf8");
|
|
78
|
+
console.log("\u2713 CLAUDE.md \u2014 appended graph workflow instructions");
|
|
79
|
+
wrote = true;
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
writeFileSync(claudeMdPath, `# CLAUDE.md
|
|
83
|
+
|
|
84
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
85
|
+
${graphSection}`, "utf8");
|
|
86
|
+
console.log("\u2713 CLAUDE.md \u2014 created with graph workflow instructions");
|
|
87
|
+
wrote = true;
|
|
88
|
+
}
|
|
66
89
|
console.log("");
|
|
67
90
|
if (wrote) {
|
|
68
91
|
console.log("Graph is ready. Restart Claude Code to load the MCP server.");
|
|
@@ -76,4 +99,4 @@ function init() {
|
|
|
76
99
|
export {
|
|
77
100
|
init
|
|
78
101
|
};
|
|
79
|
-
//# sourceMappingURL=init-
|
|
102
|
+
//# sourceMappingURL=init-74TF4PX3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/init.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { handleAgentConfig } from \"./tools/agent-config.js\";\n\n// [sl:hy8oXisWnrZN1BfkonUqd] npx @graph-tl/graph init — zero friction onboarding\n\nlet PKG_VERSION = \"0.0.0\";\ntry {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkg = JSON.parse(readFileSync(join(__dirname, \"..\", \"package.json\"), \"utf-8\"));\n PKG_VERSION = pkg.version;\n} catch {}\n\nconst MCP_CONFIG = {\n command: \"npx\",\n args: [\"-y\", \"@graph-tl/graph\"],\n env: {\n GRAPH_AGENT: \"claude-code\",\n },\n};\n\nexport function init(): void {\n const cwd = process.cwd();\n let wrote = false;\n\n // 1. Write .mcp.json\n const configPath = join(cwd, \".mcp.json\");\n if (existsSync(configPath)) {\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf8\"));\n if (config.mcpServers?.graph) {\n console.log(\"✓ .mcp.json — graph already configured\");\n } else {\n config.mcpServers = config.mcpServers ?? {};\n config.mcpServers.graph = MCP_CONFIG;\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf8\");\n console.log(\"✓ .mcp.json — added graph server\");\n wrote = true;\n }\n } catch {\n console.error(`✗ .mcp.json exists but is not valid JSON — skipping`);\n }\n } else {\n const config = { mcpServers: { graph: MCP_CONFIG } };\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf8\");\n console.log(\"✓ .mcp.json — created with graph server\");\n wrote = true;\n }\n\n // 2. Write .claude/agents/graph.md\n const agentPath = join(cwd, \".claude\", \"agents\", \"graph.md\");\n const { agent_file } = handleAgentConfig(PKG_VERSION);\n if (existsSync(agentPath)) {\n const current = readFileSync(agentPath, \"utf8\");\n if (current === agent_file) {\n console.log(\"✓ .claude/agents/graph.md — already up to date\");\n } else {\n writeFileSync(agentPath, agent_file, \"utf8\");\n console.log(\"✓ .claude/agents/graph.md — updated\");\n wrote = true;\n }\n } else {\n mkdirSync(dirname(agentPath), { recursive: true });\n writeFileSync(agentPath, agent_file, \"utf8\");\n console.log(\"✓ .claude/agents/graph.md — created graph workflow agent\");\n wrote = true;\n }\n\n // 3. Append graph workflow instructions to CLAUDE.md\n // [sl:qPxNQTKru6q3nPzsNWlfe] Ensure default agent follows graph workflow\n const claudeMdPath = join(cwd, \"CLAUDE.md\");\n const graphSection = `\n## Graph workflow\n\nThis project uses Graph for task tracking across sessions. Start every session with \\`graph_onboard\\` to see project state, actionable tasks, and continuity confidence. Follow the claim-work-resolve loop: \\`graph_next\\` (claim) → do work → \\`graph_update\\` (resolve with evidence). Don't execute ad-hoc work — add it to the graph first via \\`graph_plan\\`.\n`;\n\n if (existsSync(claudeMdPath)) {\n const current = readFileSync(claudeMdPath, \"utf8\");\n if (current.includes(\"graph_onboard\")) {\n console.log(\"✓ CLAUDE.md — graph workflow instructions already present\");\n } else {\n appendFileSync(claudeMdPath, graphSection, \"utf8\");\n console.log(\"✓ CLAUDE.md — appended graph workflow instructions\");\n wrote = true;\n }\n } else {\n writeFileSync(claudeMdPath, `# CLAUDE.md\\n\\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\\n${graphSection}`, \"utf8\");\n console.log(\"✓ CLAUDE.md — created with graph workflow instructions\");\n wrote = true;\n }\n\n // 4. Summary\n console.log(\"\");\n if (wrote) {\n console.log(\"Graph is ready. Restart Claude Code to load the MCP server.\");\n console.log(\"\");\n console.log(\"Then try:\");\n console.log(' \"Use graph to plan building a REST API with auth and tests.\"');\n } else {\n console.log(\"Graph is already set up — nothing to do.\");\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,cAAc,eAAe,YAAY,WAAW,sBAAsB;AACnF,SAAS,MAAM,eAAe;AAC9B,SAAS,qBAAqB;AAK9B,IAAI,cAAc;AAClB,IAAI;AACF,QAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,QAAM,MAAM,KAAK,MAAM,aAAa,KAAK,WAAW,MAAM,cAAc,GAAG,OAAO,CAAC;AACnF,gBAAc,IAAI;AACpB,QAAQ;AAAC;AAET,IAAM,aAAa;AAAA,EACjB,SAAS;AAAA,EACT,MAAM,CAAC,MAAM,iBAAiB;AAAA,EAC9B,KAAK;AAAA,IACH,aAAa;AAAA,EACf;AACF;AAEO,SAAS,OAAa;AAC3B,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,QAAQ;AAGZ,QAAM,aAAa,KAAK,KAAK,WAAW;AACxC,MAAI,WAAW,UAAU,GAAG;AAC1B,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,aAAa,YAAY,MAAM,CAAC;AAC1D,UAAI,OAAO,YAAY,OAAO;AAC5B,gBAAQ,IAAI,kDAAwC;AAAA,MACtD,OAAO;AACL,eAAO,aAAa,OAAO,cAAc,CAAC;AAC1C,eAAO,WAAW,QAAQ;AAC1B,sBAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AACxE,gBAAQ,IAAI,4CAAkC;AAC9C,gBAAQ;AAAA,MACV;AAAA,IACF,QAAQ;AACN,cAAQ,MAAM,+DAAqD;AAAA,IACrE;AAAA,EACF,OAAO;AACL,UAAM,SAAS,EAAE,YAAY,EAAE,OAAO,WAAW,EAAE;AACnD,kBAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AACxE,YAAQ,IAAI,mDAAyC;AACrD,YAAQ;AAAA,EACV;AAGA,QAAM,YAAY,KAAK,KAAK,WAAW,UAAU,UAAU;AAC3D,QAAM,EAAE,WAAW,IAAI,kBAAkB,WAAW;AACpD,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,UAAU,aAAa,WAAW,MAAM;AAC9C,QAAI,YAAY,YAAY;AAC1B,cAAQ,IAAI,0DAAgD;AAAA,IAC9D,OAAO;AACL,oBAAc,WAAW,YAAY,MAAM;AAC3C,cAAQ,IAAI,+CAAqC;AACjD,cAAQ;AAAA,IACV;AAAA,EACF,OAAO;AACL,cAAU,QAAQ,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,kBAAc,WAAW,YAAY,MAAM;AAC3C,YAAQ,IAAI,oEAA0D;AACtE,YAAQ;AAAA,EACV;AAIA,QAAM,eAAe,KAAK,KAAK,WAAW;AAC1C,QAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAMrB,MAAI,WAAW,YAAY,GAAG;AAC5B,UAAM,UAAU,aAAa,cAAc,MAAM;AACjD,QAAI,QAAQ,SAAS,eAAe,GAAG;AACrC,cAAQ,IAAI,qEAA2D;AAAA,IACzE,OAAO;AACL,qBAAe,cAAc,cAAc,MAAM;AACjD,cAAQ,IAAI,8DAAoD;AAChE,cAAQ;AAAA,IACV;AAAA,EACF,OAAO;AACL,kBAAc,cAAc;AAAA;AAAA;AAAA,EAA0H,YAAY,IAAI,MAAM;AAC5K,YAAQ,IAAI,kEAAwD;AACpE,YAAQ;AAAA,EACV;AAGA,UAAQ,IAAI,EAAE;AACd,MAAI,OAAO;AACT,YAAQ,IAAI,6DAA6D;AACzE,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,WAAW;AACvB,YAAQ,IAAI,gEAAgE;AAAA,EAC9E,OAAO;AACL,YAAQ,IAAI,+CAA0C;AAAA,EACxD;AACF;","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-WKOEKYTF.js";
|
|
5
5
|
import {
|
|
6
6
|
handleAgentConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-M5QOJN7D.js";
|
|
8
8
|
import {
|
|
9
9
|
EngineError,
|
|
10
10
|
ValidationError,
|
|
@@ -1006,6 +1006,93 @@ function handleHistory(input) {
|
|
|
1006
1006
|
return result;
|
|
1007
1007
|
}
|
|
1008
1008
|
|
|
1009
|
+
// src/continuity.ts
|
|
1010
|
+
function getProjectStats(project) {
|
|
1011
|
+
const db = getDb();
|
|
1012
|
+
const resolved = db.prepare(
|
|
1013
|
+
"SELECT COUNT(*) as cnt FROM nodes WHERE project = ? AND parent IS NOT NULL AND resolved = 1"
|
|
1014
|
+
).get(project);
|
|
1015
|
+
const withEvidence = db.prepare(
|
|
1016
|
+
"SELECT COUNT(*) as cnt FROM nodes WHERE project = ? AND parent IS NOT NULL AND resolved = 1 AND evidence != '[]'"
|
|
1017
|
+
).get(project);
|
|
1018
|
+
const lastAct = db.prepare(
|
|
1019
|
+
"SELECT MAX(updated_at) as last FROM nodes WHERE project = ?"
|
|
1020
|
+
).get(project);
|
|
1021
|
+
const knowledge = db.prepare(
|
|
1022
|
+
"SELECT COUNT(*) as cnt FROM knowledge WHERE project = ?"
|
|
1023
|
+
).get(project);
|
|
1024
|
+
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1e3).toISOString();
|
|
1025
|
+
const staleBlocked = db.prepare(
|
|
1026
|
+
"SELECT COUNT(*) as cnt FROM nodes WHERE project = ? AND blocked = 1 AND updated_at < ?"
|
|
1027
|
+
).get(project, sevenDaysAgo);
|
|
1028
|
+
const total = db.prepare(
|
|
1029
|
+
"SELECT COUNT(*) as cnt FROM nodes WHERE project = ? AND parent IS NOT NULL"
|
|
1030
|
+
).get(project);
|
|
1031
|
+
return {
|
|
1032
|
+
resolvedCount: resolved.cnt,
|
|
1033
|
+
resolvedWithEvidence: withEvidence.cnt,
|
|
1034
|
+
lastActivity: lastAct.last,
|
|
1035
|
+
knowledgeCount: knowledge.cnt,
|
|
1036
|
+
staleBlockedCount: staleBlocked.cnt,
|
|
1037
|
+
totalNonRoot: total.cnt
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
function computeContinuityConfidence(project) {
|
|
1041
|
+
const stats = getProjectStats(project);
|
|
1042
|
+
const reasons = [];
|
|
1043
|
+
let score = 100;
|
|
1044
|
+
if (stats.resolvedCount > 0) {
|
|
1045
|
+
const coverage = stats.resolvedWithEvidence / stats.resolvedCount;
|
|
1046
|
+
const missing = stats.resolvedCount - stats.resolvedWithEvidence;
|
|
1047
|
+
if (coverage < 0.5) {
|
|
1048
|
+
score -= 40;
|
|
1049
|
+
reasons.push(`${missing} of ${stats.resolvedCount} resolved tasks have no evidence`);
|
|
1050
|
+
} else if (coverage < 0.8) {
|
|
1051
|
+
score -= 20;
|
|
1052
|
+
reasons.push(`${missing} of ${stats.resolvedCount} resolved tasks have no evidence`);
|
|
1053
|
+
} else if (coverage < 1) {
|
|
1054
|
+
score -= 10;
|
|
1055
|
+
reasons.push(`${missing} resolved task(s) missing evidence`);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
if (stats.lastActivity) {
|
|
1059
|
+
const ageMs = Date.now() - new Date(stats.lastActivity).getTime();
|
|
1060
|
+
const ageDays = ageMs / (24 * 60 * 60 * 1e3);
|
|
1061
|
+
if (ageDays > 14) {
|
|
1062
|
+
score -= 25;
|
|
1063
|
+
reasons.push(`No activity for ${Math.floor(ageDays)} days`);
|
|
1064
|
+
} else if (ageDays > 7) {
|
|
1065
|
+
score -= 15;
|
|
1066
|
+
reasons.push(`No activity for ${Math.floor(ageDays)} days`);
|
|
1067
|
+
} else if (ageDays > 3) {
|
|
1068
|
+
score -= 5;
|
|
1069
|
+
reasons.push(`Last activity ${Math.floor(ageDays)} days ago`);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
if (stats.resolvedCount >= 5 && stats.knowledgeCount === 0) {
|
|
1073
|
+
score -= 15;
|
|
1074
|
+
reasons.push("No knowledge entries on a project with 5+ resolved tasks");
|
|
1075
|
+
}
|
|
1076
|
+
if (stats.staleBlockedCount > 0) {
|
|
1077
|
+
score -= 10;
|
|
1078
|
+
reasons.push(`${stats.staleBlockedCount} blocked item(s) not updated in 7+ days`);
|
|
1079
|
+
}
|
|
1080
|
+
if (stats.totalNonRoot === 0) {
|
|
1081
|
+
score -= 10;
|
|
1082
|
+
reasons.push("Project has no tasks yet");
|
|
1083
|
+
}
|
|
1084
|
+
score = Math.max(0, Math.min(100, score));
|
|
1085
|
+
let confidence;
|
|
1086
|
+
if (score >= 70) {
|
|
1087
|
+
confidence = "high";
|
|
1088
|
+
} else if (score >= 40) {
|
|
1089
|
+
confidence = "medium";
|
|
1090
|
+
} else {
|
|
1091
|
+
confidence = "low";
|
|
1092
|
+
}
|
|
1093
|
+
return { confidence, score, reasons };
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1009
1096
|
// src/tools/onboard.ts
|
|
1010
1097
|
function handleOnboard(input) {
|
|
1011
1098
|
const evidenceLimit = optionalNumber(input?.evidence_limit, "evidence_limit", 1, 50) ?? 20;
|
|
@@ -1134,6 +1221,7 @@ function handleOnboard(input) {
|
|
|
1134
1221
|
} else if (summary.total <= 1 && root.discovery !== "pending") {
|
|
1135
1222
|
hint = `Project is empty \u2014 use graph_plan to decompose the goal into tasks.`;
|
|
1136
1223
|
}
|
|
1224
|
+
const continuity_confidence = computeContinuityConfidence(project);
|
|
1137
1225
|
return {
|
|
1138
1226
|
project,
|
|
1139
1227
|
goal: root.summary,
|
|
@@ -1146,6 +1234,7 @@ function handleOnboard(input) {
|
|
|
1146
1234
|
knowledge: knowledgeRows,
|
|
1147
1235
|
recently_resolved,
|
|
1148
1236
|
last_activity,
|
|
1237
|
+
continuity_confidence,
|
|
1149
1238
|
actionable
|
|
1150
1239
|
};
|
|
1151
1240
|
}
|
|
@@ -1294,7 +1383,15 @@ function handleStatus(input) {
|
|
|
1294
1383
|
const resolvedTasks = Math.min(summary.resolved, taskCount);
|
|
1295
1384
|
if (taskCount > 0) {
|
|
1296
1385
|
lines.push(progressBar(resolvedTasks, taskCount));
|
|
1297
|
-
|
|
1386
|
+
const cc = computeContinuityConfidence(project);
|
|
1387
|
+
const ccBars = Math.ceil(cc.score / 20);
|
|
1388
|
+
const ccDisplay = "\u25A0".repeat(ccBars) + "\u25A1".repeat(5 - ccBars);
|
|
1389
|
+
lines.push(`${summary.actionable} actionable | ${summary.blocked} blocked | ${summary.unresolved - summary.blocked - summary.actionable} waiting | continuity confidence: ${cc.confidence} ${ccDisplay}`);
|
|
1390
|
+
if (cc.reasons.length > 0 && cc.confidence !== "high") {
|
|
1391
|
+
for (const reason of cc.reasons) {
|
|
1392
|
+
lines.push(` - ${reason}`);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1298
1395
|
} else {
|
|
1299
1396
|
lines.push("No tasks yet");
|
|
1300
1397
|
}
|
|
@@ -2136,4 +2233,4 @@ async function startServer() {
|
|
|
2136
2233
|
export {
|
|
2137
2234
|
startServer
|
|
2138
2235
|
};
|
|
2139
|
-
//# sourceMappingURL=server-
|
|
2236
|
+
//# sourceMappingURL=server-XSKUM3G5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/tools/open.ts","../src/edges.ts","../src/tools/plan.ts","../src/tools/update.ts","../src/tools/connect.ts","../src/tools/context.ts","../src/tools/query.ts","../src/tools/next.ts","../src/tools/restructure.ts","../src/tools/history.ts","../src/continuity.ts","../src/tools/onboard.ts","../src/tools/tree.ts","../src/tools/status.ts","../src/tools/knowledge.ts","../src/gates.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ReadResourceRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { setDbPath, closeDb, checkpointDb } from \"./db.js\";\nimport { ValidationError, EngineError } from \"./validate.js\";\nimport { handleOpen } from \"./tools/open.js\";\nimport { handlePlan } from \"./tools/plan.js\";\nimport { handleUpdate } from \"./tools/update.js\";\nimport { handleConnect } from \"./tools/connect.js\";\nimport { handleContext } from \"./tools/context.js\";\nimport { handleQuery } from \"./tools/query.js\";\nimport { handleNext } from \"./tools/next.js\";\nimport { handleRestructure } from \"./tools/restructure.js\";\nimport { handleHistory } from \"./tools/history.js\";\nimport { handleOnboard } from \"./tools/onboard.js\";\nimport { handleAgentConfig } from \"./tools/agent-config.js\";\nimport { handleTree } from \"./tools/tree.js\";\nimport { handleStatus } from \"./tools/status.js\";\nimport { handleKnowledgeWrite, handleKnowledgeRead, handleKnowledgeDelete, handleKnowledgeSearch } from \"./tools/knowledge.js\";\nimport { getLicenseTier, type Tier } from \"./license.js\";\nimport { checkNodeLimit, checkProjectLimit, capEvidenceLimit, checkScope, checkKnowledgeTier } from \"./gates.js\";\n\nimport { createHash } from \"crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { join, resolve, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// Config from env\nconst AGENT_IDENTITY = process.env.GRAPH_AGENT ?? \"default-agent\";\nconst CLAIM_TTL = parseInt(process.env.GRAPH_CLAIM_TTL ?? \"60\", 10);\n\nfunction defaultDbPath(): string {\n const projectDir = resolve(\".\");\n const hash = createHash(\"sha256\").update(projectDir).digest(\"hex\").slice(0, 16);\n const dir = join(homedir(), \".graph\", \"db\", hash);\n mkdirSync(dir, { recursive: true });\n return join(dir, \"graph.db\");\n}\n\nconst DB_PATH = process.env.GRAPH_DB ?? defaultDbPath();\n\n// Read version from package.json\nconst PKG_NAME = \"@graph-tl/graph\";\nlet PKG_VERSION = \"0.0.0\";\ntry {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkg = JSON.parse(readFileSync(join(__dirname, \"..\", \"package.json\"), \"utf-8\"));\n PKG_VERSION = pkg.version;\n} catch {}\n\n// Version banner — shown once on first tool call\nlet versionBanner: string | null = `[graph] v${PKG_VERSION}`;\n\n// Non-blocking version check against npm registry\nlet updateWarning: string | null = null;\n\nasync function checkForUpdate(): Promise<void> {\n try {\n const res = await fetch(`https://registry.npmjs.org/${PKG_NAME}/latest`);\n if (!res.ok) return;\n const data = await res.json() as { version: string };\n if (data.version !== PKG_VERSION) {\n updateWarning = `[graph] Update available: ${PKG_VERSION} → ${data.version}. Run: npx clear-npx-cache && restart MCP server.`;\n }\n } catch {}\n}\n\n// Auto-update agent file on first tool call\nfunction checkAndUpdateAgentFile(): string | null {\n try {\n const projectRoot = resolve(\".\");\n const agentPath = join(projectRoot, \".claude\", \"agents\", \"graph.md\");\n const latest = handleAgentConfig(PKG_VERSION).agent_file;\n\n if (existsSync(agentPath)) {\n const current = readFileSync(agentPath, \"utf-8\");\n if (current === latest) return null;\n // Extract version from existing frontmatter\n const match = current.match(/^---[\\s\\S]*?version:\\s*(\\S+)[\\s\\S]*?---/);\n const oldVersion = match?.[1] ?? \"unknown\";\n writeFileSync(agentPath, latest, \"utf-8\");\n return `[graph] Updated .claude/agents/graph.md (${oldVersion} → ${PKG_VERSION})`;\n } else {\n mkdirSync(dirname(agentPath), { recursive: true });\n writeFileSync(agentPath, latest, \"utf-8\");\n return `[graph] Created .claude/agents/graph.md`;\n }\n } catch {\n return null;\n }\n}\n\n// Tool definitions\nconst TOOLS = [\n {\n name: \"graph_open\",\n description:\n \"Open an existing project or create a new one. Omit 'project' to list all projects. Returns project root node and summary stats (total, resolved, unresolved, blocked, actionable counts).\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: {\n type: \"string\",\n description: \"Project name (e.g. 'my-project'). Omit to list all projects.\",\n },\n goal: {\n type: \"string\",\n description: \"Project goal/description. Used on creation only.\",\n },\n skip_discovery: {\n type: \"boolean\",\n description: \"Skip discovery phase — create project ready for immediate planning. Default false.\",\n },\n },\n },\n },\n {\n name: \"graph_plan\",\n description:\n \"Batch create nodes with parent-child and dependency relationships in one atomic call. Use for decomposing work into subtrees. Each node needs a temp 'ref' for intra-batch references. parent_ref and depends_on can reference batch refs or existing node IDs.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n nodes: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n ref: {\n type: \"string\",\n description: \"Temp ID for referencing within this batch\",\n },\n parent_ref: {\n type: \"string\",\n description:\n \"Parent: a ref from this batch OR an existing node ID\",\n },\n summary: { type: \"string\" },\n context_links: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Pointers to files, commits, URLs\",\n },\n depends_on: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Refs within batch OR existing node IDs this depends on\",\n },\n properties: {\n type: \"object\",\n description: \"Freeform key-value properties\",\n },\n },\n required: [\"ref\", \"summary\"],\n },\n description: \"Nodes to create\",\n },\n },\n required: [\"nodes\"],\n },\n },\n {\n name: \"graph_next\",\n description:\n \"Get the next actionable node — an unresolved leaf with all dependencies resolved. Ranked by priority (from properties), depth, and least-recently-updated. Returns the node with ancestor chain, context links, and resolved dependency info. Use claim=true to soft-lock the node. When modifying code for this task, annotate key changes with // [sl:nodeId] so future agents can trace code back to this task.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name (e.g. 'my-project'), not a node ID\" },\n scope: {\n type: \"string\",\n description: \"Node ID to scope results to. Only returns actionable descendants of this node.\",\n },\n filter: {\n type: \"object\",\n description: \"Match against node properties\",\n },\n count: {\n type: \"number\",\n description: \"Return top N nodes (default 1)\",\n },\n claim: {\n type: \"boolean\",\n description:\n \"If true, soft-lock returned nodes with agent identity\",\n },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"graph_context\",\n description:\n \"Deep-read a node and its neighborhood: ancestors (scope chain), children tree (to configurable depth), dependency graph (what it depends on, what depends on it). Look for // [sl:nodeId] annotations in source files to find code tied to specific tasks.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n node_id: { type: \"string\", description: \"Node ID to inspect\" },\n depth: {\n type: \"number\",\n description: \"Levels of children to return (default 2)\",\n },\n },\n required: [\"node_id\"],\n },\n },\n {\n name: \"graph_update\",\n description:\n \"Update one or more nodes. Can change resolved, state, summary, properties (merged), context_links, and add evidence. When resolving nodes, returns newly_actionable — nodes that became unblocked. ENFORCED: Resolving a node requires evidence — use resolved_reason (shorthand, auto-creates note) or add_evidence array (type: 'git' for commits, 'note' for what was done and why, 'test' for results). Also add context_links to files you modified.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n updates: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n node_id: { type: \"string\" },\n expected_rev: { type: \"number\", description: \"Optimistic concurrency: reject if node's current rev doesn't match. Prevents silent overwrites by concurrent agents.\" },\n resolved: { type: \"boolean\" },\n resolved_reason: { type: \"string\", description: \"Shorthand: auto-creates a note evidence entry. Use instead of add_evidence for simple cases.\" },\n discovery: { type: \"string\", description: \"Discovery phase status: 'pending' or 'done'. Set to 'done' after completing discovery interview.\" },\n blocked: { type: \"boolean\", description: \"Manually block/unblock a node. Blocked nodes are skipped by graph_next. Use for external blockers (e.g., waiting on domain purchase, another team).\" },\n blocked_reason: { type: \"string\", description: \"Why the node is blocked. Cleared automatically when unblocking.\" },\n state: { description: \"Agent-defined state, any type\" },\n summary: { type: \"string\" },\n properties: {\n type: \"object\",\n description:\n \"Merged into existing. Set a key to null to delete it.\",\n },\n add_context_links: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Files modified or created for this task. Add when resolving so future agents know what was touched.\",\n },\n remove_context_links: {\n type: \"array\",\n items: { type: \"string\" },\n },\n add_evidence: {\n type: \"array\",\n description: \"Evidence of work done. Always add when resolving. Types: 'git' (commit hash + summary), 'note' (what was implemented and why), 'test' (test results).\",\n items: {\n type: \"object\",\n properties: {\n type: { type: \"string\", description: \"Evidence type: git, note, test, or custom\" },\n ref: { type: \"string\", description: \"The evidence content — commit ref, implementation note, test result\" },\n },\n required: [\"type\", \"ref\"],\n },\n },\n },\n required: [\"node_id\"],\n },\n },\n },\n required: [\"updates\"],\n },\n },\n {\n name: \"graph_connect\",\n description:\n \"Add or remove edges between nodes. Types: 'depends_on' (with cycle detection), 'relates_to', or custom. Parent edges not allowed — use graph_restructure for reparenting.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n edges: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n from: { type: \"string\", description: \"Source node ID\" },\n to: { type: \"string\", description: \"Target node ID\" },\n type: {\n type: \"string\",\n description: \"'depends_on', 'relates_to', or custom\",\n },\n remove: {\n type: \"boolean\",\n description: \"True to remove this edge\",\n },\n },\n required: [\"from\", \"to\", \"type\"],\n },\n },\n },\n required: [\"edges\"],\n },\n },\n {\n name: \"graph_query\",\n description:\n \"Search and filter nodes. Filters: resolved, properties, text, ancestor (descendants of), is_leaf, is_actionable, is_blocked, claimed_by. Supports sorting and cursor pagination.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name (e.g. 'my-project'), not a node ID\" },\n filter: {\n type: \"object\",\n properties: {\n resolved: { type: \"boolean\" },\n properties: { type: \"object\" },\n text: { type: \"string\", description: \"Substring match on summary\" },\n ancestor: {\n type: \"string\",\n description: \"Return all descendants of this node\",\n },\n has_evidence_type: { type: \"string\" },\n is_leaf: { type: \"boolean\" },\n is_actionable: { type: \"boolean\" },\n is_blocked: { type: \"boolean\" },\n claimed_by: {\n type: [\"string\", \"null\"],\n description: \"Filter by claim. null = unclaimed.\",\n },\n },\n },\n sort: {\n type: \"string\",\n enum: [\"readiness\", \"depth\", \"recent\", \"created\"],\n },\n limit: { type: \"number\", description: \"Max results (default 20, max 100)\" },\n cursor: { type: \"string\", description: \"Pagination cursor\" },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"graph_restructure\",\n description:\n \"Modify graph structure: move (reparent), merge (combine two nodes), drop (resolve node + subtree with reason), delete (permanently remove node + subtree). Atomic. Reports newly_actionable nodes.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n operations: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n op: {\n type: \"string\",\n enum: [\"move\", \"merge\", \"drop\", \"delete\"],\n },\n node_id: { type: \"string\", description: \"For move and drop\" },\n new_parent: { type: \"string\", description: \"For move\" },\n source: { type: \"string\", description: \"For merge: node to absorb\" },\n target: {\n type: \"string\",\n description: \"For merge: node that survives\",\n },\n reason: { type: \"string\", description: \"For drop: why\" },\n },\n required: [\"op\"],\n },\n },\n },\n required: [\"operations\"],\n },\n },\n {\n name: \"graph_history\",\n description:\n \"Read the audit trail for a node. Shows who changed what, when, and why. Useful for understanding past decisions across sessions.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n node_id: { type: \"string\" },\n limit: { type: \"number\", description: \"Max events (default 20)\" },\n cursor: { type: \"string\", description: \"Pagination cursor\" },\n },\n required: [\"node_id\"],\n },\n },\n {\n name: \"graph_onboard\",\n description:\n \"Single-call orientation for new agents joining a project. Returns project summary, tree structure (depth 2), recent evidence from resolved nodes (knowledge transfer), all context links, and actionable tasks. Use this as your first call when starting work on an existing project.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name (e.g. 'my-project'). Omit to auto-select (works when there's exactly one project).\" },\n evidence_limit: {\n type: \"number\",\n description: \"Max evidence entries to return (default 20, max 50)\",\n },\n },\n },\n },\n {\n name: \"graph_tree\",\n description:\n \"Full tree visualization for a project. Returns the complete task hierarchy with resolve status. Use when you need to see the whole project structure beyond graph_context's single-node neighborhood.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name (e.g. 'my-project')\" },\n depth: {\n type: \"number\",\n description: \"Max tree depth to return (default 10, max 20)\",\n },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"graph_status\",\n description:\n \"Returns a pre-formatted markdown summary of a project's current state. Use this to present project status to the user — output the `formatted` field directly. Shows task tree with status tags, actionable items, blocked items, and knowledge entries. Omit project to auto-select or get multi-project overview.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: {\n type: \"string\",\n description: \"Project name. Omit to auto-select (works when there's exactly one project).\",\n },\n },\n },\n },\n {\n name: \"graph_agent_config\",\n description:\n \"Returns the graph-optimized agent configuration file for Claude Code. Save the returned content to .claude/agents/graph.md to enable the graph workflow agent.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {},\n },\n },\n {\n name: \"graph_knowledge_write\",\n description:\n \"Write a knowledge entry for a project. Creates or overwrites a named document. Use for persistent project-level knowledge (architecture decisions, conventions, API contracts) that outlives individual tasks.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n key: { type: \"string\", description: \"Knowledge entry key (e.g. 'auth', 'database-schema', 'api-contracts')\" },\n content: { type: \"string\", description: \"Free-form text content\" },\n },\n required: [\"project\", \"key\", \"content\"],\n },\n },\n {\n name: \"graph_knowledge_read\",\n description:\n \"Read knowledge entries for a project. Provide a key to read one entry, or omit to list all entries.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n key: { type: \"string\", description: \"Knowledge entry key. Omit to list all.\" },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"graph_knowledge_delete\",\n description:\n \"Delete a knowledge entry from a project.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n key: { type: \"string\", description: \"Knowledge entry key to delete\" },\n },\n required: [\"project\", \"key\"],\n },\n },\n {\n name: \"graph_knowledge_search\",\n description:\n \"Search knowledge entries by substring match on key or content.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n query: { type: \"string\", description: \"Search string\" },\n },\n required: [\"project\", \"query\"],\n },\n },\n];\n\nexport async function startServer(): Promise<void> {\n // Set database path — db is created lazily on first tool call\n setDbPath(DB_PATH);\n\n // [sl:N0IDVJQIhENQFsov6-Lhg] Resolve license tier once at startup (reads license file, doesn't touch db)\n const tier: Tier = getLicenseTier(DB_PATH);\n\n const server = new Server(\n { name: \"graph\", version: PKG_VERSION },\n { capabilities: { tools: {}, resources: {} } }\n );\n\n // Fire-and-forget version check (opt-in: GRAPH_UPDATE_CHECK=1)\n if (process.env.GRAPH_UPDATE_CHECK === \"1\") {\n checkForUpdate();\n }\n\n // List tools\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: TOOLS,\n }));\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n let result: unknown;\n\n switch (name) {\n case \"graph_open\": {\n const openArgs = args as any;\n // Gate: check project limit when creating a new project\n if (openArgs?.project) {\n const { getProjectRoot } = await import(\"./nodes.js\");\n if (!getProjectRoot(openArgs.project)) {\n checkProjectLimit(tier);\n }\n }\n result = handleOpen(openArgs, AGENT_IDENTITY);\n break;\n }\n\n case \"graph_plan\": {\n const planArgs = args as any;\n // Gate: check node limit before creating nodes\n if (planArgs?.nodes?.length > 0) {\n // Determine project from the first node's parent\n const { getNode } = await import(\"./nodes.js\");\n const firstParent = planArgs.nodes[0]?.parent_ref;\n if (firstParent && typeof firstParent === \"string\" && !planArgs.nodes.some((n: any) => n.ref === firstParent)) {\n const parentNode = getNode(firstParent);\n if (parentNode) {\n checkNodeLimit(tier, parentNode.project, planArgs.nodes.length);\n }\n }\n }\n result = handlePlan(planArgs, AGENT_IDENTITY);\n break;\n }\n\n case \"graph_next\": {\n const nextArgs = args as any;\n // Gate: strip scope on free tier\n if (nextArgs?.scope) {\n nextArgs.scope = checkScope(tier, nextArgs.scope);\n }\n result = handleNext(nextArgs, AGENT_IDENTITY, CLAIM_TTL);\n break;\n }\n\n case \"graph_context\":\n result = handleContext(args as any);\n break;\n\n case \"graph_update\":\n result = handleUpdate(args as any, AGENT_IDENTITY);\n break;\n\n case \"graph_connect\":\n result = handleConnect(args as any, AGENT_IDENTITY);\n break;\n\n case \"graph_query\":\n result = handleQuery(args as any);\n break;\n\n case \"graph_restructure\":\n result = handleRestructure(args as any, AGENT_IDENTITY);\n break;\n\n case \"graph_history\":\n result = handleHistory(args as any);\n break;\n\n case \"graph_onboard\": {\n const onboardArgs = args as any;\n // Gate: cap evidence limit on free tier\n onboardArgs.evidence_limit = capEvidenceLimit(tier, onboardArgs?.evidence_limit);\n result = handleOnboard(onboardArgs);\n break;\n }\n\n case \"graph_tree\":\n result = handleTree(args as any);\n break;\n\n case \"graph_status\":\n result = handleStatus(args as any);\n break;\n\n case \"graph_agent_config\":\n result = handleAgentConfig(PKG_VERSION);\n break;\n\n case \"graph_knowledge_write\":\n checkKnowledgeTier(tier);\n result = handleKnowledgeWrite(args as any, AGENT_IDENTITY);\n break;\n\n case \"graph_knowledge_read\":\n checkKnowledgeTier(tier);\n result = handleKnowledgeRead(args as any);\n break;\n\n case \"graph_knowledge_delete\":\n checkKnowledgeTier(tier);\n result = handleKnowledgeDelete(args as any);\n break;\n\n case \"graph_knowledge_search\":\n checkKnowledgeTier(tier);\n result = handleKnowledgeSearch(args as any);\n break;\n\n default:\n return {\n content: [\n { type: \"text\" as const, text: JSON.stringify({ error: `Unknown tool: ${name}` }) },\n ],\n isError: true,\n };\n }\n\n const content: Array<{ type: \"text\"; text: string }> = [\n { type: \"text\" as const, text: JSON.stringify(result, null, 2) },\n ];\n if (versionBanner) {\n const agentNote = checkAndUpdateAgentFile();\n const bannerParts = [versionBanner];\n if (agentNote) bannerParts.push(agentNote);\n if (updateWarning) bannerParts.push(updateWarning);\n content.push({ type: \"text\" as const, text: bannerParts.join(\"\\n\") });\n versionBanner = null;\n updateWarning = null;\n }\n return { content };\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n const code =\n error instanceof ValidationError\n ? \"validation_error\"\n : error instanceof EngineError\n ? (error as EngineError).code\n : \"error\";\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: message, code }),\n },\n ],\n isError: true,\n };\n }\n });\n\n // [sl:Ps3gCuzhMoQWK6tynsGA4] MCP resources — browsable read-only views of graph data\n\n // Resource templates (dynamic, parameterized URIs)\n server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({\n resourceTemplates: [\n {\n uriTemplate: \"graph://{project}/tree\",\n name: \"Project Tree\",\n description: \"Full task tree for a project with resolve status\",\n mimeType: \"application/json\",\n },\n {\n uriTemplate: \"graph://{project}/knowledge\",\n name: \"Project Knowledge\",\n description: \"All knowledge entries for a project\",\n mimeType: \"application/json\",\n },\n {\n uriTemplate: \"graph://{project}/knowledge/{key}\",\n name: \"Knowledge Entry\",\n description: \"A specific knowledge entry\",\n mimeType: \"application/json\",\n },\n ],\n }));\n\n // Static resource list (enumerate known projects)\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n try {\n const { listProjects } = await import(\"./nodes.js\");\n const projects = listProjects();\n const resources = projects.flatMap((p) => [\n {\n uri: `graph://${p.project}/tree`,\n name: `${p.project} — Tree`,\n description: `Task tree: ${p.total} nodes (${p.resolved} resolved)`,\n mimeType: \"application/json\",\n },\n {\n uri: `graph://${p.project}/knowledge`,\n name: `${p.project} — Knowledge`,\n description: `Knowledge entries for ${p.project}`,\n mimeType: \"application/json\",\n },\n ]);\n return { resources };\n } catch {\n return { resources: [] };\n }\n });\n\n // Read a specific resource\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const uri = request.params.uri;\n const match = uri.match(/^graph:\\/\\/([^/]+)\\/(.+)$/);\n if (!match) {\n throw new Error(`Invalid resource URI: ${uri}`);\n }\n\n const [, project, path] = match;\n\n if (path === \"tree\") {\n const result = handleTree({ project });\n return {\n contents: [{ uri, mimeType: \"application/json\", text: JSON.stringify(result, null, 2) }],\n };\n }\n\n if (path === \"knowledge\") {\n const result = handleKnowledgeRead({ project });\n return {\n contents: [{ uri, mimeType: \"application/json\", text: JSON.stringify(result, null, 2) }],\n };\n }\n\n const knowledgeMatch = path.match(/^knowledge\\/(.+)$/);\n if (knowledgeMatch) {\n const result = handleKnowledgeRead({ project, key: knowledgeMatch[1] });\n return {\n contents: [{ uri, mimeType: \"application/json\", text: JSON.stringify(result, null, 2) }],\n };\n }\n\n throw new Error(`Unknown resource path: ${path}`);\n });\n\n // Connect transport\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Periodic WAL checkpoint every 30s — flushes WAL data into main db file\n const checkpointInterval = setInterval(() => {\n try { checkpointDb(); } catch {}\n }, 30_000);\n\n // Cleanup on exit\n process.on(\"SIGINT\", () => {\n clearInterval(checkpointInterval);\n closeDb();\n process.exit(0);\n });\n process.on(\"SIGTERM\", () => {\n clearInterval(checkpointInterval);\n closeDb();\n process.exit(0);\n });\n}\n","import { createNode, getProjectRoot, listProjects, getProjectSummary } from \"../nodes.js\";\nimport { optionalString } from \"../validate.js\";\nimport type { Node } from \"../types.js\";\n\nexport interface OpenInput {\n project?: string;\n goal?: string;\n skip_discovery?: boolean;\n}\n\nexport type OpenResult =\n | {\n projects: Array<{\n project: string;\n id: string;\n summary: string;\n total: number;\n resolved: number;\n unresolved: number;\n updated_at: string;\n }>;\n }\n | {\n project: string;\n root: Node;\n summary: {\n total: number;\n resolved: number;\n unresolved: number;\n blocked: number;\n actionable: number;\n };\n hint?: string;\n };\n\nexport function handleOpen(input: OpenInput, agent: string): OpenResult {\n const project = optionalString(input?.project, \"project\");\n const goal = optionalString(input?.goal, \"goal\");\n\n if (!project) {\n return { projects: listProjects() };\n }\n\n let root = getProjectRoot(project);\n let isNew = false;\n\n if (!root) {\n root = createNode({\n project,\n summary: goal ?? project,\n discovery: input?.skip_discovery ? \"done\" : \"pending\",\n agent,\n });\n isNew = true;\n }\n\n const summary = getProjectSummary(project);\n\n const result: OpenResult = { project, root, summary };\n\n // Guide the agent on what to do next\n if (isNew && root.discovery === \"pending\") {\n result.hint = `New project created. Discovery is pending — interview the user to understand scope and goals, then set discovery to \"done\" via graph_update before decomposing with graph_plan.`;\n } else if (isNew) {\n result.hint = `New project created. Ready to decompose — use graph_plan to add tasks.`;\n } else if (root.discovery === \"pending\") {\n result.hint = `Discovery is still pending on this project. Complete the discovery interview, then set discovery to \"done\" via graph_update.`;\n } else if (summary.actionable > 0) {\n result.hint = `${summary.actionable} actionable task(s). Use graph_next to claim one.`;\n } else if (summary.unresolved > 0 && summary.actionable === 0) {\n result.hint = `All remaining tasks are blocked. Check dependencies with graph_query.`;\n }\n\n return result;\n}\n","import { nanoid } from \"nanoid\";\nimport { getDb } from \"./db.js\";\nimport { logEvent } from \"./events.js\";\nimport type { Edge } from \"./types.js\";\n\n// --- Cycle detection ---\n\nfunction wouldCreateCycle(from: string, to: string): boolean {\n // Adding edge \"from depends_on to\". Check if to can already reach from\n // through existing depends_on edges. If so, adding this edge creates a cycle.\n const db = getDb();\n const visited = new Set<string>();\n const stack = [to];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (current === from) return true;\n if (visited.has(current)) continue;\n visited.add(current);\n\n // Follow forward depends_on edges: what does current depend on?\n const deps = db\n .prepare(\n `SELECT to_node FROM edges WHERE from_node = ? AND type = 'depends_on'`\n )\n .all(current) as Array<{ to_node: string }>;\n\n for (const dep of deps) {\n stack.push(dep.to_node);\n }\n }\n\n return false;\n}\n\n// --- Add edge ---\n\nexport interface AddEdgeInput {\n from: string;\n to: string;\n type: string;\n agent: string;\n}\n\nexport interface AddEdgeResult {\n edge: Edge | null;\n rejected: boolean;\n reason?: string;\n}\n\nexport function addEdge(input: AddEdgeInput): AddEdgeResult {\n const db = getDb();\n\n // Check nodes exist\n const fromExists = db.prepare(\"SELECT id FROM nodes WHERE id = ?\").get(input.from);\n const toExists = db.prepare(\"SELECT id FROM nodes WHERE id = ?\").get(input.to);\n\n if (!fromExists) {\n return { edge: null, rejected: true, reason: \"node_not_found: \" + input.from };\n }\n if (!toExists) {\n return { edge: null, rejected: true, reason: \"node_not_found: \" + input.to };\n }\n\n // Check for duplicates\n const existing = db\n .prepare(\n \"SELECT id FROM edges WHERE from_node = ? AND to_node = ? AND type = ?\"\n )\n .get(input.from, input.to, input.type);\n\n if (existing) {\n return { edge: null, rejected: true, reason: \"duplicate_edge\" };\n }\n\n // Cycle detection for depends_on\n if (input.type === \"depends_on\") {\n if (wouldCreateCycle(input.from, input.to)) {\n return { edge: null, rejected: true, reason: \"cycle_detected\" };\n }\n }\n\n const edge: Edge = {\n id: nanoid(),\n from_node: input.from,\n to_node: input.to,\n type: input.type,\n created_at: new Date().toISOString(),\n };\n\n db.prepare(`\n INSERT INTO edges (id, from_node, to_node, type, created_at)\n VALUES (?, ?, ?, ?, ?)\n `).run(edge.id, edge.from_node, edge.to_node, edge.type, edge.created_at);\n\n logEvent(input.from, input.agent, \"edge_added\", [\n { field: \"edge\", before: null, after: { to: input.to, type: input.type } },\n ]);\n\n return { edge, rejected: false };\n}\n\n// --- Remove edge ---\n\nexport function removeEdge(\n from: string,\n to: string,\n type: string,\n agent: string\n): boolean {\n const db = getDb();\n\n const result = db\n .prepare(\n \"DELETE FROM edges WHERE from_node = ? AND to_node = ? AND type = ?\"\n )\n .run(from, to, type);\n\n if (result.changes > 0) {\n logEvent(from, agent, \"edge_removed\", [\n { field: \"edge\", before: { to, type }, after: null },\n ]);\n return true;\n }\n\n return false;\n}\n\n// --- Query edges ---\n\nexport function getEdgesFrom(nodeId: string, type?: string): Edge[] {\n const db = getDb();\n\n if (type) {\n return db\n .prepare(\"SELECT * FROM edges WHERE from_node = ? AND type = ?\")\n .all(nodeId, type) as Edge[];\n }\n\n return db\n .prepare(\"SELECT * FROM edges WHERE from_node = ?\")\n .all(nodeId) as Edge[];\n}\n\nexport function getEdgesTo(nodeId: string, type?: string): Edge[] {\n const db = getDb();\n\n if (type) {\n return db\n .prepare(\"SELECT * FROM edges WHERE to_node = ? AND type = ?\")\n .all(nodeId, type) as Edge[];\n }\n\n return db\n .prepare(\"SELECT * FROM edges WHERE to_node = ?\")\n .all(nodeId) as Edge[];\n}\n\n// [sl:uRocbNC_bArUXGr908Qbk] Find newly actionable nodes\n// Targeted: accepts resolved node IDs, checks only direct dependents.\n// Falls back to project-wide scan when no IDs provided.\n\nexport function findNewlyActionable(\n project: string,\n resolvedNodeIds?: string[]\n): Array<{ id: string; summary: string }> {\n const db = getDb();\n\n if (resolvedNodeIds && resolvedNodeIds.length > 0) {\n // Targeted: only check direct dependents of the resolved nodes + children of resolved nodes\n const placeholders = resolvedNodeIds.map(() => \"?\").join(\",\");\n const rows = db\n .prepare(\n `SELECT DISTINCT n.id, n.summary FROM nodes n\n WHERE n.resolved = 0 AND n.project = ?\n AND (\n -- nodes that had a depends_on edge to one of the resolved nodes\n n.id IN (\n SELECT e.from_node FROM edges e\n WHERE e.type = 'depends_on' AND e.to_node IN (${placeholders})\n )\n OR\n -- parents of resolved nodes (might now be leaf if all children resolved)\n n.id IN (SELECT parent FROM nodes WHERE id IN (${placeholders}) AND parent IS NOT NULL)\n )\n -- is a leaf (no unresolved children)\n AND NOT EXISTS (\n SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0\n )\n -- all deps resolved\n AND NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )`\n )\n .all(project, ...resolvedNodeIds, ...resolvedNodeIds) as Array<{\n id: string;\n summary: string;\n }>;\n\n return rows;\n }\n\n // Fallback: project-wide scan\n const rows = db\n .prepare(\n `SELECT n.id, n.summary FROM nodes n\n WHERE n.project = ? AND n.resolved = 0\n AND NOT EXISTS (\n SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0\n )\n AND NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )`\n )\n .all(project) as Array<{ id: string; summary: string }>;\n\n return rows;\n}\n","import { getDb } from \"../db.js\";\nimport { createNode, getNode } from \"../nodes.js\";\nimport { addEdge } from \"../edges.js\";\nimport { requireArray, requireString, EngineError } from \"../validate.js\";\n\nexport interface PlanNodeInput {\n ref: string;\n parent_ref?: string;\n summary: string;\n context_links?: string[];\n depends_on?: string[];\n properties?: Record<string, unknown>;\n}\n\nexport interface PlanInput {\n nodes: PlanNodeInput[];\n}\n\nexport interface PlanResult {\n created: Array<{ ref: string; id: string }>;\n}\n\nexport function handlePlan(input: PlanInput, agent: string): PlanResult {\n const db = getDb();\n const nodes = requireArray<PlanNodeInput>(input?.nodes, \"nodes\");\n\n // Validate each node has required fields\n for (let i = 0; i < nodes.length; i++) {\n const n = nodes[i];\n requireString(n.ref, `nodes[${i}].ref`);\n requireString(n.summary, `nodes[${i}].summary`);\n }\n\n // Ref -> real ID mapping\n const refMap = new Map<string, string>();\n const created: Array<{ ref: string; id: string }> = [];\n\n // Validate refs are unique\n const refs = new Set<string>();\n for (const node of nodes) {\n if (refs.has(node.ref)) {\n throw new EngineError(\"duplicate_ref\", `Duplicate ref in batch: ${node.ref}`);\n }\n refs.add(node.ref);\n }\n\n // Run atomically\n const transaction = db.transaction(() => {\n // First pass: create all nodes\n for (const nodeInput of nodes) {\n // Resolve parent\n let parentId: string | undefined;\n if (nodeInput.parent_ref) {\n // Check if it's a batch ref or existing node ID\n parentId = refMap.get(nodeInput.parent_ref);\n if (!parentId) {\n // Try as existing node ID\n const existing = getNode(nodeInput.parent_ref);\n if (existing) {\n parentId = existing.id;\n } else {\n throw new EngineError(\n \"invalid_parent_ref\",\n `parent_ref \"${nodeInput.parent_ref}\" is neither a batch ref nor an existing node ID`\n );\n }\n }\n }\n\n // Determine project from parent or require first node to have a parent\n let project: string;\n if (parentId) {\n const parentNode = getNode(parentId)!;\n // [sl:m3_UNy-eICtHeHExfHwUH] Block decomposition when node has pending discovery\n if (parentNode.discovery === \"pending\") {\n throw new EngineError(\n \"discovery_pending\",\n `Cannot add children to \"${parentNode.summary}\" (${parentId}) — discovery is pending. Run: graph_update({ updates: [{ node_id: \"${parentId}\", discovery: \"done\" }] }) after completing discovery, then decompose.`\n );\n }\n project = parentNode.project;\n } else {\n // If no parent, the node must be a root. But we need a project.\n // Infer from first node that has a parent, or error.\n throw new EngineError(\n \"missing_parent\",\n `Node \"${nodeInput.ref}\" has no parent_ref. All planned nodes must have a parent (an existing node or a batch ref).`\n );\n }\n\n const node = createNode({\n project,\n parent: parentId,\n summary: nodeInput.summary,\n context_links: nodeInput.context_links,\n properties: nodeInput.properties,\n agent,\n });\n\n refMap.set(nodeInput.ref, node.id);\n created.push({ ref: nodeInput.ref, id: node.id });\n }\n\n // Second pass: create dependency edges\n for (const nodeInput of nodes) {\n if (!nodeInput.depends_on || nodeInput.depends_on.length === 0) continue;\n\n const fromId = refMap.get(nodeInput.ref)!;\n\n for (const dep of nodeInput.depends_on) {\n // Resolve dep: batch ref or existing node ID\n let toId = refMap.get(dep);\n if (!toId) {\n const existing = getNode(dep);\n if (existing) {\n toId = existing.id;\n } else {\n throw new EngineError(\n \"invalid_depends_on\",\n `depends_on \"${dep}\" in node \"${nodeInput.ref}\" is neither a batch ref nor an existing node ID`\n );\n }\n }\n\n const result = addEdge({\n from: fromId,\n to: toId,\n type: \"depends_on\",\n agent,\n });\n\n if (result.rejected) {\n throw new EngineError(\n \"edge_rejected\",\n `Dependency edge from \"${nodeInput.ref}\" to \"${dep}\" rejected: ${result.reason}`\n );\n }\n }\n }\n });\n\n transaction();\n\n return { created };\n}\n","import { updateNode, getNode, getNodeOrThrow, getChildren } from \"../nodes.js\";\nimport { findNewlyActionable } from \"../edges.js\";\nimport { requireArray, requireString, EngineError } from \"../validate.js\";\n\nexport interface UpdateEntry {\n node_id: string;\n expected_rev?: number;\n resolved?: boolean;\n resolved_reason?: string; // [sl:QBEtldx8PBWACftEM8MYl] Shorthand — auto-creates note evidence\n discovery?: string | null;\n blocked?: boolean;\n blocked_reason?: string | null;\n state?: unknown;\n summary?: string;\n properties?: Record<string, unknown>;\n add_context_links?: string[];\n remove_context_links?: string[];\n add_evidence?: Array<{ type: string; ref: string }>;\n}\n\nexport interface UpdateInput {\n updates: UpdateEntry[];\n}\n\nexport interface UpdateResult {\n updated: Array<{ node_id: string; rev: number }>;\n newly_actionable?: Array<{ id: string; summary: string }>;\n auto_resolved?: Array<{ node_id: string; summary: string }>;\n}\n\nexport function handleUpdate(input: UpdateInput, agent: string): UpdateResult {\n const updates = requireArray<UpdateEntry>(input?.updates, \"updates\");\n\n for (let i = 0; i < updates.length; i++) {\n requireString(updates[i].node_id, `updates[${i}].node_id`);\n if (updates[i].add_evidence) {\n for (let j = 0; j < updates[i].add_evidence!.length; j++) {\n requireString(updates[i].add_evidence![j].type, `updates[${i}].add_evidence[${j}].type`);\n requireString(updates[i].add_evidence![j].ref, `updates[${i}].add_evidence[${j}].ref`);\n }\n }\n }\n\n const updated: Array<{ node_id: string; rev: number }> = [];\n const resolvedIds: string[] = [];\n const resolvedProjects = new Set<string>();\n\n for (const entry of updates) {\n // Optimistic concurrency: reject if rev doesn't match\n if (entry.expected_rev !== undefined) {\n const current = getNodeOrThrow(entry.node_id);\n if (current.rev !== entry.expected_rev) {\n throw new EngineError(\n \"rev_mismatch\",\n `Node ${entry.node_id} has rev ${current.rev}, expected ${entry.expected_rev}. Another agent may have modified it. Re-read and retry.`\n );\n }\n }\n\n // Expand resolved_reason shorthand into evidence\n let evidence = entry.add_evidence;\n if (entry.resolved_reason) {\n evidence = [...(evidence ?? []), { type: \"note\", ref: entry.resolved_reason }];\n }\n\n const node = updateNode({\n node_id: entry.node_id,\n agent,\n resolved: entry.resolved,\n discovery: entry.discovery,\n blocked: entry.blocked,\n blocked_reason: entry.blocked_reason,\n state: entry.state,\n summary: entry.summary,\n properties: entry.properties,\n add_context_links: entry.add_context_links,\n remove_context_links: entry.remove_context_links,\n add_evidence: evidence,\n });\n\n updated.push({ node_id: node.id, rev: node.rev });\n\n if (entry.resolved === true) {\n resolvedIds.push(node.id);\n resolvedProjects.add(node.project);\n }\n }\n\n // [sl:GBuFbmTFuFfnl5KWW-ja-] Auto-resolve parents when all children are resolved\n const autoResolved: Array<{ node_id: string; summary: string }> = [];\n if (resolvedIds.length > 0) {\n const seen = new Set<string>(resolvedIds);\n const queue = [...resolvedIds];\n\n while (queue.length > 0) {\n const nodeId = queue.shift()!;\n const node = getNode(nodeId);\n if (!node?.parent) continue;\n\n const parentId = node.parent;\n if (seen.has(parentId)) continue;\n seen.add(parentId);\n\n const parent = getNode(parentId);\n if (!parent || parent.resolved) continue;\n\n const children = getChildren(parentId);\n if (children.length === 0) continue;\n if (children.every((c) => c.resolved)) {\n const resolved = updateNode({\n node_id: parentId,\n agent,\n resolved: true,\n add_evidence: [{ type: \"note\", ref: \"Auto-resolved: all children completed\" }],\n });\n updated.push({ node_id: resolved.id, rev: resolved.rev });\n resolvedIds.push(parentId);\n autoResolved.push({ node_id: parentId, summary: parent.summary });\n queue.push(parentId);\n }\n }\n }\n\n const result: UpdateResult = { updated };\n\n if (resolvedIds.length > 0 && resolvedProjects.size > 0) {\n const allActionable: Array<{ id: string; summary: string }> = [];\n for (const proj of resolvedProjects) {\n allActionable.push(...findNewlyActionable(proj, resolvedIds));\n }\n result.newly_actionable = allActionable;\n }\n\n if (autoResolved.length > 0) {\n result.auto_resolved = autoResolved;\n }\n\n return result;\n}\n","import { addEdge, removeEdge } from \"../edges.js\";\nimport { requireArray, requireString } from \"../validate.js\";\n\nexport interface ConnectEdgeInput {\n from: string;\n to: string;\n type: string;\n remove?: boolean;\n}\n\nexport interface ConnectInput {\n edges: ConnectEdgeInput[];\n}\n\nexport interface ConnectResult {\n applied: number;\n rejected?: Array<{ from: string; to: string; reason: string }>;\n}\n\nexport function handleConnect(input: ConnectInput, agent: string): ConnectResult {\n const edges = requireArray<ConnectEdgeInput>(input?.edges, \"edges\");\n\n for (let i = 0; i < edges.length; i++) {\n requireString(edges[i].from, `edges[${i}].from`);\n requireString(edges[i].to, `edges[${i}].to`);\n requireString(edges[i].type, `edges[${i}].type`);\n }\n\n let applied = 0;\n const rejected: Array<{ from: string; to: string; reason: string }> = [];\n\n for (const edge of edges) {\n if (edge.type === \"parent\") {\n rejected.push({\n from: edge.from,\n to: edge.to,\n reason: \"parent_edges_not_allowed: use graph_restructure to reparent\",\n });\n continue;\n }\n\n if (edge.remove) {\n const removed = removeEdge(edge.from, edge.to, edge.type, agent);\n if (removed) {\n applied++;\n } else {\n rejected.push({\n from: edge.from,\n to: edge.to,\n reason: \"edge_not_found\",\n });\n }\n } else {\n const result = addEdge({\n from: edge.from,\n to: edge.to,\n type: edge.type,\n agent,\n });\n\n if (result.rejected) {\n rejected.push({\n from: edge.from,\n to: edge.to,\n reason: result.reason!,\n });\n } else {\n applied++;\n }\n }\n }\n\n const result: ConnectResult = { applied };\n if (rejected.length > 0) {\n result.rejected = rejected;\n }\n return result;\n}\n","import { getNodeOrThrow, getChildren, getAncestors, getSubtreeProgress } from \"../nodes.js\";\nimport { getEdgesFrom, getEdgesTo } from \"../edges.js\";\nimport { getNode } from \"../nodes.js\";\nimport { requireString, optionalNumber } from \"../validate.js\";\nimport type { Node } from \"../types.js\";\n\nexport interface ContextInput {\n node_id: string;\n depth?: number;\n}\n\ninterface NodeTree {\n id: string;\n summary: string;\n resolved: boolean;\n discovery: string | null;\n state: unknown;\n progress?: { resolved: number; total: number };\n children?: NodeTree[];\n child_count?: number;\n}\n\nexport interface ContextResult {\n node: Node;\n ancestors: Array<{ id: string; summary: string; resolved: boolean }>;\n children: NodeTree;\n depends_on: Array<{ node: Node; satisfied: boolean }>;\n depended_by: Array<{ node: Node; satisfied: boolean }>;\n}\n\nfunction buildNodeTree(nodeId: string, currentDepth: number, maxDepth: number): NodeTree {\n const node = getNodeOrThrow(nodeId);\n const children = getChildren(nodeId);\n\n const tree: NodeTree = {\n id: node.id,\n summary: node.summary,\n resolved: node.resolved,\n discovery: node.discovery,\n state: node.state,\n };\n\n if (children.length === 0) {\n return tree;\n }\n\n tree.progress = getSubtreeProgress(nodeId);\n\n if (currentDepth < maxDepth) {\n tree.children = children.map((child) =>\n buildNodeTree(child.id, currentDepth + 1, maxDepth)\n );\n } else {\n tree.child_count = children.length;\n }\n\n return tree;\n}\n\nexport function handleContext(input: ContextInput): ContextResult {\n const nodeId = requireString(input?.node_id, \"node_id\");\n const depth = optionalNumber(input?.depth, \"depth\", 0, 10) ?? 2;\n const node = getNodeOrThrow(nodeId);\n const ancestors = getAncestors(nodeId);\n\n // Build children tree\n const children = buildNodeTree(nodeId, 0, depth);\n\n // Get dependency edges\n const depsOut = getEdgesFrom(nodeId, \"depends_on\");\n const depsIn = getEdgesTo(nodeId, \"depends_on\");\n\n const depends_on = depsOut.map((edge) => {\n const target = getNode(edge.to_node);\n return {\n node: target!,\n satisfied: target?.resolved ?? false,\n };\n });\n\n const depended_by = depsIn.map((edge) => {\n const source = getNode(edge.from_node);\n return {\n node: source!,\n satisfied: node.resolved,\n };\n });\n\n return { node, ancestors, children, depends_on, depended_by };\n}\n","import { getDb } from \"../db.js\";\nimport { requireString, optionalNumber, optionalString } from \"../validate.js\";\nimport type { NodeRow } from \"../types.js\";\n\nexport interface QueryFilter {\n resolved?: boolean;\n properties?: Record<string, unknown>;\n text?: string;\n ancestor?: string;\n has_evidence_type?: string;\n is_leaf?: boolean;\n is_actionable?: boolean;\n is_blocked?: boolean;\n claimed_by?: string | null;\n}\n\nexport interface QueryInput {\n project: string;\n filter?: QueryFilter;\n sort?: \"readiness\" | \"depth\" | \"recent\" | \"created\";\n limit?: number;\n cursor?: string;\n}\n\nexport interface QueryResultNode {\n id: string;\n summary: string;\n resolved: boolean;\n state: unknown;\n parent: string | null;\n depth: number;\n properties: Record<string, unknown>;\n}\n\nexport interface QueryResult {\n nodes: QueryResultNode[];\n total: number;\n next_cursor?: string;\n}\n\n// [sl:tfMDHhmJSXd5TPgwD2ZC6] Descendant lookup via recursive CTE (replaced JS BFS)\nfunction getDescendantIds(nodeId: string): string[] {\n const db = getDb();\n const rows = db\n .prepare(\n `WITH RECURSIVE descendants(id) AS (\n SELECT id FROM nodes WHERE parent = ?\n UNION ALL\n SELECT n.id FROM nodes n JOIN descendants d ON n.parent = d.id\n )\n SELECT id FROM descendants`\n )\n .all(nodeId) as Array<{ id: string }>;\n\n return rows.map((r) => r.id);\n}\n\n\nexport function handleQuery(input: QueryInput): QueryResult {\n const project = requireString(input?.project, \"project\");\n const db = getDb();\n const limit = Math.min(optionalNumber(input?.limit, \"limit\", 1, 100) ?? 20, 100);\n const filter = input?.filter;\n const cursor = optionalString(input?.cursor, \"cursor\");\n\n // Build WHERE clauses\n const conditions: string[] = [\"n.project = ?\"];\n const params: unknown[] = [project];\n\n if (filter?.resolved !== undefined) {\n conditions.push(\"n.resolved = ?\");\n params.push(filter.resolved ? 1 : 0);\n }\n\n if (filter?.text) {\n conditions.push(\"n.summary LIKE ?\");\n params.push(`%${filter.text}%`);\n }\n\n if (filter?.ancestor) {\n const descendantIds = getDescendantIds(filter.ancestor);\n if (descendantIds.length === 0) {\n return { nodes: [], total: 0 };\n }\n conditions.push(`n.id IN (${descendantIds.map(() => \"?\").join(\",\")})`);\n params.push(...descendantIds);\n }\n\n if (filter?.has_evidence_type) {\n conditions.push(\n `EXISTS (SELECT 1 FROM json_each(n.evidence) WHERE json_extract(value, '$.type') = ?)`\n );\n params.push(filter.has_evidence_type);\n }\n\n if (filter?.is_leaf) {\n conditions.push(\n \"NOT EXISTS (SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0)\"\n );\n }\n\n if (filter?.is_actionable) {\n conditions.push(\"n.resolved = 0\");\n conditions.push(\"n.blocked = 0\");\n conditions.push(\n \"NOT EXISTS (SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0)\"\n );\n conditions.push(\n `NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )`\n );\n }\n\n if (filter?.is_blocked) {\n conditions.push(\"n.resolved = 0\");\n conditions.push(\n `(n.blocked = 1 OR EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n ))`\n );\n }\n\n if (filter?.properties) {\n for (const [key, value] of Object.entries(filter.properties)) {\n conditions.push(\"json_extract(n.properties, ?) = ?\");\n params.push(`$.${key}`, value as string | number);\n }\n }\n\n if (filter?.claimed_by !== undefined) {\n if (filter.claimed_by === null) {\n conditions.push(\n \"(json_extract(n.properties, '$._claimed_by') IS NULL)\"\n );\n } else {\n conditions.push(\"json_extract(n.properties, '$._claimed_by') = ?\");\n params.push(filter.claimed_by);\n }\n }\n\n // Cursor: use created_at + id for stable pagination\n if (cursor) {\n const [cursorTime, cursorId] = cursor.split(\"|\");\n conditions.push(\"(n.created_at > ? OR (n.created_at = ? AND n.id > ?))\");\n params.push(cursorTime, cursorTime, cursorId);\n }\n\n const whereClause = conditions.join(\" AND \");\n\n // Sorting\n let orderBy: string;\n switch (input.sort) {\n case \"depth\":\n // Can't sort by computed depth in SQL easily, so sort by created and compute depth post-hoc\n orderBy = \"n.created_at ASC, n.id ASC\";\n break;\n case \"recent\":\n orderBy = \"n.updated_at DESC, n.id ASC\";\n break;\n case \"created\":\n orderBy = \"n.created_at ASC, n.id ASC\";\n break;\n case \"readiness\":\n default:\n orderBy = \"n.updated_at ASC, n.id ASC\";\n break;\n }\n\n // Count total\n // Count total (without cursor filter)\n const countConditions = cursor ? conditions.slice(0, -1) : conditions;\n const countParams = cursor ? params.slice(0, -3) : [...params];\n const total = (\n db.prepare(`SELECT COUNT(*) as count FROM nodes n WHERE ${countConditions.join(\" AND \")}`).get(...countParams) as { count: number }\n ).count;\n\n // Fetch\n params.push(limit + 1);\n const query = `SELECT * FROM nodes n WHERE ${whereClause} ORDER BY ${orderBy} LIMIT ?`;\n const rows = db.prepare(query).all(...params) as NodeRow[];\n\n const hasMore = rows.length > limit;\n const slice = hasMore ? rows.slice(0, limit) : rows;\n\n const nodes: QueryResultNode[] = slice.map((row) => ({\n id: row.id,\n summary: row.summary,\n resolved: row.resolved === 1,\n state: row.state ? JSON.parse(row.state) : null,\n parent: row.parent,\n depth: row.depth,\n properties: JSON.parse(row.properties),\n }));\n\n const result: QueryResult = { nodes, total };\n\n if (hasMore) {\n const last = slice[slice.length - 1];\n result.next_cursor = `${last.created_at}|${last.id}`;\n }\n\n return result;\n}\n","import { getDb } from \"../db.js\";\nimport { getNode, getAncestors, updateNode } from \"../nodes.js\";\nimport { getEdgesFrom } from \"../edges.js\";\nimport { requireString, optionalString, optionalNumber, optionalBoolean } from \"../validate.js\";\nimport type { Node, NodeRow, Evidence } from \"../types.js\";\n\nexport interface NextInput {\n project: string;\n scope?: string;\n filter?: Record<string, unknown>;\n count?: number;\n claim?: boolean;\n}\n\nexport interface NextResultNode {\n node: Node;\n ancestors: Array<{ id: string; summary: string }>;\n context_links: {\n self: string[];\n inherited: Array<{ node_id: string; links: string[] }>;\n };\n resolved_deps: Array<{\n id: string;\n summary: string;\n evidence: Evidence[];\n }>;\n}\n\nexport interface ClaimedTask {\n id: string;\n summary: string;\n claimed_at: string;\n}\n\nexport interface NextResult {\n nodes: NextResultNode[];\n your_claims?: ClaimedTask[];\n}\n\nexport function handleNext(\n input: NextInput,\n agent: string,\n claimTtlMinutes: number = 60\n): NextResult {\n const project = requireString(input?.project, \"project\");\n const scope = optionalString(input?.scope, \"scope\");\n const count = optionalNumber(input?.count, \"count\", 1, 50) ?? 1;\n const claim = optionalBoolean(input?.claim, \"claim\") ?? false;\n const db = getDb();\n\n // [sl:HB5daFH1HlFXzuTluibnk] Scope filtering: restrict to descendants of a given node\n let scopeFilter = \"\";\n const scopeParams: unknown[] = [];\n if (scope) {\n const descendantIds = db\n .prepare(\n `WITH RECURSIVE descendants(id) AS (\n SELECT id FROM nodes WHERE parent = ?\n UNION ALL\n SELECT n.id FROM nodes n JOIN descendants d ON n.parent = d.id\n )\n SELECT id FROM descendants`\n )\n .all(scope) as Array<{ id: string }>;\n\n if (descendantIds.length === 0) {\n return { nodes: [] };\n }\n scopeFilter = `AND n.id IN (${descendantIds.map(() => \"?\").join(\",\")})`;\n scopeParams.push(...descendantIds.map((d) => d.id));\n }\n\n // Find actionable nodes: unresolved, not blocked, leaf (no unresolved children), all deps resolved\n let query = `\n SELECT n.* FROM nodes n\n WHERE n.project = ? AND n.resolved = 0 AND n.blocked = 0\n ${scopeFilter}\n AND NOT EXISTS (\n SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0\n )\n AND NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )\n `;\n\n const params: unknown[] = [project, ...scopeParams];\n\n // Skip nodes claimed by other agents (if claim TTL hasn't expired)\n const claimCutoff = new Date(\n Date.now() - claimTtlMinutes * 60 * 1000\n ).toISOString();\n\n query += `\n AND (\n json_extract(n.properties, '$._claimed_by') IS NULL\n OR json_extract(n.properties, '$._claimed_by') = ?\n OR json_extract(n.properties, '$._claimed_at') <= ?\n )\n `;\n params.push(agent, claimCutoff);\n\n // Property filters\n if (input.filter) {\n for (const [key, value] of Object.entries(input.filter)) {\n query += \" AND json_extract(n.properties, ?) = ?\";\n params.push(`$.${key}`, value as string | number);\n }\n }\n\n // [sl:md48WyMYFlOf4KP99vmtv] Ranking fully in SQL — never loads more than N rows\n // Depth is cached on the node, priority extracted via json_extract\n query += `\n ORDER BY\n COALESCE(CAST(json_extract(n.properties, '$.priority') AS REAL), 0) DESC,\n n.depth DESC,\n n.updated_at ASC\n LIMIT ?\n `;\n params.push(count);\n\n const rows = db.prepare(query).all(...params) as NodeRow[];\n\n const selected = rows.map((row) => ({ row }));\n\n const results: NextResultNode[] = selected.map(({ row }) => {\n const node = getNode(row.id)!;\n const ancestors = getAncestors(row.id);\n\n // Context links: self + inherited from ancestors\n const inherited: Array<{ node_id: string; links: string[] }> = [];\n for (const anc of ancestors) {\n const ancNode = getNode(anc.id);\n if (ancNode && ancNode.context_links.length > 0) {\n inherited.push({ node_id: anc.id, links: ancNode.context_links });\n }\n }\n\n // Resolved dependencies\n const depEdges = getEdgesFrom(row.id, \"depends_on\");\n const resolved_deps = depEdges\n .map((edge) => {\n const depNode = getNode(edge.to_node);\n if (!depNode || !depNode.resolved) return null;\n return {\n id: depNode.id,\n summary: depNode.summary,\n evidence: depNode.evidence,\n };\n })\n .filter(Boolean) as NextResultNode[\"resolved_deps\"];\n\n // Claim if requested\n if (claim) {\n updateNode({\n node_id: node.id,\n agent,\n properties: {\n _claimed_by: agent,\n _claimed_at: new Date().toISOString(),\n },\n });\n }\n\n return {\n node: claim ? getNode(row.id)! : node,\n ancestors: ancestors.map((a) => ({ id: a.id, summary: a.summary })),\n context_links: {\n self: node.context_links,\n inherited,\n },\n resolved_deps,\n };\n });\n\n // Surface caller's existing claims (unexpired) so they can resume or release them\n const claimRows = db\n .prepare(\n `SELECT id, summary, json_extract(properties, '$._claimed_at') as claimed_at\n FROM nodes\n WHERE project = ? AND resolved = 0\n AND json_extract(properties, '$._claimed_by') = ?\n AND json_extract(properties, '$._claimed_at') > ?\n ORDER BY json_extract(properties, '$._claimed_at') DESC`\n )\n .all(project, agent, claimCutoff) as Array<{ id: string; summary: string; claimed_at: string }>;\n\n const result: NextResult = { nodes: results };\n if (claimRows.length > 0) {\n result.your_claims = claimRows.map((r) => ({\n id: r.id,\n summary: r.summary,\n claimed_at: r.claimed_at,\n }));\n }\n\n return result;\n}\n","import { getDb } from \"../db.js\";\nimport { getNodeOrThrow, getNode, getChildren, updateNode } from \"../nodes.js\";\nimport { getEdgesFrom, getEdgesTo, findNewlyActionable } from \"../edges.js\";\nimport { logEvent } from \"../events.js\";\nimport { requireArray, requireString, EngineError } from \"../validate.js\";\nimport type { Evidence } from \"../types.js\";\n\nexport interface MoveOp {\n op: \"move\";\n node_id: string;\n new_parent: string;\n}\n\nexport interface MergeOp {\n op: \"merge\";\n source: string;\n target: string;\n}\n\nexport interface DropOp {\n op: \"drop\";\n node_id: string;\n reason: string;\n}\n\nexport interface DeleteOp {\n op: \"delete\";\n node_id: string;\n}\n\nexport type RestructureOp = MoveOp | MergeOp | DropOp | DeleteOp;\n\nexport interface RestructureInput {\n operations: RestructureOp[];\n}\n\nexport interface RestructureResult {\n applied: number;\n details: Array<{ op: string; node_id: string; result: string }>;\n newly_actionable?: Array<{ id: string; summary: string }>;\n}\n\nfunction wouldCreateParentCycle(nodeId: string, newParentId: string): boolean {\n // Check if newParentId is a descendant of nodeId (which would create a cycle)\n const db = getDb();\n let current: string | null = newParentId;\n\n while (current) {\n if (current === nodeId) return true;\n const row = db\n .prepare(\"SELECT parent FROM nodes WHERE id = ?\")\n .get(current) as { parent: string | null } | undefined;\n current = row?.parent ?? null;\n }\n\n return false;\n}\n\nfunction getAllDescendants(nodeId: string): string[] {\n const ids: string[] = [];\n const stack = [nodeId];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n const children = getChildren(current);\n for (const child of children) {\n ids.push(child.id);\n stack.push(child.id);\n }\n }\n\n return ids;\n}\n\nfunction recomputeSubtreeDepth(nodeId: string, newDepth: number): void {\n const db = getDb();\n db.prepare(\"UPDATE nodes SET depth = ? WHERE id = ?\").run(newDepth, nodeId);\n const children = db.prepare(\"SELECT id FROM nodes WHERE parent = ?\").all(nodeId) as Array<{ id: string }>;\n for (const child of children) {\n recomputeSubtreeDepth(child.id, newDepth + 1);\n }\n}\n\nfunction handleMove(op: MoveOp, agent: string): { node_id: string; result: string } {\n const db = getDb();\n const node = getNodeOrThrow(op.node_id);\n const newParent = getNodeOrThrow(op.new_parent);\n\n if (node.project !== newParent.project) {\n throw new EngineError(\"cross_project\", `Cannot move node across projects: \"${node.project}\" → \"${newParent.project}\"`);\n }\n\n if (wouldCreateParentCycle(op.node_id, op.new_parent)) {\n throw new EngineError(\n \"cycle_detected\",\n `Move would create cycle: ${op.node_id} cannot be moved under ${op.new_parent}`\n );\n }\n\n const oldParent = node.parent;\n const now = new Date().toISOString();\n db.prepare(\"UPDATE nodes SET parent = ?, updated_at = ? WHERE id = ?\").run(\n op.new_parent,\n now,\n op.node_id\n );\n\n // Recompute depth for moved node and all descendants\n recomputeSubtreeDepth(op.node_id, newParent.depth + 1);\n\n logEvent(op.node_id, agent, \"moved\", [\n { field: \"parent\", before: oldParent, after: op.new_parent },\n ]);\n\n return { node_id: op.node_id, result: `moved under ${op.new_parent}` };\n}\n\nfunction handleMerge(op: MergeOp, agent: string): { node_id: string; result: string } {\n const db = getDb();\n const source = getNodeOrThrow(op.source);\n const target = getNodeOrThrow(op.target);\n\n if (source.project !== target.project) {\n throw new EngineError(\"cross_project\", `Cannot merge nodes across projects: \"${source.project}\" → \"${target.project}\"`);\n }\n\n // Move source's children to target and recompute their depths\n const movedChildren = db.prepare(\"SELECT id FROM nodes WHERE parent = ?\").all(op.source) as Array<{ id: string }>;\n db.prepare(\"UPDATE nodes SET parent = ?, updated_at = ? WHERE parent = ?\").run(\n op.target,\n new Date().toISOString(),\n op.source\n );\n for (const child of movedChildren) {\n recomputeSubtreeDepth(child.id, target.depth + 1);\n }\n\n // Append source's evidence to target\n const targetEvidence: Evidence[] = [...target.evidence, ...source.evidence];\n db.prepare(\"UPDATE nodes SET evidence = ?, updated_at = ? WHERE id = ?\").run(\n JSON.stringify(targetEvidence),\n new Date().toISOString(),\n op.target\n );\n\n // Transfer source's dependency edges to target\n const sourceOutEdges = getEdgesFrom(op.source);\n const sourceInEdges = getEdgesTo(op.source);\n\n for (const edge of sourceOutEdges) {\n // source depends_on X -> target depends_on X\n const existing = db\n .prepare(\n \"SELECT id FROM edges WHERE from_node = ? AND to_node = ? AND type = ?\"\n )\n .get(op.target, edge.to_node, edge.type);\n\n if (!existing) {\n db.prepare(\n \"UPDATE edges SET from_node = ? WHERE id = ?\"\n ).run(op.target, edge.id);\n } else {\n db.prepare(\"DELETE FROM edges WHERE id = ?\").run(edge.id);\n }\n }\n\n for (const edge of sourceInEdges) {\n // X depends_on source -> X depends_on target\n const existing = db\n .prepare(\n \"SELECT id FROM edges WHERE from_node = ? AND to_node = ? AND type = ?\"\n )\n .get(edge.from_node, op.target, edge.type);\n\n if (!existing) {\n db.prepare(\n \"UPDATE edges SET to_node = ? WHERE id = ?\"\n ).run(op.target, edge.id);\n } else {\n db.prepare(\"DELETE FROM edges WHERE id = ?\").run(edge.id);\n }\n }\n\n // Log merge on target (source will be deleted)\n logEvent(op.target, agent, \"merged\", [\n { field: \"merged_from\", before: null, after: op.source },\n ]);\n\n // Delete source: events, edges, then node (FK order)\n db.prepare(\"DELETE FROM events WHERE node_id = ?\").run(op.source);\n db.prepare(\"DELETE FROM edges WHERE from_node = ? OR to_node = ?\").run(\n op.source,\n op.source\n );\n db.prepare(\"DELETE FROM nodes WHERE id = ?\").run(op.source);\n\n return { node_id: op.target, result: `merged ${op.source} into ${op.target}` };\n}\n\nfunction handleDrop(op: DropOp, agent: string): { node_id: string; result: string } {\n const now = new Date().toISOString();\n\n // Get all descendants\n const descendants = getAllDescendants(op.node_id);\n const allIds = [op.node_id, ...descendants];\n\n // Mark all as resolved with evidence\n for (const id of allIds) {\n const node = getNode(id);\n if (!node || node.resolved) continue;\n\n updateNode({\n node_id: id,\n agent,\n resolved: true,\n add_evidence: [{ type: \"dropped\", ref: op.reason }],\n });\n\n logEvent(id, agent, \"dropped\", [\n { field: \"resolved\", before: false, after: true },\n { field: \"reason\", before: null, after: op.reason },\n ]);\n }\n\n return {\n node_id: op.node_id,\n result: `dropped ${allIds.length} node(s): ${op.reason}`,\n };\n}\n\nfunction handleDelete(op: DeleteOp, agent: string): { node_id: string; result: string } {\n const db = getDb();\n const node = getNodeOrThrow(op.node_id);\n\n // Guard: prevent deleting project roots that have evidence (preserves traceability)\n if (node.parent === null) {\n const evidenceCount = db.prepare(\n `SELECT COUNT(*) as cnt FROM nodes\n WHERE project = ? AND evidence != '[]'`\n ).get(node.project) as { cnt: number };\n\n if (evidenceCount.cnt > 0) {\n throw new EngineError(\n \"delete_protected\",\n `Cannot delete project \"${node.project}\" — it contains ${evidenceCount.cnt} node(s) with evidence. Resolved projects preserve traceability across sessions. Use \"drop\" to mark as resolved instead.`\n );\n }\n }\n\n const descendants = getAllDescendants(op.node_id);\n const allIds = [op.node_id, ...descendants];\n const placeholders = allIds.map(() => \"?\").join(\",\");\n\n // Delete events, edges, then nodes (FK order)\n db.prepare(`DELETE FROM events WHERE node_id IN (${placeholders})`).run(...allIds);\n db.prepare(`DELETE FROM edges WHERE from_node IN (${placeholders}) OR to_node IN (${placeholders})`).run(...allIds, ...allIds);\n db.prepare(`DELETE FROM nodes WHERE id IN (${placeholders})`).run(...allIds);\n\n return {\n node_id: op.node_id,\n result: `deleted ${allIds.length} node(s)`,\n };\n}\n\nexport function handleRestructure(\n input: RestructureInput,\n agent: string\n): RestructureResult {\n const operations = requireArray<RestructureOp>(input?.operations, \"operations\");\n\n for (let i = 0; i < operations.length; i++) {\n const op = operations[i];\n requireString(op.op, `operations[${i}].op`);\n if (op.op === \"move\") {\n requireString((op as MoveOp).node_id, `operations[${i}].node_id`);\n requireString((op as MoveOp).new_parent, `operations[${i}].new_parent`);\n } else if (op.op === \"merge\") {\n requireString((op as MergeOp).source, `operations[${i}].source`);\n requireString((op as MergeOp).target, `operations[${i}].target`);\n } else if (op.op === \"drop\") {\n requireString((op as DropOp).node_id, `operations[${i}].node_id`);\n requireString((op as DropOp).reason, `operations[${i}].reason`);\n } else if (op.op === \"delete\") {\n requireString((op as DeleteOp).node_id, `operations[${i}].node_id`);\n } else {\n throw new EngineError(\"unknown_op\", `Unknown operation: ${op.op}`);\n }\n }\n\n const db = getDb();\n let applied = 0;\n const details: Array<{ op: string; node_id: string; result: string }> = [];\n let project: string | null = null;\n\n const transaction = db.transaction(() => {\n for (const op of operations) {\n let detail: { node_id: string; result: string };\n\n switch (op.op) {\n case \"move\":\n detail = handleMove(op, agent);\n project = getNode(op.node_id)?.project ?? project;\n break;\n case \"merge\":\n detail = handleMerge(op, agent);\n project = getNode(op.target)?.project ?? project;\n break;\n case \"drop\":\n detail = handleDrop(op, agent);\n project = getNode(op.node_id)?.project ?? project;\n break;\n case \"delete\":\n project = getNode(op.node_id)?.project ?? project;\n detail = handleDelete(op, agent);\n break;\n default:\n throw new Error(`Unknown operation: ${(op as RestructureOp).op}`);\n }\n\n details.push({ op: op.op, ...detail });\n applied++;\n }\n });\n\n transaction();\n\n const result: RestructureResult = { applied, details };\n\n if (project) {\n const actionable = findNewlyActionable(project);\n if (actionable.length > 0) {\n result.newly_actionable = actionable;\n }\n }\n\n return result;\n}\n","import { getEvents } from \"../events.js\";\nimport { getNodeOrThrow } from \"../nodes.js\";\nimport { requireString, optionalNumber, optionalString } from \"../validate.js\";\n\nexport interface HistoryInput {\n node_id: string;\n limit?: number;\n cursor?: string;\n}\n\nexport interface HistoryResult {\n events: Array<{\n timestamp: string;\n agent: string;\n action: string;\n changes: Array<{ field: string; before: unknown; after: unknown }>;\n }>;\n next_cursor?: string;\n}\n\nexport function handleHistory(input: HistoryInput): HistoryResult {\n const nodeId = requireString(input?.node_id, \"node_id\");\n const limit = optionalNumber(input?.limit, \"limit\", 1, 100) ?? 20;\n const cursor = optionalString(input?.cursor, \"cursor\");\n\n getNodeOrThrow(nodeId);\n\n const { events, next_cursor } = getEvents(nodeId, limit, cursor);\n\n const result: HistoryResult = {\n events: events.map((e) => ({\n timestamp: e.timestamp,\n agent: e.agent,\n action: e.action,\n changes: e.changes,\n })),\n };\n\n if (next_cursor) {\n result.next_cursor = next_cursor;\n }\n\n return result;\n}\n","// [sl:v4-uJ6Q28R-pGRPrGOav6] Continuity confidence signal — graph quality metric\n\nimport { getDb } from \"./db.js\";\n\nexport interface ContinuityConfidence {\n confidence: \"high\" | \"medium\" | \"low\";\n score: number; // 0-100\n reasons: string[];\n}\n\ninterface ProjectStats {\n resolvedCount: number;\n resolvedWithEvidence: number;\n lastActivity: string | null;\n knowledgeCount: number;\n staleBlockedCount: number;\n totalNonRoot: number;\n}\n\nfunction getProjectStats(project: string): ProjectStats {\n const db = getDb();\n\n // Count resolved tasks (exclude root)\n const resolved = db.prepare(\n \"SELECT COUNT(*) as cnt FROM nodes WHERE project = ? AND parent IS NOT NULL AND resolved = 1\"\n ).get(project) as { cnt: number };\n\n // Count resolved tasks with evidence\n const withEvidence = db.prepare(\n \"SELECT COUNT(*) as cnt FROM nodes WHERE project = ? AND parent IS NOT NULL AND resolved = 1 AND evidence != '[]'\"\n ).get(project) as { cnt: number };\n\n // Last activity\n const lastAct = db.prepare(\n \"SELECT MAX(updated_at) as last FROM nodes WHERE project = ?\"\n ).get(project) as { last: string | null };\n\n // Knowledge count\n const knowledge = db.prepare(\n \"SELECT COUNT(*) as cnt FROM knowledge WHERE project = ?\"\n ).get(project) as { cnt: number };\n\n // Stale blocked items (blocked for 7+ days with no update)\n const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();\n const staleBlocked = db.prepare(\n \"SELECT COUNT(*) as cnt FROM nodes WHERE project = ? AND blocked = 1 AND updated_at < ?\"\n ).get(project, sevenDaysAgo) as { cnt: number };\n\n // Total non-root nodes\n const total = db.prepare(\n \"SELECT COUNT(*) as cnt FROM nodes WHERE project = ? AND parent IS NOT NULL\"\n ).get(project) as { cnt: number };\n\n return {\n resolvedCount: resolved.cnt,\n resolvedWithEvidence: withEvidence.cnt,\n lastActivity: lastAct.last,\n knowledgeCount: knowledge.cnt,\n staleBlockedCount: staleBlocked.cnt,\n totalNonRoot: total.cnt,\n };\n}\n\nexport function computeContinuityConfidence(project: string): ContinuityConfidence {\n const stats = getProjectStats(project);\n const reasons: string[] = [];\n let score = 100;\n\n // 1. Evidence coverage (biggest factor — 40 points)\n if (stats.resolvedCount > 0) {\n const coverage = stats.resolvedWithEvidence / stats.resolvedCount;\n const missing = stats.resolvedCount - stats.resolvedWithEvidence;\n if (coverage < 0.5) {\n score -= 40;\n reasons.push(`${missing} of ${stats.resolvedCount} resolved tasks have no evidence`);\n } else if (coverage < 0.8) {\n score -= 20;\n reasons.push(`${missing} of ${stats.resolvedCount} resolved tasks have no evidence`);\n } else if (coverage < 1.0) {\n score -= 10;\n reasons.push(`${missing} resolved task(s) missing evidence`);\n }\n }\n\n // 2. Staleness (25 points)\n if (stats.lastActivity) {\n const ageMs = Date.now() - new Date(stats.lastActivity).getTime();\n const ageDays = ageMs / (24 * 60 * 60 * 1000);\n if (ageDays > 14) {\n score -= 25;\n reasons.push(`No activity for ${Math.floor(ageDays)} days`);\n } else if (ageDays > 7) {\n score -= 15;\n reasons.push(`No activity for ${Math.floor(ageDays)} days`);\n } else if (ageDays > 3) {\n score -= 5;\n reasons.push(`Last activity ${Math.floor(ageDays)} days ago`);\n }\n }\n\n // 3. Knowledge (15 points) — only flag on mature projects (5+ resolved tasks)\n if (stats.resolvedCount >= 5 && stats.knowledgeCount === 0) {\n score -= 15;\n reasons.push(\"No knowledge entries on a project with 5+ resolved tasks\");\n }\n\n // 4. Stale blockers (10 points)\n if (stats.staleBlockedCount > 0) {\n score -= 10;\n reasons.push(`${stats.staleBlockedCount} blocked item(s) not updated in 7+ days`);\n }\n\n // 5. Empty project — no tasks yet (10 points)\n if (stats.totalNonRoot === 0) {\n score -= 10;\n reasons.push(\"Project has no tasks yet\");\n }\n\n // Clamp\n score = Math.max(0, Math.min(100, score));\n\n // Map to band\n let confidence: ContinuityConfidence[\"confidence\"];\n if (score >= 70) {\n confidence = \"high\";\n } else if (score >= 40) {\n confidence = \"medium\";\n } else {\n confidence = \"low\";\n }\n\n return { confidence, score, reasons };\n}\n","import { getDb } from \"../db.js\";\nimport { getProjectRoot, getProjectSummary, listProjects } from \"../nodes.js\";\nimport { optionalString, optionalNumber } from \"../validate.js\";\nimport { EngineError } from \"../validate.js\";\nimport { computeContinuityConfidence, type ContinuityConfidence } from \"../continuity.js\";\nimport type { NodeRow, Evidence } from \"../types.js\";\n\n// [sl:yosc4NuV6j43Zv0fsDXDj] graph_onboard — single-call orientation for new agents\n\nexport interface OnboardInput {\n project?: string;\n evidence_limit?: number;\n}\n\nexport interface OnboardResult {\n project: string;\n goal: string;\n discovery: string | null;\n hint?: string;\n summary: {\n total: number;\n resolved: number;\n unresolved: number;\n blocked: number;\n actionable: number;\n };\n tree: Array<{\n id: string;\n summary: string;\n resolved: boolean;\n blocked: boolean;\n blocked_reason: string | null;\n children: Array<{\n id: string;\n summary: string;\n resolved: boolean;\n blocked: boolean;\n blocked_reason: string | null;\n child_count: number;\n }>;\n }>;\n recent_evidence: Array<{\n node_id: string;\n node_summary: string;\n type: string;\n ref: string;\n agent: string;\n timestamp: string;\n }>;\n context_links: string[];\n knowledge: Array<{\n key: string;\n content: string;\n updated_at: string;\n }>;\n recently_resolved: Array<{\n id: string;\n summary: string;\n resolved_at: string;\n agent: string;\n }>;\n last_activity: string | null;\n continuity_confidence: ContinuityConfidence;\n actionable: Array<{\n id: string;\n summary: string;\n properties: Record<string, unknown>;\n }>;\n}\n\n// [sl:1pRRsWFomcv04XAkdLMAj] Allow graph_onboard without project name\nexport function handleOnboard(input: OnboardInput): OnboardResult | { projects: ReturnType<typeof listProjects>; hint: string } {\n const evidenceLimit = optionalNumber(input?.evidence_limit, \"evidence_limit\", 1, 50) ?? 20;\n const db = getDb();\n\n // Auto-resolve project when not specified\n let project = optionalString(input?.project, \"project\");\n if (!project) {\n const projects = listProjects();\n if (projects.length === 0) {\n return {\n projects: [],\n hint: \"No projects yet. Create one with graph_open({ project: \\\"my-project\\\", goal: \\\"...\\\" }).\",\n };\n }\n if (projects.length === 1) {\n project = projects[0].project;\n } else {\n return {\n projects,\n hint: `${projects.length} projects found. Call graph_onboard with a specific project name.`,\n };\n }\n }\n\n // Verify project exists\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"project_not_found\", `Project not found: ${project}`);\n }\n\n // 1. Project summary counts\n const summary = getProjectSummary(project);\n\n // 2. Tree structure — root's children + their children (depth 1-2)\n const topChildren = db\n .prepare(\"SELECT * FROM nodes WHERE parent = ? ORDER BY created_at ASC\")\n .all(root.id) as NodeRow[];\n\n const tree = topChildren.map((child) => {\n const grandchildren = db\n .prepare(\n `SELECT id, summary, resolved, blocked, blocked_reason,\n (SELECT COUNT(*) FROM nodes gc WHERE gc.parent = n.id) as child_count\n FROM nodes n WHERE parent = ? ORDER BY created_at ASC`\n )\n .all(child.id) as Array<{\n id: string;\n summary: string;\n resolved: number;\n blocked: number;\n blocked_reason: string | null;\n child_count: number;\n }>;\n\n return {\n id: child.id,\n summary: child.summary,\n resolved: child.resolved === 1,\n discovery: child.discovery,\n blocked: child.blocked === 1,\n blocked_reason: child.blocked_reason,\n children: grandchildren.map((gc) => ({\n id: gc.id,\n summary: gc.summary,\n resolved: gc.resolved === 1,\n blocked: gc.blocked === 1,\n blocked_reason: gc.blocked_reason,\n child_count: gc.child_count,\n })),\n };\n });\n\n // 3. Recent evidence across all resolved nodes, sorted by timestamp\n const allNodes = db\n .prepare(\"SELECT id, summary, evidence FROM nodes WHERE project = ? AND resolved = 1 AND evidence != '[]'\")\n .all(project) as Array<{ id: string; summary: string; evidence: string }>;\n\n const allEvidence: OnboardResult[\"recent_evidence\"] = [];\n for (const node of allNodes) {\n const evidence: Evidence[] = JSON.parse(node.evidence);\n for (const ev of evidence) {\n allEvidence.push({\n node_id: node.id,\n node_summary: node.summary,\n type: ev.type,\n ref: ev.ref,\n agent: ev.agent,\n timestamp: ev.timestamp,\n });\n }\n }\n allEvidence.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n const recent_evidence = allEvidence.slice(0, evidenceLimit);\n\n // 4. All context_links aggregated and deduplicated\n const linkRows = db\n .prepare(\"SELECT context_links FROM nodes WHERE project = ? AND context_links != '[]'\")\n .all(project) as Array<{ context_links: string }>;\n\n const linkSet = new Set<string>();\n for (const row of linkRows) {\n const links: string[] = JSON.parse(row.context_links);\n for (const link of links) {\n linkSet.add(link);\n }\n }\n const context_links = [...linkSet].sort();\n\n // 5. Knowledge entries\n const knowledgeRows = db\n .prepare(\"SELECT key, content, updated_at FROM knowledge WHERE project = ? ORDER BY updated_at DESC\")\n .all(project) as Array<{ key: string; content: string; updated_at: string }>;\n\n // 6. Actionable tasks preview (like graph_next without claiming)\n const actionableRows = db\n .prepare(\n `SELECT n.id, n.summary, n.properties FROM nodes n\n WHERE n.project = ? AND n.resolved = 0 AND n.blocked = 0\n AND NOT EXISTS (\n SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0\n )\n AND NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )\n ORDER BY\n COALESCE(CAST(json_extract(n.properties, '$.priority') AS REAL), 0) DESC,\n n.depth DESC,\n n.updated_at ASC\n LIMIT 10`\n )\n .all(project) as Array<{ id: string; summary: string; properties: string }>;\n\n const actionable = actionableRows.map((row) => ({\n id: row.id,\n summary: row.summary,\n properties: JSON.parse(row.properties),\n }));\n\n // 7. Recently resolved nodes (last 24h) — cross-session continuity\n const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();\n const recentlyResolvedRows = db\n .prepare(\n `SELECT id, summary, updated_at,\n (SELECT json_extract(value, '$.agent') FROM json_each(evidence) ORDER BY json_extract(value, '$.timestamp') DESC LIMIT 1) as last_agent\n FROM nodes\n WHERE project = ? AND resolved = 1 AND updated_at > ?\n ORDER BY updated_at DESC\n LIMIT 10`\n )\n .all(project, oneDayAgo) as Array<{ id: string; summary: string; updated_at: string; last_agent: string | null }>;\n\n const recently_resolved = recentlyResolvedRows.map((row) => ({\n id: row.id,\n summary: row.summary,\n resolved_at: row.updated_at,\n agent: row.last_agent ?? \"unknown\",\n }));\n\n // 8. Last activity timestamp\n const lastActivityRow = db\n .prepare(\"SELECT MAX(updated_at) as last FROM nodes WHERE project = ?\")\n .get(project) as { last: string | null };\n const last_activity = lastActivityRow.last;\n\n // Build hint based on project state\n let hint: string | undefined;\n if (root.discovery === \"pending\") {\n hint = `Discovery is pending. Interview the user to understand scope and goals, write knowledge entries with findings, then set discovery to \"done\" via graph_update before decomposing with graph_plan.`;\n } else if (actionable.length > 0) {\n const recentNote = recently_resolved.length > 0\n ? ` ${recently_resolved.length} task(s) resolved recently.`\n : \"\";\n hint = `${actionable.length} actionable task(s) ready.${recentNote} Use graph_next({ project: \"${project}\", claim: true }) to claim one.`;\n } else if (summary.unresolved > 0 && summary.actionable === 0) {\n hint = `All remaining tasks are blocked. Check dependencies with graph_query.`;\n } else if (summary.total <= 1 && root.discovery !== \"pending\") {\n hint = `Project is empty — use graph_plan to decompose the goal into tasks.`;\n }\n\n // 9. Continuity confidence signal\n const continuity_confidence = computeContinuityConfidence(project);\n\n return {\n project,\n goal: root.summary,\n discovery: root.discovery,\n hint,\n summary,\n tree,\n recent_evidence,\n context_links,\n knowledge: knowledgeRows,\n recently_resolved,\n last_activity,\n continuity_confidence,\n actionable,\n };\n}\n","import { getProjectRoot, getChildren, getSubtreeProgress } from \"../nodes.js\";\nimport { requireString, optionalNumber } from \"../validate.js\";\nimport { EngineError } from \"../validate.js\";\nimport type { Node } from \"../types.js\";\n\n// [sl:ahq-BLHS9pJkJUlBZO92L] Full tree visualization — \"show me the whole tree\"\n\nexport interface TreeInput {\n project: string;\n depth?: number;\n}\n\ninterface TreeNode {\n id: string;\n summary: string;\n resolved: boolean;\n properties: Record<string, unknown>;\n progress?: { resolved: number; total: number };\n children?: TreeNode[];\n child_count?: number;\n}\n\nexport interface TreeResult {\n project: string;\n tree: TreeNode;\n stats: {\n total: number;\n resolved: number;\n unresolved: number;\n };\n}\n\nfunction buildTree(\n node: Node,\n currentDepth: number,\n maxDepth: number,\n stats: { total: number; resolved: number }\n): { treeNode: TreeNode; subtotal: number; subresolved: number } {\n stats.total++;\n if (node.resolved) stats.resolved++;\n\n const children = getChildren(node.id);\n const treeNode: TreeNode = {\n id: node.id,\n summary: node.summary,\n resolved: node.resolved,\n properties: node.properties,\n };\n\n let subtotal = 1;\n let subresolved = node.resolved ? 1 : 0;\n\n if (children.length === 0) return { treeNode, subtotal, subresolved };\n\n if (currentDepth < maxDepth) {\n treeNode.children = [];\n for (const child of children) {\n const result = buildTree(child, currentDepth + 1, maxDepth, stats);\n treeNode.children.push(result.treeNode);\n subtotal += result.subtotal;\n subresolved += result.subresolved;\n }\n } else {\n treeNode.child_count = children.length;\n // Count descendants via SQL when truncating at depth limit\n const progress = getSubtreeProgress(node.id);\n subtotal = progress.total;\n subresolved = progress.resolved;\n }\n\n treeNode.progress = { resolved: subresolved, total: subtotal };\n return { treeNode, subtotal, subresolved };\n}\n\nexport function handleTree(input: TreeInput): TreeResult {\n const project = requireString(input?.project, \"project\");\n const depth = optionalNumber(input?.depth, \"depth\", 1, 20) ?? 10;\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"project_not_found\", `Project not found: ${project}`);\n }\n\n const stats = { total: 0, resolved: 0 };\n const { treeNode } = buildTree(root, 0, depth, stats);\n\n return {\n project,\n tree: treeNode,\n stats: {\n total: stats.total,\n resolved: stats.resolved,\n unresolved: stats.total - stats.resolved,\n },\n };\n}\n","import { getDb } from \"../db.js\";\nimport { getProjectRoot, getProjectSummary, listProjects } from \"../nodes.js\";\nimport { optionalString } from \"../validate.js\";\nimport { EngineError } from \"../validate.js\";\nimport { computeContinuityConfidence } from \"../continuity.js\";\nimport type { NodeRow, Evidence } from \"../types.js\";\n\nexport interface StatusInput {\n project?: string;\n}\n\nexport interface StatusResult {\n formatted: string;\n project: string;\n}\n\ninterface TreeEntry {\n id: string;\n parent: string | null;\n summary: string;\n resolved: boolean;\n blocked: boolean;\n blocked_reason: string | null;\n depth: number;\n child_count: number;\n dep_blocked: boolean;\n resolved_children: number;\n total_children: number;\n}\n\nfunction statusIcon(entry: TreeEntry): string {\n if (entry.resolved) return \"x\";\n if (entry.blocked) return \"!\";\n if (entry.dep_blocked) return \"~\";\n return \" \";\n}\n\nfunction progressBar(resolved: number, total: number, width: number = 20): string {\n if (total === 0) return \"\";\n const clamped = Math.min(resolved, total);\n const filled = Math.round((clamped / total) * width);\n const empty = width - filled;\n const bar = \"\\u2588\".repeat(filled) + \"\\u2591\".repeat(empty);\n const pct = Math.round((resolved / total) * 100);\n return `${bar} ${resolved}/${total} (${pct}%)`;\n}\n\nfunction timeAgo(isoDate: string): string {\n const diff = Date.now() - new Date(isoDate).getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n if (days === 1) return \"yesterday\";\n return `${days}d ago`;\n}\n\nexport function handleStatus(input: StatusInput): StatusResult | { projects: ReturnType<typeof listProjects>; hint: string } {\n const db = getDb();\n\n let project = optionalString(input?.project, \"project\");\n if (!project) {\n const projects = listProjects();\n if (projects.length === 0) {\n return {\n projects: [],\n hint: \"No projects yet. Create one with graph_open({ project: \\\"my-project\\\", goal: \\\"...\\\" }).\",\n };\n }\n if (projects.length === 1) {\n project = projects[0].project;\n } else {\n const lines: string[] = [\"# All Projects\", \"\"];\n for (const p of projects) {\n const taskCount = p.total > 0 ? p.total - 1 : 0; // exclude root\n const resolvedTasks = Math.min(p.resolved, taskCount);\n const bar = taskCount > 0 ? progressBar(resolvedTasks, taskCount) : \"empty\";\n lines.push(`**${p.project}** ${bar}`);\n lines.push(` ${p.summary}`);\n lines.push(\"\");\n }\n lines.push(\"_Specify a project name for details._\");\n return { projects, hint: lines.join(\"\\n\") };\n }\n }\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"project_not_found\", `Project not found: ${project}`);\n }\n\n const summary = getProjectSummary(project);\n\n // Get all non-root nodes with subtree counts and dependency info\n const rows = db.prepare(\n `SELECT n.id, n.parent, n.summary, n.resolved, n.blocked, n.blocked_reason, n.depth,\n (SELECT COUNT(*) FROM nodes c WHERE c.parent = n.id) as child_count,\n (SELECT COUNT(*) FROM nodes c WHERE c.parent = n.id AND c.resolved = 1) as resolved_children,\n (SELECT COUNT(*) FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on') as unresolved_deps\n FROM nodes n\n WHERE n.project = ? AND n.parent IS NOT NULL\n ORDER BY n.depth ASC, n.created_at ASC`\n ).all(project) as Array<{\n id: string;\n parent: string | null;\n summary: string;\n resolved: number;\n blocked: number;\n blocked_reason: string | null;\n depth: number;\n child_count: number;\n resolved_children: number;\n unresolved_deps: number;\n }>;\n\n const entries: TreeEntry[] = rows.map(r => ({\n id: r.id,\n parent: r.parent,\n summary: r.summary,\n resolved: r.resolved === 1,\n blocked: r.blocked === 1,\n blocked_reason: r.blocked_reason,\n depth: r.depth - 1, // relative to root\n child_count: r.child_count,\n dep_blocked: r.unresolved_deps > 0,\n resolved_children: r.resolved_children,\n total_children: r.child_count,\n }));\n\n // Build formatted output\n const lines: string[] = [];\n const taskCount = summary.total - 1; // exclude root\n\n // Header with progress bar\n lines.push(`# ${project}`);\n lines.push(\"\");\n lines.push(root.summary);\n lines.push(\"\");\n const resolvedTasks = Math.min(summary.resolved, taskCount);\n if (taskCount > 0) {\n lines.push(progressBar(resolvedTasks, taskCount));\n // Continuity confidence signal\n const cc = computeContinuityConfidence(project);\n const ccBars = Math.ceil(cc.score / 20); // 0-5 filled blocks\n const ccDisplay = \"\\u25a0\".repeat(ccBars) + \"\\u25a1\".repeat(5 - ccBars);\n lines.push(`${summary.actionable} actionable | ${summary.blocked} blocked | ${summary.unresolved - summary.blocked - summary.actionable} waiting | continuity confidence: ${cc.confidence} ${ccDisplay}`);\n if (cc.reasons.length > 0 && cc.confidence !== \"high\") {\n for (const reason of cc.reasons) {\n lines.push(` - ${reason}`);\n }\n }\n } else {\n lines.push(\"No tasks yet\");\n }\n lines.push(\"\");\n\n // Task tree with indentation and inline progress for parents\n if (entries.length > 0) {\n lines.push(\"## Tasks\");\n lines.push(\"\");\n for (const entry of entries) {\n const icon = statusIcon(entry);\n const prefix = \" \".repeat(entry.depth);\n let line = `${prefix}[${icon}] ${entry.summary}`;\n\n // Inline progress for parent nodes\n if (entry.child_count > 0) {\n const pct = Math.round((entry.resolved_children / entry.total_children) * 100);\n line += ` (${entry.resolved_children}/${entry.total_children} — ${pct}%)`;\n }\n\n // Blocked reason inline\n if (entry.blocked && entry.blocked_reason) {\n line += `\\n${prefix} ^ ${entry.blocked_reason}`;\n }\n\n lines.push(line);\n }\n lines.push(\"\");\n }\n\n // Recent activity — last 5 events across the project\n const recentEvents = db.prepare(\n `SELECT e.node_id, e.agent, e.action, e.timestamp, n.summary as node_summary\n FROM events e\n JOIN nodes n ON n.id = e.node_id\n WHERE n.project = ?\n ORDER BY e.timestamp DESC\n LIMIT 5`\n ).all(project) as Array<{\n node_id: string;\n agent: string;\n action: string;\n timestamp: string;\n node_summary: string;\n }>;\n\n if (recentEvents.length > 0) {\n lines.push(\"## Recent Activity\");\n lines.push(\"\");\n for (const ev of recentEvents) {\n lines.push(`- ${ev.action} **${ev.node_summary}** (${ev.agent}, ${timeAgo(ev.timestamp)})`);\n }\n lines.push(\"\");\n }\n\n // Blocked items\n const blocked = entries.filter(e => e.blocked && e.blocked_reason);\n if (blocked.length > 0) {\n lines.push(\"## Blocked\");\n lines.push(\"\");\n for (const b of blocked) {\n lines.push(`- **${b.summary}** — ${b.blocked_reason}`);\n }\n lines.push(\"\");\n }\n\n // Knowledge entries\n const knowledge = db.prepare(\n \"SELECT key, updated_at FROM knowledge WHERE project = ? ORDER BY updated_at DESC\"\n ).all(project) as Array<{ key: string; updated_at: string }>;\n if (knowledge.length > 0) {\n lines.push(\"## Knowledge\");\n lines.push(\"\");\n for (const k of knowledge) {\n lines.push(`- ${k.key} (${timeAgo(k.updated_at)})`);\n }\n lines.push(\"\");\n }\n\n return {\n formatted: lines.join(\"\\n\").trimEnd(),\n project,\n };\n}\n","import { nanoid } from \"nanoid\";\nimport { getDb } from \"../db.js\";\nimport { getProjectRoot } from \"../nodes.js\";\nimport { EngineError, requireString } from \"../validate.js\";\n\n// [sl:4PrMkE09nf6ptz8LLR9rW] Knowledge tools — persistent project-level knowledge store\n\ninterface KnowledgeRow {\n id: string;\n project: string;\n key: string;\n content: string;\n created_by: string;\n created_at: string;\n updated_at: string;\n}\n\n// --- graph_knowledge_write ---\n\nexport interface KnowledgeWriteInput {\n project: string;\n key: string;\n content: string;\n}\n\nexport function handleKnowledgeWrite(input: KnowledgeWriteInput, agent: string) {\n const project = requireString(input.project, \"project\");\n const key = requireString(input.key, \"key\");\n const content = requireString(input.content, \"content\");\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"not_found\", `Project '${project}' not found`);\n }\n\n const db = getDb();\n const now = new Date().toISOString();\n\n const existing = db\n .prepare(\"SELECT id FROM knowledge WHERE project = ? AND key = ?\")\n .get(project, key) as { id: string } | undefined;\n\n if (existing) {\n db.prepare(\n \"UPDATE knowledge SET content = ?, updated_at = ? WHERE id = ?\"\n ).run(content, now, existing.id);\n return { key, action: \"updated\" };\n } else {\n const id = nanoid();\n db.prepare(\n \"INSERT INTO knowledge (id, project, key, content, created_by, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)\"\n ).run(id, project, key, content, agent, now, now);\n return { key, action: \"created\" };\n }\n}\n\n// --- graph_knowledge_read ---\n\nexport interface KnowledgeReadInput {\n project: string;\n key?: string;\n}\n\nexport function handleKnowledgeRead(input: KnowledgeReadInput) {\n const project = requireString(input.project, \"project\");\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"not_found\", `Project '${project}' not found`);\n }\n\n const db = getDb();\n\n if (input.key) {\n const row = db\n .prepare(\"SELECT * FROM knowledge WHERE project = ? AND key = ?\")\n .get(project, input.key) as KnowledgeRow | undefined;\n\n if (!row) {\n throw new EngineError(\"not_found\", `Knowledge entry '${input.key}' not found in project '${project}'`);\n }\n\n return {\n key: row.key,\n content: row.content,\n updated_at: row.updated_at,\n created_by: row.created_by,\n };\n }\n\n // List all\n const rows = db\n .prepare(\"SELECT key, content, updated_at, created_by FROM knowledge WHERE project = ? ORDER BY updated_at DESC\")\n .all(project) as Array<{ key: string; content: string; updated_at: string; created_by: string }>;\n\n return { entries: rows };\n}\n\n// --- graph_knowledge_delete ---\n\nexport interface KnowledgeDeleteInput {\n project: string;\n key: string;\n}\n\nexport function handleKnowledgeDelete(input: KnowledgeDeleteInput) {\n const project = requireString(input.project, \"project\");\n const key = requireString(input.key, \"key\");\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"not_found\", `Project '${project}' not found`);\n }\n\n const db = getDb();\n const result = db\n .prepare(\"DELETE FROM knowledge WHERE project = ? AND key = ?\")\n .run(project, key);\n\n if (result.changes === 0) {\n throw new EngineError(\"not_found\", `Knowledge entry '${key}' not found in project '${project}'`);\n }\n\n return { key, action: \"deleted\" };\n}\n\n// --- graph_knowledge_search ---\n\nexport interface KnowledgeSearchInput {\n project: string;\n query: string;\n}\n\nexport function handleKnowledgeSearch(input: KnowledgeSearchInput) {\n const project = requireString(input.project, \"project\");\n const query = requireString(input.query, \"query\");\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"not_found\", `Project '${project}' not found`);\n }\n\n const db = getDb();\n const pattern = `%${query}%`;\n\n const rows = db\n .prepare(\n \"SELECT key, content, updated_at, created_by FROM knowledge WHERE project = ? AND (key LIKE ? OR content LIKE ?) ORDER BY updated_at DESC\"\n )\n .all(project, pattern, pattern) as Array<{ key: string; content: string; updated_at: string; created_by: string }>;\n\n return { entries: rows, query };\n}\n","import { getDb } from \"./db.js\";\nimport { EngineError } from \"./validate.js\";\nimport type { Tier } from \"./license.js\";\n\n// [sl:N0IDVJQIhENQFsov6-Lhg] Feature gates — enforce free vs pro limits\n\n// Limits relaxed — everything free while building user base (Phase 1: Acquisition)\nconst FREE_LIMITS = {\n maxProjects: Infinity,\n maxNodesPerProject: Infinity,\n onboardEvidenceLimit: 50,\n scopeEnabled: true,\n};\n\n/**\n * Check if creating nodes would exceed the free tier node limit.\n * Throws EngineError if limit would be exceeded.\n */\nexport function checkNodeLimit(tier: Tier, project: string, adding: number): void {\n if (tier === \"pro\") return;\n\n const db = getDb();\n const { count } = db\n .prepare(\"SELECT COUNT(*) as count FROM nodes WHERE project = ?\")\n .get(project) as { count: number };\n\n if (count + adding > FREE_LIMITS.maxNodesPerProject) {\n throw new EngineError(\n \"free_tier_limit\",\n `Free tier is limited to ${FREE_LIMITS.maxNodesPerProject} nodes per project. ` +\n `Current: ${count}, adding: ${adding}. Activate a license key to remove this limit.`\n );\n }\n}\n\n/**\n * Check if creating a new project would exceed the free tier project limit.\n * Throws EngineError if limit would be exceeded.\n */\nexport function checkProjectLimit(tier: Tier): void {\n if (tier === \"pro\") return;\n\n const db = getDb();\n const { count } = db\n .prepare(\"SELECT COUNT(*) as count FROM nodes WHERE parent IS NULL\")\n .get() as { count: number };\n\n if (count >= FREE_LIMITS.maxProjects) {\n throw new EngineError(\n \"free_tier_limit\",\n `Free tier is limited to ${FREE_LIMITS.maxProjects} project. ` +\n `Activate a license key to create unlimited projects.`\n );\n }\n}\n\n/**\n * Cap the evidence limit for graph_onboard on free tier.\n */\nexport function capEvidenceLimit(tier: Tier, requested?: number): number {\n const max = tier === \"pro\" ? (requested ?? 20) : FREE_LIMITS.onboardEvidenceLimit;\n return Math.min(requested ?? max, tier === \"pro\" ? 50 : FREE_LIMITS.onboardEvidenceLimit);\n}\n\n/**\n * Check if knowledge tools are allowed on the current tier.\n * Currently free for all — everything ungated during acquisition phase.\n */\nexport function checkKnowledgeTier(_tier: Tier): void {\n // All tiers allowed during acquisition phase\n return;\n}\n\n/**\n * Check if scope parameter is allowed.\n * Currently free for all during acquisition phase.\n */\nexport function checkScope(_tier: Tier, scope?: string): string | undefined {\n return scope;\n}\n"],"mappings":"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","names":["rows","result","lines","taskCount","resolvedTasks","nanoid","nanoid","getProjectRoot","getNode","listProjects"]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tools/agent-config.ts"],"sourcesContent":["// [sl:fV9I7Vel3xT5d_Ws2YHul] Subagent delivery — free for all (retention hook)\n\nfunction agentPrompt(version: string): string {\n return `---\nname: graph\nversion: ${version}\ndescription: Use this agent for tasks tracked in Graph. Enforces the claim-work-resolve workflow — always checks graph_next before working, adds new work to the graph before executing, and resolves with evidence.\ntools: Read, Edit, Write, Bash, Glob, Grep, Task(Explore), AskUserQuestion\nmodel: sonnet\n---\n\nYou are a graph-optimized agent. You execute tasks tracked in a Graph project. Follow this workflow strictly. The human directs, you execute through the graph.\n\n# Workflow\n\n## 1. ORIENT\nOn your first call, orient yourself:\n\\`\\`\\`\ngraph_onboard({ project: \"<project-name>\" })\n\\`\\`\\`\nRead the \\`hint\\` field first — it tells you exactly what to do next. Then read the summary, evidence, knowledge, and actionable tasks.\n\n**First-run:** If the tree is empty and discovery is \\`\"pending\"\\`, this is a brand new project. Jump directly to DISCOVER below. Do not call graph_next on an empty project.\n\n**Drift check:** After onboarding, check for work done outside the graph:\n1. Run \\`git log --oneline -10\\` to see recent commits\n2. Compare against git evidence in the graph (commit hashes from resolved tasks)\n3. If there are commits not tracked in the graph, surface them to the user:\n - \"Found N commits not linked to any graph task: <list>\"\n - Ask: add retroactively (create node + evidence), or acknowledge and move on?\n\nThis catches work done ad-hoc or through plan files that bypassed the graph. It's cheap to run and prevents silent context loss.\n\n## 2. DISCOVER (when discovery is pending)\nIf the project root or a task node has \\`discovery: \"pending\"\\`, you must complete discovery before decomposing it. Discovery is an interview with the user to understand what needs to happen.\n\nUse AskUserQuestion to cover these areas (adapt to what's relevant — skip what's obvious):\n- **Scope** — What exactly needs to happen? What's explicitly out of scope?\n- **Existing patterns** — How does the codebase currently handle similar things? (explore first, then confirm)\n- **Technical approach** — What libraries, APIs, or patterns should we use?\n- **Acceptance criteria** — How will we know it's done? What does success look like?\n\nAfter the interview:\n1. Write findings as knowledge: \\`graph_knowledge_write({ project, key: \"discovery-<topic>\", content: \"...\" })\\`\n2. Flip discovery to done: \\`graph_update({ updates: [{ node_id: \"<id>\", discovery: \"done\" }] })\\`\n3. NOW decompose with graph_plan\n\nDo NOT skip discovery. If you try to add children to a node with \\`discovery: \"pending\"\\`, graph_plan will reject it.\n\n## 3. CLAIM\nGet your next task:\n\\`\\`\\`\ngraph_next({ project: \"<project-name>\", claim: true })\n\\`\\`\\`\nRead the task summary, ancestor chain (for scope), resolved dependencies (for context on what was done before you), and context links (for files to look at).\n\n## 4. PLAN\nIf you discover work that isn't in the graph, add it BEFORE executing:\n\\`\\`\\`\ngraph_plan({ nodes: [{ ref: \"new-work\", parent_ref: \"<parent-id>\", summary: \"...\" }] })\n\\`\\`\\`\nNever execute ad-hoc work. The graph is the source of truth.\n\nWhen decomposing work:\n- Set dependencies on LEAF nodes, not parent nodes. If \"Page A\" depends on \"Layout\", the dependency is from \"Page A\" to \"Layout\", not from the \"Pages\" parent to \"Layout\".\n- Keep tasks small and specific. A task should be completable in one session.\n- Parent nodes are organizational — they resolve when all children resolve. Don't put work in parent nodes.\n\n## 5. WORK\nExecute the claimed task. While working:\n- Annotate key code changes with \\`// [sl:nodeId]\\` where nodeId is the task you're working on\n- This creates a traceable link from code back to the task, its evidence, and its history\n- Build and run tests before considering a task done\n\n## 6. RESOLVE\nWhen done, resolve the task with a structured handoff. Every resolution should answer these questions for the next agent:\n\n- **What changed** — what was modified or created\n- **Why** — reasoning behind the approach taken\n- **Evidence** — commits, test results, implementation notes\n- **Next action** — what should happen next (if applicable)\n\n\\`\\`\\`\ngraph_update({ updates: [{\n node_id: \"<task-id>\",\n resolved: true,\n add_evidence: [\n { type: \"note\", ref: \"Implemented X using Y because Z. Next: wire up the API endpoint.\" },\n { type: \"git\", ref: \"<commit-hash> — <summary>\" },\n { type: \"test\", ref: \"All 155 tests passing\" }\n ],\n add_context_links: [\"path/to/files/you/touched\"]\n}] })\n\\`\\`\\`\n\nEvidence is mandatory. Write notes as if briefing an agent who has never seen the codebase — they should understand what was done and why without reading the code.\n\n## 7. PAUSE\nAfter resolving a task, STOP. Show the user the project status using \\`graph_status\\`, then wait for them to say \"continue\" before claiming the next task.\n\nThe user controls the pace. Do not auto-claim the next task.\n\n## Presenting status\nWhen showing project state to the user, always use \\`graph_status({ project: \"...\" })\\` and output the \\`formatted\\` field directly. This gives a consistent, readable view. Never format graph data manually — use the tool.\n\n# Rules\n\n- NEVER start work without a claimed task\n- NEVER resolve without evidence\n- NEVER execute ad-hoc work — add it to the graph first via graph_plan\n- NEVER auto-continue to the next task — pause and let the user decide\n- ALWAYS build and test before resolving\n- ALWAYS include context_links for files you modified when resolving\n- Parent nodes auto-resolve when all their children are resolved — you don't need to manually resolve them\n- NEVER skip discovery on nodes with discovery:pending — the system will block you from decomposing\n- NEVER delete resolved projects — they are the historical record. Completed projects are lightweight and preserve traceability across sessions\n- If you're approaching context limits, ensure your current task's state is captured (update with evidence even if not fully resolved) so the next agent can pick up where you left off\n\n# Record observations proactively\n\nGraph is the project memory across sessions. If something isn't in Graph, it's effectively forgotten. While working, record things you notice — even if they're not part of your current task:\n\n- **Warnings & errors**: CI failures, deprecation warnings, security vulnerabilities, linter issues\n- **Tech debt**: Code smells, outdated dependencies, missing tests, hardcoded values\n- **Broken things**: Flaky tests, dead links, misconfigured environments\n- **Ideas & improvements**: Performance opportunities, UX issues, missing features\n\nUse \\`graph_plan\\` to add observation nodes under the project root. Keep them lightweight — a clear summary is enough. They can always be dropped later if irrelevant.\n\nDefault to \"if in doubt, add a node.\" It's cheap to create and the next session will thank you.\n\n# Blocked status\n\nNodes can be manually blocked (separate from dependency-blocked). Use this for external blockers:\n\n\\`\\`\\`\ngraph_update({ updates: [{\n node_id: \"<id>\",\n blocked: true,\n blocked_reason: \"Waiting on API key from client\"\n}] })\n\\`\\`\\`\n\nTo unblock: \\`graph_update({ updates: [{ node_id: \"<id>\", blocked: false }] })\\`\n\n- \\`blocked_reason\\` is required when setting \\`blocked: true\\`\n- Blocked nodes won't appear in \\`graph_next\\` results\n- Unblocking auto-clears the reason\n- Use this for things like: waiting on external input, upstream API down, needs design review\n\n# Common mistakes to avoid\n\n- Setting dependencies on parent nodes instead of leaf nodes\n- Running project scaffolding tools (create-next-app, etc.) before planning in the graph\n- Resolving tasks without running tests\n- Doing work that isn't tracked in the graph\n- Continuing to the next task without pausing for user review\n- Trying to decompose a node without completing discovery first\n- Not writing knowledge entries during discovery — future agents need this context\n`;\n}\n\nexport interface AgentConfigResult {\n agent_file: string;\n install_path: string;\n instructions: string;\n}\n\nexport function handleAgentConfig(version: string): AgentConfigResult {\n return {\n agent_file: agentPrompt(version),\n install_path: \".claude/agents/graph.md\",\n instructions:\n \"Save the agent_file content to .claude/agents/graph.md in your project root. \" +\n \"Claude Code will automatically discover it and use it when tasks match the agent description.\",\n };\n}\n"],"mappings":";;;AAEA,SAAS,YAAY,SAAyB;AAC5C,SAAO;AAAA;AAAA,WAEE,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2JlB;AAQO,SAAS,kBAAkB,SAAoC;AACpE,SAAO;AAAA,IACL,YAAY,YAAY,OAAO;AAAA,IAC/B,cAAc;AAAA,IACd,cACE;AAAA,EAEJ;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/init.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, mkdirSync } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { handleAgentConfig } from \"./tools/agent-config.js\";\n\n// [sl:hy8oXisWnrZN1BfkonUqd] npx @graph-tl/graph init — zero friction onboarding\n\nlet PKG_VERSION = \"0.0.0\";\ntry {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkg = JSON.parse(readFileSync(join(__dirname, \"..\", \"package.json\"), \"utf-8\"));\n PKG_VERSION = pkg.version;\n} catch {}\n\nconst MCP_CONFIG = {\n command: \"npx\",\n args: [\"-y\", \"@graph-tl/graph\"],\n env: {\n GRAPH_AGENT: \"claude-code\",\n },\n};\n\nexport function init(): void {\n const cwd = process.cwd();\n let wrote = false;\n\n // 1. Write .mcp.json\n const configPath = join(cwd, \".mcp.json\");\n if (existsSync(configPath)) {\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf8\"));\n if (config.mcpServers?.graph) {\n console.log(\"✓ .mcp.json — graph already configured\");\n } else {\n config.mcpServers = config.mcpServers ?? {};\n config.mcpServers.graph = MCP_CONFIG;\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf8\");\n console.log(\"✓ .mcp.json — added graph server\");\n wrote = true;\n }\n } catch {\n console.error(`✗ .mcp.json exists but is not valid JSON — skipping`);\n }\n } else {\n const config = { mcpServers: { graph: MCP_CONFIG } };\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf8\");\n console.log(\"✓ .mcp.json — created with graph server\");\n wrote = true;\n }\n\n // 2. Write .claude/agents/graph.md\n const agentPath = join(cwd, \".claude\", \"agents\", \"graph.md\");\n const { agent_file } = handleAgentConfig(PKG_VERSION);\n if (existsSync(agentPath)) {\n const current = readFileSync(agentPath, \"utf8\");\n if (current === agent_file) {\n console.log(\"✓ .claude/agents/graph.md — already up to date\");\n } else {\n writeFileSync(agentPath, agent_file, \"utf8\");\n console.log(\"✓ .claude/agents/graph.md — updated\");\n wrote = true;\n }\n } else {\n mkdirSync(dirname(agentPath), { recursive: true });\n writeFileSync(agentPath, agent_file, \"utf8\");\n console.log(\"✓ .claude/agents/graph.md — created graph workflow agent\");\n wrote = true;\n }\n\n // 3. Summary\n console.log(\"\");\n if (wrote) {\n console.log(\"Graph is ready. Restart Claude Code to load the MCP server.\");\n console.log(\"\");\n console.log(\"Then try:\");\n console.log(' \"Use graph to plan building a REST API with auth and tests.\"');\n } else {\n console.log(\"Graph is already set up — nothing to do.\");\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,cAAc,eAAe,YAAY,iBAAiB;AACnE,SAAS,MAAM,eAAe;AAC9B,SAAS,qBAAqB;AAK9B,IAAI,cAAc;AAClB,IAAI;AACF,QAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,QAAM,MAAM,KAAK,MAAM,aAAa,KAAK,WAAW,MAAM,cAAc,GAAG,OAAO,CAAC;AACnF,gBAAc,IAAI;AACpB,QAAQ;AAAC;AAET,IAAM,aAAa;AAAA,EACjB,SAAS;AAAA,EACT,MAAM,CAAC,MAAM,iBAAiB;AAAA,EAC9B,KAAK;AAAA,IACH,aAAa;AAAA,EACf;AACF;AAEO,SAAS,OAAa;AAC3B,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,QAAQ;AAGZ,QAAM,aAAa,KAAK,KAAK,WAAW;AACxC,MAAI,WAAW,UAAU,GAAG;AAC1B,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,aAAa,YAAY,MAAM,CAAC;AAC1D,UAAI,OAAO,YAAY,OAAO;AAC5B,gBAAQ,IAAI,kDAAwC;AAAA,MACtD,OAAO;AACL,eAAO,aAAa,OAAO,cAAc,CAAC;AAC1C,eAAO,WAAW,QAAQ;AAC1B,sBAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AACxE,gBAAQ,IAAI,4CAAkC;AAC9C,gBAAQ;AAAA,MACV;AAAA,IACF,QAAQ;AACN,cAAQ,MAAM,+DAAqD;AAAA,IACrE;AAAA,EACF,OAAO;AACL,UAAM,SAAS,EAAE,YAAY,EAAE,OAAO,WAAW,EAAE;AACnD,kBAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AACxE,YAAQ,IAAI,mDAAyC;AACrD,YAAQ;AAAA,EACV;AAGA,QAAM,YAAY,KAAK,KAAK,WAAW,UAAU,UAAU;AAC3D,QAAM,EAAE,WAAW,IAAI,kBAAkB,WAAW;AACpD,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,UAAU,aAAa,WAAW,MAAM;AAC9C,QAAI,YAAY,YAAY;AAC1B,cAAQ,IAAI,0DAAgD;AAAA,IAC9D,OAAO;AACL,oBAAc,WAAW,YAAY,MAAM;AAC3C,cAAQ,IAAI,+CAAqC;AACjD,cAAQ;AAAA,IACV;AAAA,EACF,OAAO;AACL,cAAU,QAAQ,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,kBAAc,WAAW,YAAY,MAAM;AAC3C,YAAQ,IAAI,oEAA0D;AACtE,YAAQ;AAAA,EACV;AAGA,UAAQ,IAAI,EAAE;AACd,MAAI,OAAO;AACT,YAAQ,IAAI,6DAA6D;AACzE,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,WAAW;AACvB,YAAQ,IAAI,gEAAgE;AAAA,EAC9E,OAAO;AACL,YAAQ,IAAI,+CAA0C;AAAA,EACxD;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/tools/open.ts","../src/edges.ts","../src/tools/plan.ts","../src/tools/update.ts","../src/tools/connect.ts","../src/tools/context.ts","../src/tools/query.ts","../src/tools/next.ts","../src/tools/restructure.ts","../src/tools/history.ts","../src/tools/onboard.ts","../src/tools/tree.ts","../src/tools/status.ts","../src/tools/knowledge.ts","../src/gates.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ReadResourceRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { setDbPath, closeDb, checkpointDb } from \"./db.js\";\nimport { ValidationError, EngineError } from \"./validate.js\";\nimport { handleOpen } from \"./tools/open.js\";\nimport { handlePlan } from \"./tools/plan.js\";\nimport { handleUpdate } from \"./tools/update.js\";\nimport { handleConnect } from \"./tools/connect.js\";\nimport { handleContext } from \"./tools/context.js\";\nimport { handleQuery } from \"./tools/query.js\";\nimport { handleNext } from \"./tools/next.js\";\nimport { handleRestructure } from \"./tools/restructure.js\";\nimport { handleHistory } from \"./tools/history.js\";\nimport { handleOnboard } from \"./tools/onboard.js\";\nimport { handleAgentConfig } from \"./tools/agent-config.js\";\nimport { handleTree } from \"./tools/tree.js\";\nimport { handleStatus } from \"./tools/status.js\";\nimport { handleKnowledgeWrite, handleKnowledgeRead, handleKnowledgeDelete, handleKnowledgeSearch } from \"./tools/knowledge.js\";\nimport { getLicenseTier, type Tier } from \"./license.js\";\nimport { checkNodeLimit, checkProjectLimit, capEvidenceLimit, checkScope, checkKnowledgeTier } from \"./gates.js\";\n\nimport { createHash } from \"crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { join, resolve, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// Config from env\nconst AGENT_IDENTITY = process.env.GRAPH_AGENT ?? \"default-agent\";\nconst CLAIM_TTL = parseInt(process.env.GRAPH_CLAIM_TTL ?? \"60\", 10);\n\nfunction defaultDbPath(): string {\n const projectDir = resolve(\".\");\n const hash = createHash(\"sha256\").update(projectDir).digest(\"hex\").slice(0, 16);\n const dir = join(homedir(), \".graph\", \"db\", hash);\n mkdirSync(dir, { recursive: true });\n return join(dir, \"graph.db\");\n}\n\nconst DB_PATH = process.env.GRAPH_DB ?? defaultDbPath();\n\n// Read version from package.json\nconst PKG_NAME = \"@graph-tl/graph\";\nlet PKG_VERSION = \"0.0.0\";\ntry {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkg = JSON.parse(readFileSync(join(__dirname, \"..\", \"package.json\"), \"utf-8\"));\n PKG_VERSION = pkg.version;\n} catch {}\n\n// Version banner — shown once on first tool call\nlet versionBanner: string | null = `[graph] v${PKG_VERSION}`;\n\n// Non-blocking version check against npm registry\nlet updateWarning: string | null = null;\n\nasync function checkForUpdate(): Promise<void> {\n try {\n const res = await fetch(`https://registry.npmjs.org/${PKG_NAME}/latest`);\n if (!res.ok) return;\n const data = await res.json() as { version: string };\n if (data.version !== PKG_VERSION) {\n updateWarning = `[graph] Update available: ${PKG_VERSION} → ${data.version}. Run: npx clear-npx-cache && restart MCP server.`;\n }\n } catch {}\n}\n\n// Auto-update agent file on first tool call\nfunction checkAndUpdateAgentFile(): string | null {\n try {\n const projectRoot = resolve(\".\");\n const agentPath = join(projectRoot, \".claude\", \"agents\", \"graph.md\");\n const latest = handleAgentConfig(PKG_VERSION).agent_file;\n\n if (existsSync(agentPath)) {\n const current = readFileSync(agentPath, \"utf-8\");\n if (current === latest) return null;\n // Extract version from existing frontmatter\n const match = current.match(/^---[\\s\\S]*?version:\\s*(\\S+)[\\s\\S]*?---/);\n const oldVersion = match?.[1] ?? \"unknown\";\n writeFileSync(agentPath, latest, \"utf-8\");\n return `[graph] Updated .claude/agents/graph.md (${oldVersion} → ${PKG_VERSION})`;\n } else {\n mkdirSync(dirname(agentPath), { recursive: true });\n writeFileSync(agentPath, latest, \"utf-8\");\n return `[graph] Created .claude/agents/graph.md`;\n }\n } catch {\n return null;\n }\n}\n\n// Tool definitions\nconst TOOLS = [\n {\n name: \"graph_open\",\n description:\n \"Open an existing project or create a new one. Omit 'project' to list all projects. Returns project root node and summary stats (total, resolved, unresolved, blocked, actionable counts).\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: {\n type: \"string\",\n description: \"Project name (e.g. 'my-project'). Omit to list all projects.\",\n },\n goal: {\n type: \"string\",\n description: \"Project goal/description. Used on creation only.\",\n },\n skip_discovery: {\n type: \"boolean\",\n description: \"Skip discovery phase — create project ready for immediate planning. Default false.\",\n },\n },\n },\n },\n {\n name: \"graph_plan\",\n description:\n \"Batch create nodes with parent-child and dependency relationships in one atomic call. Use for decomposing work into subtrees. Each node needs a temp 'ref' for intra-batch references. parent_ref and depends_on can reference batch refs or existing node IDs.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n nodes: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n ref: {\n type: \"string\",\n description: \"Temp ID for referencing within this batch\",\n },\n parent_ref: {\n type: \"string\",\n description:\n \"Parent: a ref from this batch OR an existing node ID\",\n },\n summary: { type: \"string\" },\n context_links: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Pointers to files, commits, URLs\",\n },\n depends_on: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Refs within batch OR existing node IDs this depends on\",\n },\n properties: {\n type: \"object\",\n description: \"Freeform key-value properties\",\n },\n },\n required: [\"ref\", \"summary\"],\n },\n description: \"Nodes to create\",\n },\n },\n required: [\"nodes\"],\n },\n },\n {\n name: \"graph_next\",\n description:\n \"Get the next actionable node — an unresolved leaf with all dependencies resolved. Ranked by priority (from properties), depth, and least-recently-updated. Returns the node with ancestor chain, context links, and resolved dependency info. Use claim=true to soft-lock the node. When modifying code for this task, annotate key changes with // [sl:nodeId] so future agents can trace code back to this task.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name (e.g. 'my-project'), not a node ID\" },\n scope: {\n type: \"string\",\n description: \"Node ID to scope results to. Only returns actionable descendants of this node.\",\n },\n filter: {\n type: \"object\",\n description: \"Match against node properties\",\n },\n count: {\n type: \"number\",\n description: \"Return top N nodes (default 1)\",\n },\n claim: {\n type: \"boolean\",\n description:\n \"If true, soft-lock returned nodes with agent identity\",\n },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"graph_context\",\n description:\n \"Deep-read a node and its neighborhood: ancestors (scope chain), children tree (to configurable depth), dependency graph (what it depends on, what depends on it). Look for // [sl:nodeId] annotations in source files to find code tied to specific tasks.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n node_id: { type: \"string\", description: \"Node ID to inspect\" },\n depth: {\n type: \"number\",\n description: \"Levels of children to return (default 2)\",\n },\n },\n required: [\"node_id\"],\n },\n },\n {\n name: \"graph_update\",\n description:\n \"Update one or more nodes. Can change resolved, state, summary, properties (merged), context_links, and add evidence. When resolving nodes, returns newly_actionable — nodes that became unblocked. ENFORCED: Resolving a node requires evidence — use resolved_reason (shorthand, auto-creates note) or add_evidence array (type: 'git' for commits, 'note' for what was done and why, 'test' for results). Also add context_links to files you modified.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n updates: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n node_id: { type: \"string\" },\n expected_rev: { type: \"number\", description: \"Optimistic concurrency: reject if node's current rev doesn't match. Prevents silent overwrites by concurrent agents.\" },\n resolved: { type: \"boolean\" },\n resolved_reason: { type: \"string\", description: \"Shorthand: auto-creates a note evidence entry. Use instead of add_evidence for simple cases.\" },\n discovery: { type: \"string\", description: \"Discovery phase status: 'pending' or 'done'. Set to 'done' after completing discovery interview.\" },\n blocked: { type: \"boolean\", description: \"Manually block/unblock a node. Blocked nodes are skipped by graph_next. Use for external blockers (e.g., waiting on domain purchase, another team).\" },\n blocked_reason: { type: \"string\", description: \"Why the node is blocked. Cleared automatically when unblocking.\" },\n state: { description: \"Agent-defined state, any type\" },\n summary: { type: \"string\" },\n properties: {\n type: \"object\",\n description:\n \"Merged into existing. Set a key to null to delete it.\",\n },\n add_context_links: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Files modified or created for this task. Add when resolving so future agents know what was touched.\",\n },\n remove_context_links: {\n type: \"array\",\n items: { type: \"string\" },\n },\n add_evidence: {\n type: \"array\",\n description: \"Evidence of work done. Always add when resolving. Types: 'git' (commit hash + summary), 'note' (what was implemented and why), 'test' (test results).\",\n items: {\n type: \"object\",\n properties: {\n type: { type: \"string\", description: \"Evidence type: git, note, test, or custom\" },\n ref: { type: \"string\", description: \"The evidence content — commit ref, implementation note, test result\" },\n },\n required: [\"type\", \"ref\"],\n },\n },\n },\n required: [\"node_id\"],\n },\n },\n },\n required: [\"updates\"],\n },\n },\n {\n name: \"graph_connect\",\n description:\n \"Add or remove edges between nodes. Types: 'depends_on' (with cycle detection), 'relates_to', or custom. Parent edges not allowed — use graph_restructure for reparenting.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n edges: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n from: { type: \"string\", description: \"Source node ID\" },\n to: { type: \"string\", description: \"Target node ID\" },\n type: {\n type: \"string\",\n description: \"'depends_on', 'relates_to', or custom\",\n },\n remove: {\n type: \"boolean\",\n description: \"True to remove this edge\",\n },\n },\n required: [\"from\", \"to\", \"type\"],\n },\n },\n },\n required: [\"edges\"],\n },\n },\n {\n name: \"graph_query\",\n description:\n \"Search and filter nodes. Filters: resolved, properties, text, ancestor (descendants of), is_leaf, is_actionable, is_blocked, claimed_by. Supports sorting and cursor pagination.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name (e.g. 'my-project'), not a node ID\" },\n filter: {\n type: \"object\",\n properties: {\n resolved: { type: \"boolean\" },\n properties: { type: \"object\" },\n text: { type: \"string\", description: \"Substring match on summary\" },\n ancestor: {\n type: \"string\",\n description: \"Return all descendants of this node\",\n },\n has_evidence_type: { type: \"string\" },\n is_leaf: { type: \"boolean\" },\n is_actionable: { type: \"boolean\" },\n is_blocked: { type: \"boolean\" },\n claimed_by: {\n type: [\"string\", \"null\"],\n description: \"Filter by claim. null = unclaimed.\",\n },\n },\n },\n sort: {\n type: \"string\",\n enum: [\"readiness\", \"depth\", \"recent\", \"created\"],\n },\n limit: { type: \"number\", description: \"Max results (default 20, max 100)\" },\n cursor: { type: \"string\", description: \"Pagination cursor\" },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"graph_restructure\",\n description:\n \"Modify graph structure: move (reparent), merge (combine two nodes), drop (resolve node + subtree with reason), delete (permanently remove node + subtree). Atomic. Reports newly_actionable nodes.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n operations: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n op: {\n type: \"string\",\n enum: [\"move\", \"merge\", \"drop\", \"delete\"],\n },\n node_id: { type: \"string\", description: \"For move and drop\" },\n new_parent: { type: \"string\", description: \"For move\" },\n source: { type: \"string\", description: \"For merge: node to absorb\" },\n target: {\n type: \"string\",\n description: \"For merge: node that survives\",\n },\n reason: { type: \"string\", description: \"For drop: why\" },\n },\n required: [\"op\"],\n },\n },\n },\n required: [\"operations\"],\n },\n },\n {\n name: \"graph_history\",\n description:\n \"Read the audit trail for a node. Shows who changed what, when, and why. Useful for understanding past decisions across sessions.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n node_id: { type: \"string\" },\n limit: { type: \"number\", description: \"Max events (default 20)\" },\n cursor: { type: \"string\", description: \"Pagination cursor\" },\n },\n required: [\"node_id\"],\n },\n },\n {\n name: \"graph_onboard\",\n description:\n \"Single-call orientation for new agents joining a project. Returns project summary, tree structure (depth 2), recent evidence from resolved nodes (knowledge transfer), all context links, and actionable tasks. Use this as your first call when starting work on an existing project.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name (e.g. 'my-project'). Omit to auto-select (works when there's exactly one project).\" },\n evidence_limit: {\n type: \"number\",\n description: \"Max evidence entries to return (default 20, max 50)\",\n },\n },\n },\n },\n {\n name: \"graph_tree\",\n description:\n \"Full tree visualization for a project. Returns the complete task hierarchy with resolve status. Use when you need to see the whole project structure beyond graph_context's single-node neighborhood.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name (e.g. 'my-project')\" },\n depth: {\n type: \"number\",\n description: \"Max tree depth to return (default 10, max 20)\",\n },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"graph_status\",\n description:\n \"Returns a pre-formatted markdown summary of a project's current state. Use this to present project status to the user — output the `formatted` field directly. Shows task tree with status tags, actionable items, blocked items, and knowledge entries. Omit project to auto-select or get multi-project overview.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: {\n type: \"string\",\n description: \"Project name. Omit to auto-select (works when there's exactly one project).\",\n },\n },\n },\n },\n {\n name: \"graph_agent_config\",\n description:\n \"Returns the graph-optimized agent configuration file for Claude Code. Save the returned content to .claude/agents/graph.md to enable the graph workflow agent.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {},\n },\n },\n {\n name: \"graph_knowledge_write\",\n description:\n \"Write a knowledge entry for a project. Creates or overwrites a named document. Use for persistent project-level knowledge (architecture decisions, conventions, API contracts) that outlives individual tasks.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n key: { type: \"string\", description: \"Knowledge entry key (e.g. 'auth', 'database-schema', 'api-contracts')\" },\n content: { type: \"string\", description: \"Free-form text content\" },\n },\n required: [\"project\", \"key\", \"content\"],\n },\n },\n {\n name: \"graph_knowledge_read\",\n description:\n \"Read knowledge entries for a project. Provide a key to read one entry, or omit to list all entries.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n key: { type: \"string\", description: \"Knowledge entry key. Omit to list all.\" },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"graph_knowledge_delete\",\n description:\n \"Delete a knowledge entry from a project.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n key: { type: \"string\", description: \"Knowledge entry key to delete\" },\n },\n required: [\"project\", \"key\"],\n },\n },\n {\n name: \"graph_knowledge_search\",\n description:\n \"Search knowledge entries by substring match on key or content.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n query: { type: \"string\", description: \"Search string\" },\n },\n required: [\"project\", \"query\"],\n },\n },\n];\n\nexport async function startServer(): Promise<void> {\n // Set database path — db is created lazily on first tool call\n setDbPath(DB_PATH);\n\n // [sl:N0IDVJQIhENQFsov6-Lhg] Resolve license tier once at startup (reads license file, doesn't touch db)\n const tier: Tier = getLicenseTier(DB_PATH);\n\n const server = new Server(\n { name: \"graph\", version: PKG_VERSION },\n { capabilities: { tools: {}, resources: {} } }\n );\n\n // Fire-and-forget version check (opt-in: GRAPH_UPDATE_CHECK=1)\n if (process.env.GRAPH_UPDATE_CHECK === \"1\") {\n checkForUpdate();\n }\n\n // List tools\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: TOOLS,\n }));\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n let result: unknown;\n\n switch (name) {\n case \"graph_open\": {\n const openArgs = args as any;\n // Gate: check project limit when creating a new project\n if (openArgs?.project) {\n const { getProjectRoot } = await import(\"./nodes.js\");\n if (!getProjectRoot(openArgs.project)) {\n checkProjectLimit(tier);\n }\n }\n result = handleOpen(openArgs, AGENT_IDENTITY);\n break;\n }\n\n case \"graph_plan\": {\n const planArgs = args as any;\n // Gate: check node limit before creating nodes\n if (planArgs?.nodes?.length > 0) {\n // Determine project from the first node's parent\n const { getNode } = await import(\"./nodes.js\");\n const firstParent = planArgs.nodes[0]?.parent_ref;\n if (firstParent && typeof firstParent === \"string\" && !planArgs.nodes.some((n: any) => n.ref === firstParent)) {\n const parentNode = getNode(firstParent);\n if (parentNode) {\n checkNodeLimit(tier, parentNode.project, planArgs.nodes.length);\n }\n }\n }\n result = handlePlan(planArgs, AGENT_IDENTITY);\n break;\n }\n\n case \"graph_next\": {\n const nextArgs = args as any;\n // Gate: strip scope on free tier\n if (nextArgs?.scope) {\n nextArgs.scope = checkScope(tier, nextArgs.scope);\n }\n result = handleNext(nextArgs, AGENT_IDENTITY, CLAIM_TTL);\n break;\n }\n\n case \"graph_context\":\n result = handleContext(args as any);\n break;\n\n case \"graph_update\":\n result = handleUpdate(args as any, AGENT_IDENTITY);\n break;\n\n case \"graph_connect\":\n result = handleConnect(args as any, AGENT_IDENTITY);\n break;\n\n case \"graph_query\":\n result = handleQuery(args as any);\n break;\n\n case \"graph_restructure\":\n result = handleRestructure(args as any, AGENT_IDENTITY);\n break;\n\n case \"graph_history\":\n result = handleHistory(args as any);\n break;\n\n case \"graph_onboard\": {\n const onboardArgs = args as any;\n // Gate: cap evidence limit on free tier\n onboardArgs.evidence_limit = capEvidenceLimit(tier, onboardArgs?.evidence_limit);\n result = handleOnboard(onboardArgs);\n break;\n }\n\n case \"graph_tree\":\n result = handleTree(args as any);\n break;\n\n case \"graph_status\":\n result = handleStatus(args as any);\n break;\n\n case \"graph_agent_config\":\n result = handleAgentConfig(PKG_VERSION);\n break;\n\n case \"graph_knowledge_write\":\n checkKnowledgeTier(tier);\n result = handleKnowledgeWrite(args as any, AGENT_IDENTITY);\n break;\n\n case \"graph_knowledge_read\":\n checkKnowledgeTier(tier);\n result = handleKnowledgeRead(args as any);\n break;\n\n case \"graph_knowledge_delete\":\n checkKnowledgeTier(tier);\n result = handleKnowledgeDelete(args as any);\n break;\n\n case \"graph_knowledge_search\":\n checkKnowledgeTier(tier);\n result = handleKnowledgeSearch(args as any);\n break;\n\n default:\n return {\n content: [\n { type: \"text\" as const, text: JSON.stringify({ error: `Unknown tool: ${name}` }) },\n ],\n isError: true,\n };\n }\n\n const content: Array<{ type: \"text\"; text: string }> = [\n { type: \"text\" as const, text: JSON.stringify(result, null, 2) },\n ];\n if (versionBanner) {\n const agentNote = checkAndUpdateAgentFile();\n const bannerParts = [versionBanner];\n if (agentNote) bannerParts.push(agentNote);\n if (updateWarning) bannerParts.push(updateWarning);\n content.push({ type: \"text\" as const, text: bannerParts.join(\"\\n\") });\n versionBanner = null;\n updateWarning = null;\n }\n return { content };\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n const code =\n error instanceof ValidationError\n ? \"validation_error\"\n : error instanceof EngineError\n ? (error as EngineError).code\n : \"error\";\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: message, code }),\n },\n ],\n isError: true,\n };\n }\n });\n\n // [sl:Ps3gCuzhMoQWK6tynsGA4] MCP resources — browsable read-only views of graph data\n\n // Resource templates (dynamic, parameterized URIs)\n server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({\n resourceTemplates: [\n {\n uriTemplate: \"graph://{project}/tree\",\n name: \"Project Tree\",\n description: \"Full task tree for a project with resolve status\",\n mimeType: \"application/json\",\n },\n {\n uriTemplate: \"graph://{project}/knowledge\",\n name: \"Project Knowledge\",\n description: \"All knowledge entries for a project\",\n mimeType: \"application/json\",\n },\n {\n uriTemplate: \"graph://{project}/knowledge/{key}\",\n name: \"Knowledge Entry\",\n description: \"A specific knowledge entry\",\n mimeType: \"application/json\",\n },\n ],\n }));\n\n // Static resource list (enumerate known projects)\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n try {\n const { listProjects } = await import(\"./nodes.js\");\n const projects = listProjects();\n const resources = projects.flatMap((p) => [\n {\n uri: `graph://${p.project}/tree`,\n name: `${p.project} — Tree`,\n description: `Task tree: ${p.total} nodes (${p.resolved} resolved)`,\n mimeType: \"application/json\",\n },\n {\n uri: `graph://${p.project}/knowledge`,\n name: `${p.project} — Knowledge`,\n description: `Knowledge entries for ${p.project}`,\n mimeType: \"application/json\",\n },\n ]);\n return { resources };\n } catch {\n return { resources: [] };\n }\n });\n\n // Read a specific resource\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const uri = request.params.uri;\n const match = uri.match(/^graph:\\/\\/([^/]+)\\/(.+)$/);\n if (!match) {\n throw new Error(`Invalid resource URI: ${uri}`);\n }\n\n const [, project, path] = match;\n\n if (path === \"tree\") {\n const result = handleTree({ project });\n return {\n contents: [{ uri, mimeType: \"application/json\", text: JSON.stringify(result, null, 2) }],\n };\n }\n\n if (path === \"knowledge\") {\n const result = handleKnowledgeRead({ project });\n return {\n contents: [{ uri, mimeType: \"application/json\", text: JSON.stringify(result, null, 2) }],\n };\n }\n\n const knowledgeMatch = path.match(/^knowledge\\/(.+)$/);\n if (knowledgeMatch) {\n const result = handleKnowledgeRead({ project, key: knowledgeMatch[1] });\n return {\n contents: [{ uri, mimeType: \"application/json\", text: JSON.stringify(result, null, 2) }],\n };\n }\n\n throw new Error(`Unknown resource path: ${path}`);\n });\n\n // Connect transport\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Periodic WAL checkpoint every 30s — flushes WAL data into main db file\n const checkpointInterval = setInterval(() => {\n try { checkpointDb(); } catch {}\n }, 30_000);\n\n // Cleanup on exit\n process.on(\"SIGINT\", () => {\n clearInterval(checkpointInterval);\n closeDb();\n process.exit(0);\n });\n process.on(\"SIGTERM\", () => {\n clearInterval(checkpointInterval);\n closeDb();\n process.exit(0);\n });\n}\n","import { createNode, getProjectRoot, listProjects, getProjectSummary } from \"../nodes.js\";\nimport { optionalString } from \"../validate.js\";\nimport type { Node } from \"../types.js\";\n\nexport interface OpenInput {\n project?: string;\n goal?: string;\n skip_discovery?: boolean;\n}\n\nexport type OpenResult =\n | {\n projects: Array<{\n project: string;\n id: string;\n summary: string;\n total: number;\n resolved: number;\n unresolved: number;\n updated_at: string;\n }>;\n }\n | {\n project: string;\n root: Node;\n summary: {\n total: number;\n resolved: number;\n unresolved: number;\n blocked: number;\n actionable: number;\n };\n hint?: string;\n };\n\nexport function handleOpen(input: OpenInput, agent: string): OpenResult {\n const project = optionalString(input?.project, \"project\");\n const goal = optionalString(input?.goal, \"goal\");\n\n if (!project) {\n return { projects: listProjects() };\n }\n\n let root = getProjectRoot(project);\n let isNew = false;\n\n if (!root) {\n root = createNode({\n project,\n summary: goal ?? project,\n discovery: input?.skip_discovery ? \"done\" : \"pending\",\n agent,\n });\n isNew = true;\n }\n\n const summary = getProjectSummary(project);\n\n const result: OpenResult = { project, root, summary };\n\n // Guide the agent on what to do next\n if (isNew && root.discovery === \"pending\") {\n result.hint = `New project created. Discovery is pending — interview the user to understand scope and goals, then set discovery to \"done\" via graph_update before decomposing with graph_plan.`;\n } else if (isNew) {\n result.hint = `New project created. Ready to decompose — use graph_plan to add tasks.`;\n } else if (root.discovery === \"pending\") {\n result.hint = `Discovery is still pending on this project. Complete the discovery interview, then set discovery to \"done\" via graph_update.`;\n } else if (summary.actionable > 0) {\n result.hint = `${summary.actionable} actionable task(s). Use graph_next to claim one.`;\n } else if (summary.unresolved > 0 && summary.actionable === 0) {\n result.hint = `All remaining tasks are blocked. Check dependencies with graph_query.`;\n }\n\n return result;\n}\n","import { nanoid } from \"nanoid\";\nimport { getDb } from \"./db.js\";\nimport { logEvent } from \"./events.js\";\nimport type { Edge } from \"./types.js\";\n\n// --- Cycle detection ---\n\nfunction wouldCreateCycle(from: string, to: string): boolean {\n // Adding edge \"from depends_on to\". Check if to can already reach from\n // through existing depends_on edges. If so, adding this edge creates a cycle.\n const db = getDb();\n const visited = new Set<string>();\n const stack = [to];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (current === from) return true;\n if (visited.has(current)) continue;\n visited.add(current);\n\n // Follow forward depends_on edges: what does current depend on?\n const deps = db\n .prepare(\n `SELECT to_node FROM edges WHERE from_node = ? AND type = 'depends_on'`\n )\n .all(current) as Array<{ to_node: string }>;\n\n for (const dep of deps) {\n stack.push(dep.to_node);\n }\n }\n\n return false;\n}\n\n// --- Add edge ---\n\nexport interface AddEdgeInput {\n from: string;\n to: string;\n type: string;\n agent: string;\n}\n\nexport interface AddEdgeResult {\n edge: Edge | null;\n rejected: boolean;\n reason?: string;\n}\n\nexport function addEdge(input: AddEdgeInput): AddEdgeResult {\n const db = getDb();\n\n // Check nodes exist\n const fromExists = db.prepare(\"SELECT id FROM nodes WHERE id = ?\").get(input.from);\n const toExists = db.prepare(\"SELECT id FROM nodes WHERE id = ?\").get(input.to);\n\n if (!fromExists) {\n return { edge: null, rejected: true, reason: \"node_not_found: \" + input.from };\n }\n if (!toExists) {\n return { edge: null, rejected: true, reason: \"node_not_found: \" + input.to };\n }\n\n // Check for duplicates\n const existing = db\n .prepare(\n \"SELECT id FROM edges WHERE from_node = ? AND to_node = ? AND type = ?\"\n )\n .get(input.from, input.to, input.type);\n\n if (existing) {\n return { edge: null, rejected: true, reason: \"duplicate_edge\" };\n }\n\n // Cycle detection for depends_on\n if (input.type === \"depends_on\") {\n if (wouldCreateCycle(input.from, input.to)) {\n return { edge: null, rejected: true, reason: \"cycle_detected\" };\n }\n }\n\n const edge: Edge = {\n id: nanoid(),\n from_node: input.from,\n to_node: input.to,\n type: input.type,\n created_at: new Date().toISOString(),\n };\n\n db.prepare(`\n INSERT INTO edges (id, from_node, to_node, type, created_at)\n VALUES (?, ?, ?, ?, ?)\n `).run(edge.id, edge.from_node, edge.to_node, edge.type, edge.created_at);\n\n logEvent(input.from, input.agent, \"edge_added\", [\n { field: \"edge\", before: null, after: { to: input.to, type: input.type } },\n ]);\n\n return { edge, rejected: false };\n}\n\n// --- Remove edge ---\n\nexport function removeEdge(\n from: string,\n to: string,\n type: string,\n agent: string\n): boolean {\n const db = getDb();\n\n const result = db\n .prepare(\n \"DELETE FROM edges WHERE from_node = ? AND to_node = ? AND type = ?\"\n )\n .run(from, to, type);\n\n if (result.changes > 0) {\n logEvent(from, agent, \"edge_removed\", [\n { field: \"edge\", before: { to, type }, after: null },\n ]);\n return true;\n }\n\n return false;\n}\n\n// --- Query edges ---\n\nexport function getEdgesFrom(nodeId: string, type?: string): Edge[] {\n const db = getDb();\n\n if (type) {\n return db\n .prepare(\"SELECT * FROM edges WHERE from_node = ? AND type = ?\")\n .all(nodeId, type) as Edge[];\n }\n\n return db\n .prepare(\"SELECT * FROM edges WHERE from_node = ?\")\n .all(nodeId) as Edge[];\n}\n\nexport function getEdgesTo(nodeId: string, type?: string): Edge[] {\n const db = getDb();\n\n if (type) {\n return db\n .prepare(\"SELECT * FROM edges WHERE to_node = ? AND type = ?\")\n .all(nodeId, type) as Edge[];\n }\n\n return db\n .prepare(\"SELECT * FROM edges WHERE to_node = ?\")\n .all(nodeId) as Edge[];\n}\n\n// [sl:uRocbNC_bArUXGr908Qbk] Find newly actionable nodes\n// Targeted: accepts resolved node IDs, checks only direct dependents.\n// Falls back to project-wide scan when no IDs provided.\n\nexport function findNewlyActionable(\n project: string,\n resolvedNodeIds?: string[]\n): Array<{ id: string; summary: string }> {\n const db = getDb();\n\n if (resolvedNodeIds && resolvedNodeIds.length > 0) {\n // Targeted: only check direct dependents of the resolved nodes + children of resolved nodes\n const placeholders = resolvedNodeIds.map(() => \"?\").join(\",\");\n const rows = db\n .prepare(\n `SELECT DISTINCT n.id, n.summary FROM nodes n\n WHERE n.resolved = 0 AND n.project = ?\n AND (\n -- nodes that had a depends_on edge to one of the resolved nodes\n n.id IN (\n SELECT e.from_node FROM edges e\n WHERE e.type = 'depends_on' AND e.to_node IN (${placeholders})\n )\n OR\n -- parents of resolved nodes (might now be leaf if all children resolved)\n n.id IN (SELECT parent FROM nodes WHERE id IN (${placeholders}) AND parent IS NOT NULL)\n )\n -- is a leaf (no unresolved children)\n AND NOT EXISTS (\n SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0\n )\n -- all deps resolved\n AND NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )`\n )\n .all(project, ...resolvedNodeIds, ...resolvedNodeIds) as Array<{\n id: string;\n summary: string;\n }>;\n\n return rows;\n }\n\n // Fallback: project-wide scan\n const rows = db\n .prepare(\n `SELECT n.id, n.summary FROM nodes n\n WHERE n.project = ? AND n.resolved = 0\n AND NOT EXISTS (\n SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0\n )\n AND NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )`\n )\n .all(project) as Array<{ id: string; summary: string }>;\n\n return rows;\n}\n","import { getDb } from \"../db.js\";\nimport { createNode, getNode } from \"../nodes.js\";\nimport { addEdge } from \"../edges.js\";\nimport { requireArray, requireString, EngineError } from \"../validate.js\";\n\nexport interface PlanNodeInput {\n ref: string;\n parent_ref?: string;\n summary: string;\n context_links?: string[];\n depends_on?: string[];\n properties?: Record<string, unknown>;\n}\n\nexport interface PlanInput {\n nodes: PlanNodeInput[];\n}\n\nexport interface PlanResult {\n created: Array<{ ref: string; id: string }>;\n}\n\nexport function handlePlan(input: PlanInput, agent: string): PlanResult {\n const db = getDb();\n const nodes = requireArray<PlanNodeInput>(input?.nodes, \"nodes\");\n\n // Validate each node has required fields\n for (let i = 0; i < nodes.length; i++) {\n const n = nodes[i];\n requireString(n.ref, `nodes[${i}].ref`);\n requireString(n.summary, `nodes[${i}].summary`);\n }\n\n // Ref -> real ID mapping\n const refMap = new Map<string, string>();\n const created: Array<{ ref: string; id: string }> = [];\n\n // Validate refs are unique\n const refs = new Set<string>();\n for (const node of nodes) {\n if (refs.has(node.ref)) {\n throw new EngineError(\"duplicate_ref\", `Duplicate ref in batch: ${node.ref}`);\n }\n refs.add(node.ref);\n }\n\n // Run atomically\n const transaction = db.transaction(() => {\n // First pass: create all nodes\n for (const nodeInput of nodes) {\n // Resolve parent\n let parentId: string | undefined;\n if (nodeInput.parent_ref) {\n // Check if it's a batch ref or existing node ID\n parentId = refMap.get(nodeInput.parent_ref);\n if (!parentId) {\n // Try as existing node ID\n const existing = getNode(nodeInput.parent_ref);\n if (existing) {\n parentId = existing.id;\n } else {\n throw new EngineError(\n \"invalid_parent_ref\",\n `parent_ref \"${nodeInput.parent_ref}\" is neither a batch ref nor an existing node ID`\n );\n }\n }\n }\n\n // Determine project from parent or require first node to have a parent\n let project: string;\n if (parentId) {\n const parentNode = getNode(parentId)!;\n // [sl:m3_UNy-eICtHeHExfHwUH] Block decomposition when node has pending discovery\n if (parentNode.discovery === \"pending\") {\n throw new EngineError(\n \"discovery_pending\",\n `Cannot add children to \"${parentNode.summary}\" (${parentId}) — discovery is pending. Run: graph_update({ updates: [{ node_id: \"${parentId}\", discovery: \"done\" }] }) after completing discovery, then decompose.`\n );\n }\n project = parentNode.project;\n } else {\n // If no parent, the node must be a root. But we need a project.\n // Infer from first node that has a parent, or error.\n throw new EngineError(\n \"missing_parent\",\n `Node \"${nodeInput.ref}\" has no parent_ref. All planned nodes must have a parent (an existing node or a batch ref).`\n );\n }\n\n const node = createNode({\n project,\n parent: parentId,\n summary: nodeInput.summary,\n context_links: nodeInput.context_links,\n properties: nodeInput.properties,\n agent,\n });\n\n refMap.set(nodeInput.ref, node.id);\n created.push({ ref: nodeInput.ref, id: node.id });\n }\n\n // Second pass: create dependency edges\n for (const nodeInput of nodes) {\n if (!nodeInput.depends_on || nodeInput.depends_on.length === 0) continue;\n\n const fromId = refMap.get(nodeInput.ref)!;\n\n for (const dep of nodeInput.depends_on) {\n // Resolve dep: batch ref or existing node ID\n let toId = refMap.get(dep);\n if (!toId) {\n const existing = getNode(dep);\n if (existing) {\n toId = existing.id;\n } else {\n throw new EngineError(\n \"invalid_depends_on\",\n `depends_on \"${dep}\" in node \"${nodeInput.ref}\" is neither a batch ref nor an existing node ID`\n );\n }\n }\n\n const result = addEdge({\n from: fromId,\n to: toId,\n type: \"depends_on\",\n agent,\n });\n\n if (result.rejected) {\n throw new EngineError(\n \"edge_rejected\",\n `Dependency edge from \"${nodeInput.ref}\" to \"${dep}\" rejected: ${result.reason}`\n );\n }\n }\n }\n });\n\n transaction();\n\n return { created };\n}\n","import { updateNode, getNode, getNodeOrThrow, getChildren } from \"../nodes.js\";\nimport { findNewlyActionable } from \"../edges.js\";\nimport { requireArray, requireString, EngineError } from \"../validate.js\";\n\nexport interface UpdateEntry {\n node_id: string;\n expected_rev?: number;\n resolved?: boolean;\n resolved_reason?: string; // [sl:QBEtldx8PBWACftEM8MYl] Shorthand — auto-creates note evidence\n discovery?: string | null;\n blocked?: boolean;\n blocked_reason?: string | null;\n state?: unknown;\n summary?: string;\n properties?: Record<string, unknown>;\n add_context_links?: string[];\n remove_context_links?: string[];\n add_evidence?: Array<{ type: string; ref: string }>;\n}\n\nexport interface UpdateInput {\n updates: UpdateEntry[];\n}\n\nexport interface UpdateResult {\n updated: Array<{ node_id: string; rev: number }>;\n newly_actionable?: Array<{ id: string; summary: string }>;\n auto_resolved?: Array<{ node_id: string; summary: string }>;\n}\n\nexport function handleUpdate(input: UpdateInput, agent: string): UpdateResult {\n const updates = requireArray<UpdateEntry>(input?.updates, \"updates\");\n\n for (let i = 0; i < updates.length; i++) {\n requireString(updates[i].node_id, `updates[${i}].node_id`);\n if (updates[i].add_evidence) {\n for (let j = 0; j < updates[i].add_evidence!.length; j++) {\n requireString(updates[i].add_evidence![j].type, `updates[${i}].add_evidence[${j}].type`);\n requireString(updates[i].add_evidence![j].ref, `updates[${i}].add_evidence[${j}].ref`);\n }\n }\n }\n\n const updated: Array<{ node_id: string; rev: number }> = [];\n const resolvedIds: string[] = [];\n const resolvedProjects = new Set<string>();\n\n for (const entry of updates) {\n // Optimistic concurrency: reject if rev doesn't match\n if (entry.expected_rev !== undefined) {\n const current = getNodeOrThrow(entry.node_id);\n if (current.rev !== entry.expected_rev) {\n throw new EngineError(\n \"rev_mismatch\",\n `Node ${entry.node_id} has rev ${current.rev}, expected ${entry.expected_rev}. Another agent may have modified it. Re-read and retry.`\n );\n }\n }\n\n // Expand resolved_reason shorthand into evidence\n let evidence = entry.add_evidence;\n if (entry.resolved_reason) {\n evidence = [...(evidence ?? []), { type: \"note\", ref: entry.resolved_reason }];\n }\n\n const node = updateNode({\n node_id: entry.node_id,\n agent,\n resolved: entry.resolved,\n discovery: entry.discovery,\n blocked: entry.blocked,\n blocked_reason: entry.blocked_reason,\n state: entry.state,\n summary: entry.summary,\n properties: entry.properties,\n add_context_links: entry.add_context_links,\n remove_context_links: entry.remove_context_links,\n add_evidence: evidence,\n });\n\n updated.push({ node_id: node.id, rev: node.rev });\n\n if (entry.resolved === true) {\n resolvedIds.push(node.id);\n resolvedProjects.add(node.project);\n }\n }\n\n // [sl:GBuFbmTFuFfnl5KWW-ja-] Auto-resolve parents when all children are resolved\n const autoResolved: Array<{ node_id: string; summary: string }> = [];\n if (resolvedIds.length > 0) {\n const seen = new Set<string>(resolvedIds);\n const queue = [...resolvedIds];\n\n while (queue.length > 0) {\n const nodeId = queue.shift()!;\n const node = getNode(nodeId);\n if (!node?.parent) continue;\n\n const parentId = node.parent;\n if (seen.has(parentId)) continue;\n seen.add(parentId);\n\n const parent = getNode(parentId);\n if (!parent || parent.resolved) continue;\n\n const children = getChildren(parentId);\n if (children.length === 0) continue;\n if (children.every((c) => c.resolved)) {\n const resolved = updateNode({\n node_id: parentId,\n agent,\n resolved: true,\n add_evidence: [{ type: \"note\", ref: \"Auto-resolved: all children completed\" }],\n });\n updated.push({ node_id: resolved.id, rev: resolved.rev });\n resolvedIds.push(parentId);\n autoResolved.push({ node_id: parentId, summary: parent.summary });\n queue.push(parentId);\n }\n }\n }\n\n const result: UpdateResult = { updated };\n\n if (resolvedIds.length > 0 && resolvedProjects.size > 0) {\n const allActionable: Array<{ id: string; summary: string }> = [];\n for (const proj of resolvedProjects) {\n allActionable.push(...findNewlyActionable(proj, resolvedIds));\n }\n result.newly_actionable = allActionable;\n }\n\n if (autoResolved.length > 0) {\n result.auto_resolved = autoResolved;\n }\n\n return result;\n}\n","import { addEdge, removeEdge } from \"../edges.js\";\nimport { requireArray, requireString } from \"../validate.js\";\n\nexport interface ConnectEdgeInput {\n from: string;\n to: string;\n type: string;\n remove?: boolean;\n}\n\nexport interface ConnectInput {\n edges: ConnectEdgeInput[];\n}\n\nexport interface ConnectResult {\n applied: number;\n rejected?: Array<{ from: string; to: string; reason: string }>;\n}\n\nexport function handleConnect(input: ConnectInput, agent: string): ConnectResult {\n const edges = requireArray<ConnectEdgeInput>(input?.edges, \"edges\");\n\n for (let i = 0; i < edges.length; i++) {\n requireString(edges[i].from, `edges[${i}].from`);\n requireString(edges[i].to, `edges[${i}].to`);\n requireString(edges[i].type, `edges[${i}].type`);\n }\n\n let applied = 0;\n const rejected: Array<{ from: string; to: string; reason: string }> = [];\n\n for (const edge of edges) {\n if (edge.type === \"parent\") {\n rejected.push({\n from: edge.from,\n to: edge.to,\n reason: \"parent_edges_not_allowed: use graph_restructure to reparent\",\n });\n continue;\n }\n\n if (edge.remove) {\n const removed = removeEdge(edge.from, edge.to, edge.type, agent);\n if (removed) {\n applied++;\n } else {\n rejected.push({\n from: edge.from,\n to: edge.to,\n reason: \"edge_not_found\",\n });\n }\n } else {\n const result = addEdge({\n from: edge.from,\n to: edge.to,\n type: edge.type,\n agent,\n });\n\n if (result.rejected) {\n rejected.push({\n from: edge.from,\n to: edge.to,\n reason: result.reason!,\n });\n } else {\n applied++;\n }\n }\n }\n\n const result: ConnectResult = { applied };\n if (rejected.length > 0) {\n result.rejected = rejected;\n }\n return result;\n}\n","import { getNodeOrThrow, getChildren, getAncestors, getSubtreeProgress } from \"../nodes.js\";\nimport { getEdgesFrom, getEdgesTo } from \"../edges.js\";\nimport { getNode } from \"../nodes.js\";\nimport { requireString, optionalNumber } from \"../validate.js\";\nimport type { Node } from \"../types.js\";\n\nexport interface ContextInput {\n node_id: string;\n depth?: number;\n}\n\ninterface NodeTree {\n id: string;\n summary: string;\n resolved: boolean;\n discovery: string | null;\n state: unknown;\n progress?: { resolved: number; total: number };\n children?: NodeTree[];\n child_count?: number;\n}\n\nexport interface ContextResult {\n node: Node;\n ancestors: Array<{ id: string; summary: string; resolved: boolean }>;\n children: NodeTree;\n depends_on: Array<{ node: Node; satisfied: boolean }>;\n depended_by: Array<{ node: Node; satisfied: boolean }>;\n}\n\nfunction buildNodeTree(nodeId: string, currentDepth: number, maxDepth: number): NodeTree {\n const node = getNodeOrThrow(nodeId);\n const children = getChildren(nodeId);\n\n const tree: NodeTree = {\n id: node.id,\n summary: node.summary,\n resolved: node.resolved,\n discovery: node.discovery,\n state: node.state,\n };\n\n if (children.length === 0) {\n return tree;\n }\n\n tree.progress = getSubtreeProgress(nodeId);\n\n if (currentDepth < maxDepth) {\n tree.children = children.map((child) =>\n buildNodeTree(child.id, currentDepth + 1, maxDepth)\n );\n } else {\n tree.child_count = children.length;\n }\n\n return tree;\n}\n\nexport function handleContext(input: ContextInput): ContextResult {\n const nodeId = requireString(input?.node_id, \"node_id\");\n const depth = optionalNumber(input?.depth, \"depth\", 0, 10) ?? 2;\n const node = getNodeOrThrow(nodeId);\n const ancestors = getAncestors(nodeId);\n\n // Build children tree\n const children = buildNodeTree(nodeId, 0, depth);\n\n // Get dependency edges\n const depsOut = getEdgesFrom(nodeId, \"depends_on\");\n const depsIn = getEdgesTo(nodeId, \"depends_on\");\n\n const depends_on = depsOut.map((edge) => {\n const target = getNode(edge.to_node);\n return {\n node: target!,\n satisfied: target?.resolved ?? false,\n };\n });\n\n const depended_by = depsIn.map((edge) => {\n const source = getNode(edge.from_node);\n return {\n node: source!,\n satisfied: node.resolved,\n };\n });\n\n return { node, ancestors, children, depends_on, depended_by };\n}\n","import { getDb } from \"../db.js\";\nimport { requireString, optionalNumber, optionalString } from \"../validate.js\";\nimport type { NodeRow } from \"../types.js\";\n\nexport interface QueryFilter {\n resolved?: boolean;\n properties?: Record<string, unknown>;\n text?: string;\n ancestor?: string;\n has_evidence_type?: string;\n is_leaf?: boolean;\n is_actionable?: boolean;\n is_blocked?: boolean;\n claimed_by?: string | null;\n}\n\nexport interface QueryInput {\n project: string;\n filter?: QueryFilter;\n sort?: \"readiness\" | \"depth\" | \"recent\" | \"created\";\n limit?: number;\n cursor?: string;\n}\n\nexport interface QueryResultNode {\n id: string;\n summary: string;\n resolved: boolean;\n state: unknown;\n parent: string | null;\n depth: number;\n properties: Record<string, unknown>;\n}\n\nexport interface QueryResult {\n nodes: QueryResultNode[];\n total: number;\n next_cursor?: string;\n}\n\n// [sl:tfMDHhmJSXd5TPgwD2ZC6] Descendant lookup via recursive CTE (replaced JS BFS)\nfunction getDescendantIds(nodeId: string): string[] {\n const db = getDb();\n const rows = db\n .prepare(\n `WITH RECURSIVE descendants(id) AS (\n SELECT id FROM nodes WHERE parent = ?\n UNION ALL\n SELECT n.id FROM nodes n JOIN descendants d ON n.parent = d.id\n )\n SELECT id FROM descendants`\n )\n .all(nodeId) as Array<{ id: string }>;\n\n return rows.map((r) => r.id);\n}\n\n\nexport function handleQuery(input: QueryInput): QueryResult {\n const project = requireString(input?.project, \"project\");\n const db = getDb();\n const limit = Math.min(optionalNumber(input?.limit, \"limit\", 1, 100) ?? 20, 100);\n const filter = input?.filter;\n const cursor = optionalString(input?.cursor, \"cursor\");\n\n // Build WHERE clauses\n const conditions: string[] = [\"n.project = ?\"];\n const params: unknown[] = [project];\n\n if (filter?.resolved !== undefined) {\n conditions.push(\"n.resolved = ?\");\n params.push(filter.resolved ? 1 : 0);\n }\n\n if (filter?.text) {\n conditions.push(\"n.summary LIKE ?\");\n params.push(`%${filter.text}%`);\n }\n\n if (filter?.ancestor) {\n const descendantIds = getDescendantIds(filter.ancestor);\n if (descendantIds.length === 0) {\n return { nodes: [], total: 0 };\n }\n conditions.push(`n.id IN (${descendantIds.map(() => \"?\").join(\",\")})`);\n params.push(...descendantIds);\n }\n\n if (filter?.has_evidence_type) {\n conditions.push(\n `EXISTS (SELECT 1 FROM json_each(n.evidence) WHERE json_extract(value, '$.type') = ?)`\n );\n params.push(filter.has_evidence_type);\n }\n\n if (filter?.is_leaf) {\n conditions.push(\n \"NOT EXISTS (SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0)\"\n );\n }\n\n if (filter?.is_actionable) {\n conditions.push(\"n.resolved = 0\");\n conditions.push(\"n.blocked = 0\");\n conditions.push(\n \"NOT EXISTS (SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0)\"\n );\n conditions.push(\n `NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )`\n );\n }\n\n if (filter?.is_blocked) {\n conditions.push(\"n.resolved = 0\");\n conditions.push(\n `(n.blocked = 1 OR EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n ))`\n );\n }\n\n if (filter?.properties) {\n for (const [key, value] of Object.entries(filter.properties)) {\n conditions.push(\"json_extract(n.properties, ?) = ?\");\n params.push(`$.${key}`, value as string | number);\n }\n }\n\n if (filter?.claimed_by !== undefined) {\n if (filter.claimed_by === null) {\n conditions.push(\n \"(json_extract(n.properties, '$._claimed_by') IS NULL)\"\n );\n } else {\n conditions.push(\"json_extract(n.properties, '$._claimed_by') = ?\");\n params.push(filter.claimed_by);\n }\n }\n\n // Cursor: use created_at + id for stable pagination\n if (cursor) {\n const [cursorTime, cursorId] = cursor.split(\"|\");\n conditions.push(\"(n.created_at > ? OR (n.created_at = ? AND n.id > ?))\");\n params.push(cursorTime, cursorTime, cursorId);\n }\n\n const whereClause = conditions.join(\" AND \");\n\n // Sorting\n let orderBy: string;\n switch (input.sort) {\n case \"depth\":\n // Can't sort by computed depth in SQL easily, so sort by created and compute depth post-hoc\n orderBy = \"n.created_at ASC, n.id ASC\";\n break;\n case \"recent\":\n orderBy = \"n.updated_at DESC, n.id ASC\";\n break;\n case \"created\":\n orderBy = \"n.created_at ASC, n.id ASC\";\n break;\n case \"readiness\":\n default:\n orderBy = \"n.updated_at ASC, n.id ASC\";\n break;\n }\n\n // Count total\n // Count total (without cursor filter)\n const countConditions = cursor ? conditions.slice(0, -1) : conditions;\n const countParams = cursor ? params.slice(0, -3) : [...params];\n const total = (\n db.prepare(`SELECT COUNT(*) as count FROM nodes n WHERE ${countConditions.join(\" AND \")}`).get(...countParams) as { count: number }\n ).count;\n\n // Fetch\n params.push(limit + 1);\n const query = `SELECT * FROM nodes n WHERE ${whereClause} ORDER BY ${orderBy} LIMIT ?`;\n const rows = db.prepare(query).all(...params) as NodeRow[];\n\n const hasMore = rows.length > limit;\n const slice = hasMore ? rows.slice(0, limit) : rows;\n\n const nodes: QueryResultNode[] = slice.map((row) => ({\n id: row.id,\n summary: row.summary,\n resolved: row.resolved === 1,\n state: row.state ? JSON.parse(row.state) : null,\n parent: row.parent,\n depth: row.depth,\n properties: JSON.parse(row.properties),\n }));\n\n const result: QueryResult = { nodes, total };\n\n if (hasMore) {\n const last = slice[slice.length - 1];\n result.next_cursor = `${last.created_at}|${last.id}`;\n }\n\n return result;\n}\n","import { getDb } from \"../db.js\";\nimport { getNode, getAncestors, updateNode } from \"../nodes.js\";\nimport { getEdgesFrom } from \"../edges.js\";\nimport { requireString, optionalString, optionalNumber, optionalBoolean } from \"../validate.js\";\nimport type { Node, NodeRow, Evidence } from \"../types.js\";\n\nexport interface NextInput {\n project: string;\n scope?: string;\n filter?: Record<string, unknown>;\n count?: number;\n claim?: boolean;\n}\n\nexport interface NextResultNode {\n node: Node;\n ancestors: Array<{ id: string; summary: string }>;\n context_links: {\n self: string[];\n inherited: Array<{ node_id: string; links: string[] }>;\n };\n resolved_deps: Array<{\n id: string;\n summary: string;\n evidence: Evidence[];\n }>;\n}\n\nexport interface ClaimedTask {\n id: string;\n summary: string;\n claimed_at: string;\n}\n\nexport interface NextResult {\n nodes: NextResultNode[];\n your_claims?: ClaimedTask[];\n}\n\nexport function handleNext(\n input: NextInput,\n agent: string,\n claimTtlMinutes: number = 60\n): NextResult {\n const project = requireString(input?.project, \"project\");\n const scope = optionalString(input?.scope, \"scope\");\n const count = optionalNumber(input?.count, \"count\", 1, 50) ?? 1;\n const claim = optionalBoolean(input?.claim, \"claim\") ?? false;\n const db = getDb();\n\n // [sl:HB5daFH1HlFXzuTluibnk] Scope filtering: restrict to descendants of a given node\n let scopeFilter = \"\";\n const scopeParams: unknown[] = [];\n if (scope) {\n const descendantIds = db\n .prepare(\n `WITH RECURSIVE descendants(id) AS (\n SELECT id FROM nodes WHERE parent = ?\n UNION ALL\n SELECT n.id FROM nodes n JOIN descendants d ON n.parent = d.id\n )\n SELECT id FROM descendants`\n )\n .all(scope) as Array<{ id: string }>;\n\n if (descendantIds.length === 0) {\n return { nodes: [] };\n }\n scopeFilter = `AND n.id IN (${descendantIds.map(() => \"?\").join(\",\")})`;\n scopeParams.push(...descendantIds.map((d) => d.id));\n }\n\n // Find actionable nodes: unresolved, not blocked, leaf (no unresolved children), all deps resolved\n let query = `\n SELECT n.* FROM nodes n\n WHERE n.project = ? AND n.resolved = 0 AND n.blocked = 0\n ${scopeFilter}\n AND NOT EXISTS (\n SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0\n )\n AND NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )\n `;\n\n const params: unknown[] = [project, ...scopeParams];\n\n // Skip nodes claimed by other agents (if claim TTL hasn't expired)\n const claimCutoff = new Date(\n Date.now() - claimTtlMinutes * 60 * 1000\n ).toISOString();\n\n query += `\n AND (\n json_extract(n.properties, '$._claimed_by') IS NULL\n OR json_extract(n.properties, '$._claimed_by') = ?\n OR json_extract(n.properties, '$._claimed_at') <= ?\n )\n `;\n params.push(agent, claimCutoff);\n\n // Property filters\n if (input.filter) {\n for (const [key, value] of Object.entries(input.filter)) {\n query += \" AND json_extract(n.properties, ?) = ?\";\n params.push(`$.${key}`, value as string | number);\n }\n }\n\n // [sl:md48WyMYFlOf4KP99vmtv] Ranking fully in SQL — never loads more than N rows\n // Depth is cached on the node, priority extracted via json_extract\n query += `\n ORDER BY\n COALESCE(CAST(json_extract(n.properties, '$.priority') AS REAL), 0) DESC,\n n.depth DESC,\n n.updated_at ASC\n LIMIT ?\n `;\n params.push(count);\n\n const rows = db.prepare(query).all(...params) as NodeRow[];\n\n const selected = rows.map((row) => ({ row }));\n\n const results: NextResultNode[] = selected.map(({ row }) => {\n const node = getNode(row.id)!;\n const ancestors = getAncestors(row.id);\n\n // Context links: self + inherited from ancestors\n const inherited: Array<{ node_id: string; links: string[] }> = [];\n for (const anc of ancestors) {\n const ancNode = getNode(anc.id);\n if (ancNode && ancNode.context_links.length > 0) {\n inherited.push({ node_id: anc.id, links: ancNode.context_links });\n }\n }\n\n // Resolved dependencies\n const depEdges = getEdgesFrom(row.id, \"depends_on\");\n const resolved_deps = depEdges\n .map((edge) => {\n const depNode = getNode(edge.to_node);\n if (!depNode || !depNode.resolved) return null;\n return {\n id: depNode.id,\n summary: depNode.summary,\n evidence: depNode.evidence,\n };\n })\n .filter(Boolean) as NextResultNode[\"resolved_deps\"];\n\n // Claim if requested\n if (claim) {\n updateNode({\n node_id: node.id,\n agent,\n properties: {\n _claimed_by: agent,\n _claimed_at: new Date().toISOString(),\n },\n });\n }\n\n return {\n node: claim ? getNode(row.id)! : node,\n ancestors: ancestors.map((a) => ({ id: a.id, summary: a.summary })),\n context_links: {\n self: node.context_links,\n inherited,\n },\n resolved_deps,\n };\n });\n\n // Surface caller's existing claims (unexpired) so they can resume or release them\n const claimRows = db\n .prepare(\n `SELECT id, summary, json_extract(properties, '$._claimed_at') as claimed_at\n FROM nodes\n WHERE project = ? AND resolved = 0\n AND json_extract(properties, '$._claimed_by') = ?\n AND json_extract(properties, '$._claimed_at') > ?\n ORDER BY json_extract(properties, '$._claimed_at') DESC`\n )\n .all(project, agent, claimCutoff) as Array<{ id: string; summary: string; claimed_at: string }>;\n\n const result: NextResult = { nodes: results };\n if (claimRows.length > 0) {\n result.your_claims = claimRows.map((r) => ({\n id: r.id,\n summary: r.summary,\n claimed_at: r.claimed_at,\n }));\n }\n\n return result;\n}\n","import { getDb } from \"../db.js\";\nimport { getNodeOrThrow, getNode, getChildren, updateNode } from \"../nodes.js\";\nimport { getEdgesFrom, getEdgesTo, findNewlyActionable } from \"../edges.js\";\nimport { logEvent } from \"../events.js\";\nimport { requireArray, requireString, EngineError } from \"../validate.js\";\nimport type { Evidence } from \"../types.js\";\n\nexport interface MoveOp {\n op: \"move\";\n node_id: string;\n new_parent: string;\n}\n\nexport interface MergeOp {\n op: \"merge\";\n source: string;\n target: string;\n}\n\nexport interface DropOp {\n op: \"drop\";\n node_id: string;\n reason: string;\n}\n\nexport interface DeleteOp {\n op: \"delete\";\n node_id: string;\n}\n\nexport type RestructureOp = MoveOp | MergeOp | DropOp | DeleteOp;\n\nexport interface RestructureInput {\n operations: RestructureOp[];\n}\n\nexport interface RestructureResult {\n applied: number;\n details: Array<{ op: string; node_id: string; result: string }>;\n newly_actionable?: Array<{ id: string; summary: string }>;\n}\n\nfunction wouldCreateParentCycle(nodeId: string, newParentId: string): boolean {\n // Check if newParentId is a descendant of nodeId (which would create a cycle)\n const db = getDb();\n let current: string | null = newParentId;\n\n while (current) {\n if (current === nodeId) return true;\n const row = db\n .prepare(\"SELECT parent FROM nodes WHERE id = ?\")\n .get(current) as { parent: string | null } | undefined;\n current = row?.parent ?? null;\n }\n\n return false;\n}\n\nfunction getAllDescendants(nodeId: string): string[] {\n const ids: string[] = [];\n const stack = [nodeId];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n const children = getChildren(current);\n for (const child of children) {\n ids.push(child.id);\n stack.push(child.id);\n }\n }\n\n return ids;\n}\n\nfunction recomputeSubtreeDepth(nodeId: string, newDepth: number): void {\n const db = getDb();\n db.prepare(\"UPDATE nodes SET depth = ? WHERE id = ?\").run(newDepth, nodeId);\n const children = db.prepare(\"SELECT id FROM nodes WHERE parent = ?\").all(nodeId) as Array<{ id: string }>;\n for (const child of children) {\n recomputeSubtreeDepth(child.id, newDepth + 1);\n }\n}\n\nfunction handleMove(op: MoveOp, agent: string): { node_id: string; result: string } {\n const db = getDb();\n const node = getNodeOrThrow(op.node_id);\n const newParent = getNodeOrThrow(op.new_parent);\n\n if (node.project !== newParent.project) {\n throw new EngineError(\"cross_project\", `Cannot move node across projects: \"${node.project}\" → \"${newParent.project}\"`);\n }\n\n if (wouldCreateParentCycle(op.node_id, op.new_parent)) {\n throw new EngineError(\n \"cycle_detected\",\n `Move would create cycle: ${op.node_id} cannot be moved under ${op.new_parent}`\n );\n }\n\n const oldParent = node.parent;\n const now = new Date().toISOString();\n db.prepare(\"UPDATE nodes SET parent = ?, updated_at = ? WHERE id = ?\").run(\n op.new_parent,\n now,\n op.node_id\n );\n\n // Recompute depth for moved node and all descendants\n recomputeSubtreeDepth(op.node_id, newParent.depth + 1);\n\n logEvent(op.node_id, agent, \"moved\", [\n { field: \"parent\", before: oldParent, after: op.new_parent },\n ]);\n\n return { node_id: op.node_id, result: `moved under ${op.new_parent}` };\n}\n\nfunction handleMerge(op: MergeOp, agent: string): { node_id: string; result: string } {\n const db = getDb();\n const source = getNodeOrThrow(op.source);\n const target = getNodeOrThrow(op.target);\n\n if (source.project !== target.project) {\n throw new EngineError(\"cross_project\", `Cannot merge nodes across projects: \"${source.project}\" → \"${target.project}\"`);\n }\n\n // Move source's children to target and recompute their depths\n const movedChildren = db.prepare(\"SELECT id FROM nodes WHERE parent = ?\").all(op.source) as Array<{ id: string }>;\n db.prepare(\"UPDATE nodes SET parent = ?, updated_at = ? WHERE parent = ?\").run(\n op.target,\n new Date().toISOString(),\n op.source\n );\n for (const child of movedChildren) {\n recomputeSubtreeDepth(child.id, target.depth + 1);\n }\n\n // Append source's evidence to target\n const targetEvidence: Evidence[] = [...target.evidence, ...source.evidence];\n db.prepare(\"UPDATE nodes SET evidence = ?, updated_at = ? WHERE id = ?\").run(\n JSON.stringify(targetEvidence),\n new Date().toISOString(),\n op.target\n );\n\n // Transfer source's dependency edges to target\n const sourceOutEdges = getEdgesFrom(op.source);\n const sourceInEdges = getEdgesTo(op.source);\n\n for (const edge of sourceOutEdges) {\n // source depends_on X -> target depends_on X\n const existing = db\n .prepare(\n \"SELECT id FROM edges WHERE from_node = ? AND to_node = ? AND type = ?\"\n )\n .get(op.target, edge.to_node, edge.type);\n\n if (!existing) {\n db.prepare(\n \"UPDATE edges SET from_node = ? WHERE id = ?\"\n ).run(op.target, edge.id);\n } else {\n db.prepare(\"DELETE FROM edges WHERE id = ?\").run(edge.id);\n }\n }\n\n for (const edge of sourceInEdges) {\n // X depends_on source -> X depends_on target\n const existing = db\n .prepare(\n \"SELECT id FROM edges WHERE from_node = ? AND to_node = ? AND type = ?\"\n )\n .get(edge.from_node, op.target, edge.type);\n\n if (!existing) {\n db.prepare(\n \"UPDATE edges SET to_node = ? WHERE id = ?\"\n ).run(op.target, edge.id);\n } else {\n db.prepare(\"DELETE FROM edges WHERE id = ?\").run(edge.id);\n }\n }\n\n // Log merge on target (source will be deleted)\n logEvent(op.target, agent, \"merged\", [\n { field: \"merged_from\", before: null, after: op.source },\n ]);\n\n // Delete source: events, edges, then node (FK order)\n db.prepare(\"DELETE FROM events WHERE node_id = ?\").run(op.source);\n db.prepare(\"DELETE FROM edges WHERE from_node = ? OR to_node = ?\").run(\n op.source,\n op.source\n );\n db.prepare(\"DELETE FROM nodes WHERE id = ?\").run(op.source);\n\n return { node_id: op.target, result: `merged ${op.source} into ${op.target}` };\n}\n\nfunction handleDrop(op: DropOp, agent: string): { node_id: string; result: string } {\n const now = new Date().toISOString();\n\n // Get all descendants\n const descendants = getAllDescendants(op.node_id);\n const allIds = [op.node_id, ...descendants];\n\n // Mark all as resolved with evidence\n for (const id of allIds) {\n const node = getNode(id);\n if (!node || node.resolved) continue;\n\n updateNode({\n node_id: id,\n agent,\n resolved: true,\n add_evidence: [{ type: \"dropped\", ref: op.reason }],\n });\n\n logEvent(id, agent, \"dropped\", [\n { field: \"resolved\", before: false, after: true },\n { field: \"reason\", before: null, after: op.reason },\n ]);\n }\n\n return {\n node_id: op.node_id,\n result: `dropped ${allIds.length} node(s): ${op.reason}`,\n };\n}\n\nfunction handleDelete(op: DeleteOp, agent: string): { node_id: string; result: string } {\n const db = getDb();\n const node = getNodeOrThrow(op.node_id);\n\n // Guard: prevent deleting project roots that have evidence (preserves traceability)\n if (node.parent === null) {\n const evidenceCount = db.prepare(\n `SELECT COUNT(*) as cnt FROM nodes\n WHERE project = ? AND evidence != '[]'`\n ).get(node.project) as { cnt: number };\n\n if (evidenceCount.cnt > 0) {\n throw new EngineError(\n \"delete_protected\",\n `Cannot delete project \"${node.project}\" — it contains ${evidenceCount.cnt} node(s) with evidence. Resolved projects preserve traceability across sessions. Use \"drop\" to mark as resolved instead.`\n );\n }\n }\n\n const descendants = getAllDescendants(op.node_id);\n const allIds = [op.node_id, ...descendants];\n const placeholders = allIds.map(() => \"?\").join(\",\");\n\n // Delete events, edges, then nodes (FK order)\n db.prepare(`DELETE FROM events WHERE node_id IN (${placeholders})`).run(...allIds);\n db.prepare(`DELETE FROM edges WHERE from_node IN (${placeholders}) OR to_node IN (${placeholders})`).run(...allIds, ...allIds);\n db.prepare(`DELETE FROM nodes WHERE id IN (${placeholders})`).run(...allIds);\n\n return {\n node_id: op.node_id,\n result: `deleted ${allIds.length} node(s)`,\n };\n}\n\nexport function handleRestructure(\n input: RestructureInput,\n agent: string\n): RestructureResult {\n const operations = requireArray<RestructureOp>(input?.operations, \"operations\");\n\n for (let i = 0; i < operations.length; i++) {\n const op = operations[i];\n requireString(op.op, `operations[${i}].op`);\n if (op.op === \"move\") {\n requireString((op as MoveOp).node_id, `operations[${i}].node_id`);\n requireString((op as MoveOp).new_parent, `operations[${i}].new_parent`);\n } else if (op.op === \"merge\") {\n requireString((op as MergeOp).source, `operations[${i}].source`);\n requireString((op as MergeOp).target, `operations[${i}].target`);\n } else if (op.op === \"drop\") {\n requireString((op as DropOp).node_id, `operations[${i}].node_id`);\n requireString((op as DropOp).reason, `operations[${i}].reason`);\n } else if (op.op === \"delete\") {\n requireString((op as DeleteOp).node_id, `operations[${i}].node_id`);\n } else {\n throw new EngineError(\"unknown_op\", `Unknown operation: ${op.op}`);\n }\n }\n\n const db = getDb();\n let applied = 0;\n const details: Array<{ op: string; node_id: string; result: string }> = [];\n let project: string | null = null;\n\n const transaction = db.transaction(() => {\n for (const op of operations) {\n let detail: { node_id: string; result: string };\n\n switch (op.op) {\n case \"move\":\n detail = handleMove(op, agent);\n project = getNode(op.node_id)?.project ?? project;\n break;\n case \"merge\":\n detail = handleMerge(op, agent);\n project = getNode(op.target)?.project ?? project;\n break;\n case \"drop\":\n detail = handleDrop(op, agent);\n project = getNode(op.node_id)?.project ?? project;\n break;\n case \"delete\":\n project = getNode(op.node_id)?.project ?? project;\n detail = handleDelete(op, agent);\n break;\n default:\n throw new Error(`Unknown operation: ${(op as RestructureOp).op}`);\n }\n\n details.push({ op: op.op, ...detail });\n applied++;\n }\n });\n\n transaction();\n\n const result: RestructureResult = { applied, details };\n\n if (project) {\n const actionable = findNewlyActionable(project);\n if (actionable.length > 0) {\n result.newly_actionable = actionable;\n }\n }\n\n return result;\n}\n","import { getEvents } from \"../events.js\";\nimport { getNodeOrThrow } from \"../nodes.js\";\nimport { requireString, optionalNumber, optionalString } from \"../validate.js\";\n\nexport interface HistoryInput {\n node_id: string;\n limit?: number;\n cursor?: string;\n}\n\nexport interface HistoryResult {\n events: Array<{\n timestamp: string;\n agent: string;\n action: string;\n changes: Array<{ field: string; before: unknown; after: unknown }>;\n }>;\n next_cursor?: string;\n}\n\nexport function handleHistory(input: HistoryInput): HistoryResult {\n const nodeId = requireString(input?.node_id, \"node_id\");\n const limit = optionalNumber(input?.limit, \"limit\", 1, 100) ?? 20;\n const cursor = optionalString(input?.cursor, \"cursor\");\n\n getNodeOrThrow(nodeId);\n\n const { events, next_cursor } = getEvents(nodeId, limit, cursor);\n\n const result: HistoryResult = {\n events: events.map((e) => ({\n timestamp: e.timestamp,\n agent: e.agent,\n action: e.action,\n changes: e.changes,\n })),\n };\n\n if (next_cursor) {\n result.next_cursor = next_cursor;\n }\n\n return result;\n}\n","import { getDb } from \"../db.js\";\nimport { getProjectRoot, getProjectSummary, listProjects } from \"../nodes.js\";\nimport { optionalString, optionalNumber } from \"../validate.js\";\nimport { EngineError } from \"../validate.js\";\nimport type { NodeRow, Evidence } from \"../types.js\";\n\n// [sl:yosc4NuV6j43Zv0fsDXDj] graph_onboard — single-call orientation for new agents\n\nexport interface OnboardInput {\n project?: string;\n evidence_limit?: number;\n}\n\nexport interface OnboardResult {\n project: string;\n goal: string;\n discovery: string | null;\n hint?: string;\n summary: {\n total: number;\n resolved: number;\n unresolved: number;\n blocked: number;\n actionable: number;\n };\n tree: Array<{\n id: string;\n summary: string;\n resolved: boolean;\n blocked: boolean;\n blocked_reason: string | null;\n children: Array<{\n id: string;\n summary: string;\n resolved: boolean;\n blocked: boolean;\n blocked_reason: string | null;\n child_count: number;\n }>;\n }>;\n recent_evidence: Array<{\n node_id: string;\n node_summary: string;\n type: string;\n ref: string;\n agent: string;\n timestamp: string;\n }>;\n context_links: string[];\n knowledge: Array<{\n key: string;\n content: string;\n updated_at: string;\n }>;\n recently_resolved: Array<{\n id: string;\n summary: string;\n resolved_at: string;\n agent: string;\n }>;\n last_activity: string | null;\n actionable: Array<{\n id: string;\n summary: string;\n properties: Record<string, unknown>;\n }>;\n}\n\n// [sl:1pRRsWFomcv04XAkdLMAj] Allow graph_onboard without project name\nexport function handleOnboard(input: OnboardInput): OnboardResult | { projects: ReturnType<typeof listProjects>; hint: string } {\n const evidenceLimit = optionalNumber(input?.evidence_limit, \"evidence_limit\", 1, 50) ?? 20;\n const db = getDb();\n\n // Auto-resolve project when not specified\n let project = optionalString(input?.project, \"project\");\n if (!project) {\n const projects = listProjects();\n if (projects.length === 0) {\n return {\n projects: [],\n hint: \"No projects yet. Create one with graph_open({ project: \\\"my-project\\\", goal: \\\"...\\\" }).\",\n };\n }\n if (projects.length === 1) {\n project = projects[0].project;\n } else {\n return {\n projects,\n hint: `${projects.length} projects found. Call graph_onboard with a specific project name.`,\n };\n }\n }\n\n // Verify project exists\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"project_not_found\", `Project not found: ${project}`);\n }\n\n // 1. Project summary counts\n const summary = getProjectSummary(project);\n\n // 2. Tree structure — root's children + their children (depth 1-2)\n const topChildren = db\n .prepare(\"SELECT * FROM nodes WHERE parent = ? ORDER BY created_at ASC\")\n .all(root.id) as NodeRow[];\n\n const tree = topChildren.map((child) => {\n const grandchildren = db\n .prepare(\n `SELECT id, summary, resolved, blocked, blocked_reason,\n (SELECT COUNT(*) FROM nodes gc WHERE gc.parent = n.id) as child_count\n FROM nodes n WHERE parent = ? ORDER BY created_at ASC`\n )\n .all(child.id) as Array<{\n id: string;\n summary: string;\n resolved: number;\n blocked: number;\n blocked_reason: string | null;\n child_count: number;\n }>;\n\n return {\n id: child.id,\n summary: child.summary,\n resolved: child.resolved === 1,\n discovery: child.discovery,\n blocked: child.blocked === 1,\n blocked_reason: child.blocked_reason,\n children: grandchildren.map((gc) => ({\n id: gc.id,\n summary: gc.summary,\n resolved: gc.resolved === 1,\n blocked: gc.blocked === 1,\n blocked_reason: gc.blocked_reason,\n child_count: gc.child_count,\n })),\n };\n });\n\n // 3. Recent evidence across all resolved nodes, sorted by timestamp\n const allNodes = db\n .prepare(\"SELECT id, summary, evidence FROM nodes WHERE project = ? AND resolved = 1 AND evidence != '[]'\")\n .all(project) as Array<{ id: string; summary: string; evidence: string }>;\n\n const allEvidence: OnboardResult[\"recent_evidence\"] = [];\n for (const node of allNodes) {\n const evidence: Evidence[] = JSON.parse(node.evidence);\n for (const ev of evidence) {\n allEvidence.push({\n node_id: node.id,\n node_summary: node.summary,\n type: ev.type,\n ref: ev.ref,\n agent: ev.agent,\n timestamp: ev.timestamp,\n });\n }\n }\n allEvidence.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n const recent_evidence = allEvidence.slice(0, evidenceLimit);\n\n // 4. All context_links aggregated and deduplicated\n const linkRows = db\n .prepare(\"SELECT context_links FROM nodes WHERE project = ? AND context_links != '[]'\")\n .all(project) as Array<{ context_links: string }>;\n\n const linkSet = new Set<string>();\n for (const row of linkRows) {\n const links: string[] = JSON.parse(row.context_links);\n for (const link of links) {\n linkSet.add(link);\n }\n }\n const context_links = [...linkSet].sort();\n\n // 5. Knowledge entries\n const knowledgeRows = db\n .prepare(\"SELECT key, content, updated_at FROM knowledge WHERE project = ? ORDER BY updated_at DESC\")\n .all(project) as Array<{ key: string; content: string; updated_at: string }>;\n\n // 6. Actionable tasks preview (like graph_next without claiming)\n const actionableRows = db\n .prepare(\n `SELECT n.id, n.summary, n.properties FROM nodes n\n WHERE n.project = ? AND n.resolved = 0 AND n.blocked = 0\n AND NOT EXISTS (\n SELECT 1 FROM nodes child WHERE child.parent = n.id AND child.resolved = 0\n )\n AND NOT EXISTS (\n SELECT 1 FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on'\n )\n ORDER BY\n COALESCE(CAST(json_extract(n.properties, '$.priority') AS REAL), 0) DESC,\n n.depth DESC,\n n.updated_at ASC\n LIMIT 10`\n )\n .all(project) as Array<{ id: string; summary: string; properties: string }>;\n\n const actionable = actionableRows.map((row) => ({\n id: row.id,\n summary: row.summary,\n properties: JSON.parse(row.properties),\n }));\n\n // 7. Recently resolved nodes (last 24h) — cross-session continuity\n const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();\n const recentlyResolvedRows = db\n .prepare(\n `SELECT id, summary, updated_at,\n (SELECT json_extract(value, '$.agent') FROM json_each(evidence) ORDER BY json_extract(value, '$.timestamp') DESC LIMIT 1) as last_agent\n FROM nodes\n WHERE project = ? AND resolved = 1 AND updated_at > ?\n ORDER BY updated_at DESC\n LIMIT 10`\n )\n .all(project, oneDayAgo) as Array<{ id: string; summary: string; updated_at: string; last_agent: string | null }>;\n\n const recently_resolved = recentlyResolvedRows.map((row) => ({\n id: row.id,\n summary: row.summary,\n resolved_at: row.updated_at,\n agent: row.last_agent ?? \"unknown\",\n }));\n\n // 8. Last activity timestamp\n const lastActivityRow = db\n .prepare(\"SELECT MAX(updated_at) as last FROM nodes WHERE project = ?\")\n .get(project) as { last: string | null };\n const last_activity = lastActivityRow.last;\n\n // Build hint based on project state\n let hint: string | undefined;\n if (root.discovery === \"pending\") {\n hint = `Discovery is pending. Interview the user to understand scope and goals, write knowledge entries with findings, then set discovery to \"done\" via graph_update before decomposing with graph_plan.`;\n } else if (actionable.length > 0) {\n const recentNote = recently_resolved.length > 0\n ? ` ${recently_resolved.length} task(s) resolved recently.`\n : \"\";\n hint = `${actionable.length} actionable task(s) ready.${recentNote} Use graph_next({ project: \"${project}\", claim: true }) to claim one.`;\n } else if (summary.unresolved > 0 && summary.actionable === 0) {\n hint = `All remaining tasks are blocked. Check dependencies with graph_query.`;\n } else if (summary.total <= 1 && root.discovery !== \"pending\") {\n hint = `Project is empty — use graph_plan to decompose the goal into tasks.`;\n }\n\n return {\n project,\n goal: root.summary,\n discovery: root.discovery,\n hint,\n summary,\n tree,\n recent_evidence,\n context_links,\n knowledge: knowledgeRows,\n recently_resolved,\n last_activity,\n actionable,\n };\n}\n","import { getProjectRoot, getChildren, getSubtreeProgress } from \"../nodes.js\";\nimport { requireString, optionalNumber } from \"../validate.js\";\nimport { EngineError } from \"../validate.js\";\nimport type { Node } from \"../types.js\";\n\n// [sl:ahq-BLHS9pJkJUlBZO92L] Full tree visualization — \"show me the whole tree\"\n\nexport interface TreeInput {\n project: string;\n depth?: number;\n}\n\ninterface TreeNode {\n id: string;\n summary: string;\n resolved: boolean;\n properties: Record<string, unknown>;\n progress?: { resolved: number; total: number };\n children?: TreeNode[];\n child_count?: number;\n}\n\nexport interface TreeResult {\n project: string;\n tree: TreeNode;\n stats: {\n total: number;\n resolved: number;\n unresolved: number;\n };\n}\n\nfunction buildTree(\n node: Node,\n currentDepth: number,\n maxDepth: number,\n stats: { total: number; resolved: number }\n): { treeNode: TreeNode; subtotal: number; subresolved: number } {\n stats.total++;\n if (node.resolved) stats.resolved++;\n\n const children = getChildren(node.id);\n const treeNode: TreeNode = {\n id: node.id,\n summary: node.summary,\n resolved: node.resolved,\n properties: node.properties,\n };\n\n let subtotal = 1;\n let subresolved = node.resolved ? 1 : 0;\n\n if (children.length === 0) return { treeNode, subtotal, subresolved };\n\n if (currentDepth < maxDepth) {\n treeNode.children = [];\n for (const child of children) {\n const result = buildTree(child, currentDepth + 1, maxDepth, stats);\n treeNode.children.push(result.treeNode);\n subtotal += result.subtotal;\n subresolved += result.subresolved;\n }\n } else {\n treeNode.child_count = children.length;\n // Count descendants via SQL when truncating at depth limit\n const progress = getSubtreeProgress(node.id);\n subtotal = progress.total;\n subresolved = progress.resolved;\n }\n\n treeNode.progress = { resolved: subresolved, total: subtotal };\n return { treeNode, subtotal, subresolved };\n}\n\nexport function handleTree(input: TreeInput): TreeResult {\n const project = requireString(input?.project, \"project\");\n const depth = optionalNumber(input?.depth, \"depth\", 1, 20) ?? 10;\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"project_not_found\", `Project not found: ${project}`);\n }\n\n const stats = { total: 0, resolved: 0 };\n const { treeNode } = buildTree(root, 0, depth, stats);\n\n return {\n project,\n tree: treeNode,\n stats: {\n total: stats.total,\n resolved: stats.resolved,\n unresolved: stats.total - stats.resolved,\n },\n };\n}\n","import { getDb } from \"../db.js\";\nimport { getProjectRoot, getProjectSummary, listProjects } from \"../nodes.js\";\nimport { optionalString } from \"../validate.js\";\nimport { EngineError } from \"../validate.js\";\nimport type { NodeRow, Evidence } from \"../types.js\";\n\nexport interface StatusInput {\n project?: string;\n}\n\nexport interface StatusResult {\n formatted: string;\n project: string;\n}\n\ninterface TreeEntry {\n id: string;\n parent: string | null;\n summary: string;\n resolved: boolean;\n blocked: boolean;\n blocked_reason: string | null;\n depth: number;\n child_count: number;\n dep_blocked: boolean;\n resolved_children: number;\n total_children: number;\n}\n\nfunction statusIcon(entry: TreeEntry): string {\n if (entry.resolved) return \"x\";\n if (entry.blocked) return \"!\";\n if (entry.dep_blocked) return \"~\";\n return \" \";\n}\n\nfunction progressBar(resolved: number, total: number, width: number = 20): string {\n if (total === 0) return \"\";\n const clamped = Math.min(resolved, total);\n const filled = Math.round((clamped / total) * width);\n const empty = width - filled;\n const bar = \"\\u2588\".repeat(filled) + \"\\u2591\".repeat(empty);\n const pct = Math.round((resolved / total) * 100);\n return `${bar} ${resolved}/${total} (${pct}%)`;\n}\n\nfunction timeAgo(isoDate: string): string {\n const diff = Date.now() - new Date(isoDate).getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n if (days === 1) return \"yesterday\";\n return `${days}d ago`;\n}\n\nexport function handleStatus(input: StatusInput): StatusResult | { projects: ReturnType<typeof listProjects>; hint: string } {\n const db = getDb();\n\n let project = optionalString(input?.project, \"project\");\n if (!project) {\n const projects = listProjects();\n if (projects.length === 0) {\n return {\n projects: [],\n hint: \"No projects yet. Create one with graph_open({ project: \\\"my-project\\\", goal: \\\"...\\\" }).\",\n };\n }\n if (projects.length === 1) {\n project = projects[0].project;\n } else {\n const lines: string[] = [\"# All Projects\", \"\"];\n for (const p of projects) {\n const taskCount = p.total > 0 ? p.total - 1 : 0; // exclude root\n const resolvedTasks = Math.min(p.resolved, taskCount);\n const bar = taskCount > 0 ? progressBar(resolvedTasks, taskCount) : \"empty\";\n lines.push(`**${p.project}** ${bar}`);\n lines.push(` ${p.summary}`);\n lines.push(\"\");\n }\n lines.push(\"_Specify a project name for details._\");\n return { projects, hint: lines.join(\"\\n\") };\n }\n }\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"project_not_found\", `Project not found: ${project}`);\n }\n\n const summary = getProjectSummary(project);\n\n // Get all non-root nodes with subtree counts and dependency info\n const rows = db.prepare(\n `SELECT n.id, n.parent, n.summary, n.resolved, n.blocked, n.blocked_reason, n.depth,\n (SELECT COUNT(*) FROM nodes c WHERE c.parent = n.id) as child_count,\n (SELECT COUNT(*) FROM nodes c WHERE c.parent = n.id AND c.resolved = 1) as resolved_children,\n (SELECT COUNT(*) FROM edges e\n JOIN nodes dep ON dep.id = e.to_node AND dep.resolved = 0\n WHERE e.from_node = n.id AND e.type = 'depends_on') as unresolved_deps\n FROM nodes n\n WHERE n.project = ? AND n.parent IS NOT NULL\n ORDER BY n.depth ASC, n.created_at ASC`\n ).all(project) as Array<{\n id: string;\n parent: string | null;\n summary: string;\n resolved: number;\n blocked: number;\n blocked_reason: string | null;\n depth: number;\n child_count: number;\n resolved_children: number;\n unresolved_deps: number;\n }>;\n\n const entries: TreeEntry[] = rows.map(r => ({\n id: r.id,\n parent: r.parent,\n summary: r.summary,\n resolved: r.resolved === 1,\n blocked: r.blocked === 1,\n blocked_reason: r.blocked_reason,\n depth: r.depth - 1, // relative to root\n child_count: r.child_count,\n dep_blocked: r.unresolved_deps > 0,\n resolved_children: r.resolved_children,\n total_children: r.child_count,\n }));\n\n // Build formatted output\n const lines: string[] = [];\n const taskCount = summary.total - 1; // exclude root\n\n // Header with progress bar\n lines.push(`# ${project}`);\n lines.push(\"\");\n lines.push(root.summary);\n lines.push(\"\");\n const resolvedTasks = Math.min(summary.resolved, taskCount);\n if (taskCount > 0) {\n lines.push(progressBar(resolvedTasks, taskCount));\n lines.push(`${summary.actionable} actionable | ${summary.blocked} blocked | ${summary.unresolved - summary.blocked - summary.actionable} waiting`);\n } else {\n lines.push(\"No tasks yet\");\n }\n lines.push(\"\");\n\n // Task tree with indentation and inline progress for parents\n if (entries.length > 0) {\n lines.push(\"## Tasks\");\n lines.push(\"\");\n for (const entry of entries) {\n const icon = statusIcon(entry);\n const prefix = \" \".repeat(entry.depth);\n let line = `${prefix}[${icon}] ${entry.summary}`;\n\n // Inline progress for parent nodes\n if (entry.child_count > 0) {\n const pct = Math.round((entry.resolved_children / entry.total_children) * 100);\n line += ` (${entry.resolved_children}/${entry.total_children} — ${pct}%)`;\n }\n\n // Blocked reason inline\n if (entry.blocked && entry.blocked_reason) {\n line += `\\n${prefix} ^ ${entry.blocked_reason}`;\n }\n\n lines.push(line);\n }\n lines.push(\"\");\n }\n\n // Recent activity — last 5 events across the project\n const recentEvents = db.prepare(\n `SELECT e.node_id, e.agent, e.action, e.timestamp, n.summary as node_summary\n FROM events e\n JOIN nodes n ON n.id = e.node_id\n WHERE n.project = ?\n ORDER BY e.timestamp DESC\n LIMIT 5`\n ).all(project) as Array<{\n node_id: string;\n agent: string;\n action: string;\n timestamp: string;\n node_summary: string;\n }>;\n\n if (recentEvents.length > 0) {\n lines.push(\"## Recent Activity\");\n lines.push(\"\");\n for (const ev of recentEvents) {\n lines.push(`- ${ev.action} **${ev.node_summary}** (${ev.agent}, ${timeAgo(ev.timestamp)})`);\n }\n lines.push(\"\");\n }\n\n // Blocked items\n const blocked = entries.filter(e => e.blocked && e.blocked_reason);\n if (blocked.length > 0) {\n lines.push(\"## Blocked\");\n lines.push(\"\");\n for (const b of blocked) {\n lines.push(`- **${b.summary}** — ${b.blocked_reason}`);\n }\n lines.push(\"\");\n }\n\n // Knowledge entries\n const knowledge = db.prepare(\n \"SELECT key, updated_at FROM knowledge WHERE project = ? ORDER BY updated_at DESC\"\n ).all(project) as Array<{ key: string; updated_at: string }>;\n if (knowledge.length > 0) {\n lines.push(\"## Knowledge\");\n lines.push(\"\");\n for (const k of knowledge) {\n lines.push(`- ${k.key} (${timeAgo(k.updated_at)})`);\n }\n lines.push(\"\");\n }\n\n return {\n formatted: lines.join(\"\\n\").trimEnd(),\n project,\n };\n}\n","import { nanoid } from \"nanoid\";\nimport { getDb } from \"../db.js\";\nimport { getProjectRoot } from \"../nodes.js\";\nimport { EngineError, requireString } from \"../validate.js\";\n\n// [sl:4PrMkE09nf6ptz8LLR9rW] Knowledge tools — persistent project-level knowledge store\n\ninterface KnowledgeRow {\n id: string;\n project: string;\n key: string;\n content: string;\n created_by: string;\n created_at: string;\n updated_at: string;\n}\n\n// --- graph_knowledge_write ---\n\nexport interface KnowledgeWriteInput {\n project: string;\n key: string;\n content: string;\n}\n\nexport function handleKnowledgeWrite(input: KnowledgeWriteInput, agent: string) {\n const project = requireString(input.project, \"project\");\n const key = requireString(input.key, \"key\");\n const content = requireString(input.content, \"content\");\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"not_found\", `Project '${project}' not found`);\n }\n\n const db = getDb();\n const now = new Date().toISOString();\n\n const existing = db\n .prepare(\"SELECT id FROM knowledge WHERE project = ? AND key = ?\")\n .get(project, key) as { id: string } | undefined;\n\n if (existing) {\n db.prepare(\n \"UPDATE knowledge SET content = ?, updated_at = ? WHERE id = ?\"\n ).run(content, now, existing.id);\n return { key, action: \"updated\" };\n } else {\n const id = nanoid();\n db.prepare(\n \"INSERT INTO knowledge (id, project, key, content, created_by, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)\"\n ).run(id, project, key, content, agent, now, now);\n return { key, action: \"created\" };\n }\n}\n\n// --- graph_knowledge_read ---\n\nexport interface KnowledgeReadInput {\n project: string;\n key?: string;\n}\n\nexport function handleKnowledgeRead(input: KnowledgeReadInput) {\n const project = requireString(input.project, \"project\");\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"not_found\", `Project '${project}' not found`);\n }\n\n const db = getDb();\n\n if (input.key) {\n const row = db\n .prepare(\"SELECT * FROM knowledge WHERE project = ? AND key = ?\")\n .get(project, input.key) as KnowledgeRow | undefined;\n\n if (!row) {\n throw new EngineError(\"not_found\", `Knowledge entry '${input.key}' not found in project '${project}'`);\n }\n\n return {\n key: row.key,\n content: row.content,\n updated_at: row.updated_at,\n created_by: row.created_by,\n };\n }\n\n // List all\n const rows = db\n .prepare(\"SELECT key, content, updated_at, created_by FROM knowledge WHERE project = ? ORDER BY updated_at DESC\")\n .all(project) as Array<{ key: string; content: string; updated_at: string; created_by: string }>;\n\n return { entries: rows };\n}\n\n// --- graph_knowledge_delete ---\n\nexport interface KnowledgeDeleteInput {\n project: string;\n key: string;\n}\n\nexport function handleKnowledgeDelete(input: KnowledgeDeleteInput) {\n const project = requireString(input.project, \"project\");\n const key = requireString(input.key, \"key\");\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"not_found\", `Project '${project}' not found`);\n }\n\n const db = getDb();\n const result = db\n .prepare(\"DELETE FROM knowledge WHERE project = ? AND key = ?\")\n .run(project, key);\n\n if (result.changes === 0) {\n throw new EngineError(\"not_found\", `Knowledge entry '${key}' not found in project '${project}'`);\n }\n\n return { key, action: \"deleted\" };\n}\n\n// --- graph_knowledge_search ---\n\nexport interface KnowledgeSearchInput {\n project: string;\n query: string;\n}\n\nexport function handleKnowledgeSearch(input: KnowledgeSearchInput) {\n const project = requireString(input.project, \"project\");\n const query = requireString(input.query, \"query\");\n\n const root = getProjectRoot(project);\n if (!root) {\n throw new EngineError(\"not_found\", `Project '${project}' not found`);\n }\n\n const db = getDb();\n const pattern = `%${query}%`;\n\n const rows = db\n .prepare(\n \"SELECT key, content, updated_at, created_by FROM knowledge WHERE project = ? AND (key LIKE ? OR content LIKE ?) ORDER BY updated_at DESC\"\n )\n .all(project, pattern, pattern) as Array<{ key: string; content: string; updated_at: string; created_by: string }>;\n\n return { entries: rows, query };\n}\n","import { getDb } from \"./db.js\";\nimport { EngineError } from \"./validate.js\";\nimport type { Tier } from \"./license.js\";\n\n// [sl:N0IDVJQIhENQFsov6-Lhg] Feature gates — enforce free vs pro limits\n\n// Limits relaxed — everything free while building user base (Phase 1: Acquisition)\nconst FREE_LIMITS = {\n maxProjects: Infinity,\n maxNodesPerProject: Infinity,\n onboardEvidenceLimit: 50,\n scopeEnabled: true,\n};\n\n/**\n * Check if creating nodes would exceed the free tier node limit.\n * Throws EngineError if limit would be exceeded.\n */\nexport function checkNodeLimit(tier: Tier, project: string, adding: number): void {\n if (tier === \"pro\") return;\n\n const db = getDb();\n const { count } = db\n .prepare(\"SELECT COUNT(*) as count FROM nodes WHERE project = ?\")\n .get(project) as { count: number };\n\n if (count + adding > FREE_LIMITS.maxNodesPerProject) {\n throw new EngineError(\n \"free_tier_limit\",\n `Free tier is limited to ${FREE_LIMITS.maxNodesPerProject} nodes per project. ` +\n `Current: ${count}, adding: ${adding}. Activate a license key to remove this limit.`\n );\n }\n}\n\n/**\n * Check if creating a new project would exceed the free tier project limit.\n * Throws EngineError if limit would be exceeded.\n */\nexport function checkProjectLimit(tier: Tier): void {\n if (tier === \"pro\") return;\n\n const db = getDb();\n const { count } = db\n .prepare(\"SELECT COUNT(*) as count FROM nodes WHERE parent IS NULL\")\n .get() as { count: number };\n\n if (count >= FREE_LIMITS.maxProjects) {\n throw new EngineError(\n \"free_tier_limit\",\n `Free tier is limited to ${FREE_LIMITS.maxProjects} project. ` +\n `Activate a license key to create unlimited projects.`\n );\n }\n}\n\n/**\n * Cap the evidence limit for graph_onboard on free tier.\n */\nexport function capEvidenceLimit(tier: Tier, requested?: number): number {\n const max = tier === \"pro\" ? (requested ?? 20) : FREE_LIMITS.onboardEvidenceLimit;\n return Math.min(requested ?? max, tier === \"pro\" ? 50 : FREE_LIMITS.onboardEvidenceLimit);\n}\n\n/**\n * Check if knowledge tools are allowed on the current tier.\n * Currently free for all — everything ungated during acquisition phase.\n */\nexport function checkKnowledgeTier(_tier: Tier): void {\n // All tiers allowed during acquisition phase\n return;\n}\n\n/**\n * Check if scope parameter is allowed.\n * Currently free for all during acquisition phase.\n */\nexport function checkScope(_tier: Tier, scope?: string): string | undefined {\n return scope;\n}\n"],"mappings":"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","names":["rows","result","lines","taskCount","resolvedTasks","nanoid","nanoid","getProjectRoot","getNode","listProjects"]}
|