@farukada/langchain-ts-gms 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +444 -0
  3. package/dist/app/governance/guardrails.d.ts +59 -0
  4. package/dist/app/governance/guardrails.d.ts.map +1 -0
  5. package/dist/app/governance/guardrails.js +73 -0
  6. package/dist/app/governance/guardrails.js.map +1 -0
  7. package/dist/app/graph/workflow.d.ts +329 -0
  8. package/dist/app/graph/workflow.d.ts.map +1 -0
  9. package/dist/app/graph/workflow.js +172 -0
  10. package/dist/app/graph/workflow.js.map +1 -0
  11. package/dist/app/planning/decomposeGoal.d.ts +31 -0
  12. package/dist/app/planning/decomposeGoal.d.ts.map +1 -0
  13. package/dist/app/planning/decomposeGoal.js +130 -0
  14. package/dist/app/planning/decomposeGoal.js.map +1 -0
  15. package/dist/app/planning/decompositionSchema.d.ts +83 -0
  16. package/dist/app/planning/decompositionSchema.d.ts.map +1 -0
  17. package/dist/app/planning/decompositionSchema.js +56 -0
  18. package/dist/app/planning/decompositionSchema.js.map +1 -0
  19. package/dist/app/state/schema.d.ts +57 -0
  20. package/dist/app/state/schema.d.ts.map +1 -0
  21. package/dist/app/state/schema.js +34 -0
  22. package/dist/app/state/schema.js.map +1 -0
  23. package/dist/config/env.d.ts +34 -0
  24. package/dist/config/env.d.ts.map +1 -0
  25. package/dist/config/env.js +38 -0
  26. package/dist/config/env.js.map +1 -0
  27. package/dist/domain/contracts.d.ts +192 -0
  28. package/dist/domain/contracts.d.ts.map +1 -0
  29. package/dist/domain/contracts.js +74 -0
  30. package/dist/domain/contracts.js.map +1 -0
  31. package/dist/domain/taskUtils.d.ts +42 -0
  32. package/dist/domain/taskUtils.d.ts.map +1 -0
  33. package/dist/domain/taskUtils.js +179 -0
  34. package/dist/domain/taskUtils.js.map +1 -0
  35. package/dist/infra/chat/chatModelProvider.d.ts +4 -0
  36. package/dist/infra/chat/chatModelProvider.d.ts.map +1 -0
  37. package/dist/infra/chat/chatModelProvider.js +12 -0
  38. package/dist/infra/chat/chatModelProvider.js.map +1 -0
  39. package/dist/infra/embeddings/embeddingProvider.d.ts +4 -0
  40. package/dist/infra/embeddings/embeddingProvider.d.ts.map +1 -0
  41. package/dist/infra/embeddings/embeddingProvider.js +11 -0
  42. package/dist/infra/embeddings/embeddingProvider.js.map +1 -0
  43. package/dist/infra/observability/tracing.d.ts +39 -0
  44. package/dist/infra/observability/tracing.d.ts.map +1 -0
  45. package/dist/infra/observability/tracing.js +93 -0
  46. package/dist/infra/observability/tracing.js.map +1 -0
  47. package/dist/infra/vector/goalMemoryRepository.d.ts +80 -0
  48. package/dist/infra/vector/goalMemoryRepository.d.ts.map +1 -0
  49. package/dist/infra/vector/goalMemoryRepository.js +239 -0
  50. package/dist/infra/vector/goalMemoryRepository.js.map +1 -0
  51. package/dist/infra/vector/qdrantClient.d.ts +14 -0
  52. package/dist/infra/vector/qdrantClient.d.ts.map +1 -0
  53. package/dist/infra/vector/qdrantClient.js +55 -0
  54. package/dist/infra/vector/qdrantClient.js.map +1 -0
  55. package/dist/lib/gmsTool.d.ts +27 -0
  56. package/dist/lib/gmsTool.d.ts.map +1 -0
  57. package/dist/lib/gmsTool.js +86 -0
  58. package/dist/lib/gmsTool.js.map +1 -0
  59. package/dist/lib/helpers.d.ts +50 -0
  60. package/dist/lib/helpers.d.ts.map +1 -0
  61. package/dist/lib/helpers.js +135 -0
  62. package/dist/lib/helpers.js.map +1 -0
  63. package/dist/lib/index.d.ts +32 -0
  64. package/dist/lib/index.d.ts.map +1 -0
  65. package/dist/lib/index.js +31 -0
  66. package/dist/lib/index.js.map +1 -0
  67. package/dist/lib/schemas/lifecycleSchemas.d.ts +151 -0
  68. package/dist/lib/schemas/lifecycleSchemas.d.ts.map +1 -0
  69. package/dist/lib/schemas/lifecycleSchemas.js +272 -0
  70. package/dist/lib/schemas/lifecycleSchemas.js.map +1 -0
  71. package/dist/lib/schemas/planningSchemas.d.ts +24 -0
  72. package/dist/lib/schemas/planningSchemas.d.ts.map +1 -0
  73. package/dist/lib/schemas/planningSchemas.js +60 -0
  74. package/dist/lib/schemas/planningSchemas.js.map +1 -0
  75. package/dist/lib/tools/getGoal.d.ts +9 -0
  76. package/dist/lib/tools/getGoal.d.ts.map +1 -0
  77. package/dist/lib/tools/getGoal.js +15 -0
  78. package/dist/lib/tools/getGoal.js.map +1 -0
  79. package/dist/lib/tools/getProgress.d.ts +9 -0
  80. package/dist/lib/tools/getProgress.d.ts.map +1 -0
  81. package/dist/lib/tools/getProgress.js +48 -0
  82. package/dist/lib/tools/getProgress.js.map +1 -0
  83. package/dist/lib/tools/getTask.d.ts +12 -0
  84. package/dist/lib/tools/getTask.d.ts.map +1 -0
  85. package/dist/lib/tools/getTask.js +26 -0
  86. package/dist/lib/tools/getTask.js.map +1 -0
  87. package/dist/lib/tools/listGoals.d.ts +36 -0
  88. package/dist/lib/tools/listGoals.d.ts.map +1 -0
  89. package/dist/lib/tools/listGoals.js +56 -0
  90. package/dist/lib/tools/listGoals.js.map +1 -0
  91. package/dist/lib/tools/listTasks.d.ts +47 -0
  92. package/dist/lib/tools/listTasks.d.ts.map +1 -0
  93. package/dist/lib/tools/listTasks.js +43 -0
  94. package/dist/lib/tools/listTasks.js.map +1 -0
  95. package/dist/lib/tools/planGoal.d.ts +52 -0
  96. package/dist/lib/tools/planGoal.d.ts.map +1 -0
  97. package/dist/lib/tools/planGoal.js +108 -0
  98. package/dist/lib/tools/planGoal.js.map +1 -0
  99. package/dist/lib/tools/replanGoal.d.ts +34 -0
  100. package/dist/lib/tools/replanGoal.d.ts.map +1 -0
  101. package/dist/lib/tools/replanGoal.js +78 -0
  102. package/dist/lib/tools/replanGoal.js.map +1 -0
  103. package/dist/lib/tools/searchTasks.d.ts +57 -0
  104. package/dist/lib/tools/searchTasks.d.ts.map +1 -0
  105. package/dist/lib/tools/searchTasks.js +94 -0
  106. package/dist/lib/tools/searchTasks.js.map +1 -0
  107. package/dist/lib/tools/updateGoal.d.ts +36 -0
  108. package/dist/lib/tools/updateGoal.d.ts.map +1 -0
  109. package/dist/lib/tools/updateGoal.js +55 -0
  110. package/dist/lib/tools/updateGoal.js.map +1 -0
  111. package/dist/lib/tools/updateTask.d.ts +28 -0
  112. package/dist/lib/tools/updateTask.d.ts.map +1 -0
  113. package/dist/lib/tools/updateTask.js +40 -0
  114. package/dist/lib/tools/updateTask.js.map +1 -0
  115. package/dist/lib/tools/validateGoalTree.d.ts +9 -0
  116. package/dist/lib/tools/validateGoalTree.d.ts.map +1 -0
  117. package/dist/lib/tools/validateGoalTree.js +22 -0
  118. package/dist/lib/tools/validateGoalTree.js.map +1 -0
  119. package/dist/lib/types.d.ts +48 -0
  120. package/dist/lib/types.d.ts.map +1 -0
  121. package/dist/lib/types.js +2 -0
  122. package/dist/lib/types.js.map +1 -0
  123. package/package.json +120 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Faruk Ada
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,444 @@
1
+ # Vector-centric Goal Management System built with LangChain TypeScript and LangGraph (GMS)
2
+
3
+ [![npm version](https://img.shields.io/npm/v/%40farukada%2Flangchain-ts-gms)](https://www.npmjs.com/package/@farukada/langchain-ts-gms)
4
+ [![Sponsor](https://img.shields.io/badge/Sponsor-FarukAda-ea4aaa?logo=githubsponsors)](https://github.com/sponsors/FarukAda)
5
+ ![Node >=22](https://img.shields.io/badge/node-%3E%3D22-339933)
6
+ ![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6)
7
+ ![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)
8
+ ![CI Ready](https://img.shields.io/badge/CI-fast%20%2B%20heavy-success)
9
+
10
+ GMS is a planning library for autonomous agents. It turns a goal into a hierarchical task graph (tasks + sub-tasks + dependencies), while your external agent remains responsible for execution.
11
+
12
+ ## Table of Contents
13
+
14
+ - [What This Package Is](#what-this-package-is)
15
+ - [Responsibility Boundary](#responsibility-boundary)
16
+ - [System Overview](#system-overview)
17
+ - [Quick Start](#quick-start)
18
+ - [Use as Library](#use-as-library)
19
+ - [Public API Reference](#public-api-reference)
20
+ - [Package Exports](#package-exports)
21
+ - [Tool Catalog](#tool-catalog)
22
+ - [Configuration Reference](#configuration-reference)
23
+ - [Production Considerations](#production-considerations)
24
+ - [Known Non-Goals](#known-non-goals)
25
+ - [Testing and CI](#testing-and-ci)
26
+ - [Documentation](#documentation)
27
+ - [Project Structure](#project-structure)
28
+ - [License](#license)
29
+
30
+ <a id="what-this-package-is"></a>
31
+
32
+ ## What This Package Is
33
+
34
+ - **Planning-only engine**: builds plans and validates goal trees.
35
+ - **Hierarchical model**: goal -> tasks -> sub-tasks with parent and dependency links.
36
+ - **LangChain-native**: exports tools via the `tool()` factory from `@langchain/core/tools`.
37
+ - **Vector-centric**: uses embeddings + Qdrant for semantic decomposition and retrieval.
38
+
39
+ <a id="responsibility-boundary"></a>
40
+
41
+ ## Responsibility Boundary
42
+
43
+ | Concern | Owned by GMS | Owned by your Agent |
44
+ | --------------------------------------------- | ------------ | ------------------- |
45
+ | Goal decomposition into tasks/sub-tasks | Yes | No |
46
+ | Task dependency-safe ordering | Yes | No |
47
+ | Goal/task retrieval and mutation tooling | Yes | No |
48
+ | Task execution (calling APIs, tools, scripts) | No | Yes |
49
+ | Runtime retries, side effects, actuation | No | Yes |
50
+
51
+ <a id="system-overview"></a>
52
+
53
+ ## System Overview
54
+
55
+ ```mermaid
56
+ flowchart LR
57
+ subgraph agentRuntime [AgentRuntime]
58
+ agent[LangChainAgent]
59
+ gmsTools[GmsTools]
60
+ executor[TaskExecutor]
61
+ end
62
+
63
+ subgraph gmsLibrary [GmsLibraryInProcess]
64
+ workflow[createGmsWorkflow]
65
+ planner[gms_plan_goal]
66
+ lifecycle[LifecycleTools]
67
+ end
68
+
69
+ subgraph backingServices [BackingServices]
70
+ qdrant[(Qdrant)]
71
+ embeddings[EmbeddingsProvider]
72
+ end
73
+
74
+ agent --> gmsTools
75
+ gmsTools --> planner
76
+ gmsTools --> lifecycle
77
+ planner --> workflow
78
+ workflow --> qdrant
79
+ workflow --> embeddings
80
+ planner -->|"returns plan JSON"| executor
81
+ ```
82
+
83
+ <a id="quick-start"></a>
84
+
85
+ ## Quick Start
86
+
87
+ ### Prerequisites
88
+
89
+ - Node.js >= 22
90
+ - npm
91
+ - Docker (for Qdrant)
92
+
93
+ ### Install
94
+
95
+ ```bash
96
+ npm add @farukada/langchain-ts-gms
97
+ ```
98
+
99
+ ### Development infrastructure
100
+
101
+ ```bash
102
+ # Start Qdrant (vector storage) and Ollama (LLM + embeddings)
103
+ docker compose up -d qdrant
104
+ docker compose --profile ollama up -d ollama
105
+ ```
106
+
107
+ Full operational steps and troubleshooting are in [docs/operations.md](./docs/operations.md).
108
+
109
+ <a id="use-as-library"></a>
110
+
111
+ ## Use as Library
112
+
113
+ Install:
114
+
115
+ ```bash
116
+ npm add @farukada/langchain-ts-gms
117
+ ```
118
+
119
+ ### Minimal registration
120
+
121
+ ```ts
122
+ import { createGmsToolFromEnv } from "@farukada/langchain-ts-gms/tool";
123
+
124
+ const planTool = await createGmsToolFromEnv();
125
+ agent.tools.push(planTool);
126
+ ```
127
+
128
+ ### Full lifecycle registration
129
+
130
+ ```ts
131
+ import {
132
+ createGmsToolFromEnv,
133
+ createGmsLifecycleToolsFromEnv,
134
+ } from "@farukada/langchain-ts-gms/tool";
135
+
136
+ const planTool = await createGmsToolFromEnv({
137
+ decomposeOptions: { topK: 5, maxDepth: 4 },
138
+ });
139
+ const lifecycleTools = await createGmsLifecycleToolsFromEnv();
140
+
141
+ agent.tools.push(planTool, ...lifecycleTools);
142
+ ```
143
+
144
+ #### `decomposeOptions`
145
+
146
+ | Option | Default | Purpose |
147
+ | ---------- | ------- | --------------------------------------------------------------------------------------- |
148
+ | `topK` | `5` | Number of capability vectors retrieved from Qdrant as context for the LLM decomposition |
149
+ | `maxDepth` | `4` | Maximum nesting depth for the hierarchical task tree |
150
+
151
+ Higher `topK` gives the planner more context but increases token cost. Lower `maxDepth` produces flatter plans.
152
+
153
+ ### Multi-tenancy
154
+
155
+ All tools support an optional `tenantId` field for data isolation. When set, capability search and goal listing are scoped to the given tenant:
156
+
157
+ ```ts
158
+ const planTool = await createGmsToolFromEnv();
159
+ // The agent passes tenantId when invoking the tool:
160
+ // { goalDescription: "...", tenantId: "org-123" }
161
+ ```
162
+
163
+ Qdrant payload indexes on `metadata.tenant_id` ensure filtered queries remain fast.
164
+
165
+ <a id="public-api-reference"></a>
166
+
167
+ ## Public API Reference
168
+
169
+ ### Main exports
170
+
171
+ - `createGmsPlanTool(deps)`: create planning tool (`gms_plan_goal`).
172
+ - `createGmsToolFromEnv(options)`: env-based planning tool factory.
173
+ - `createGmsLifecycleTools(deps)`: create retrieval/mutation/validation toolset.
174
+ - `createGmsLifecycleToolsFromEnv(options)`: env-based lifecycle factory.
175
+ - `createAllGmsToolsFromEnv(options)`: convenience factory for both planning + lifecycle tools with shared repository instances (recommended).
176
+ - `createPlan(input, deps)`: execute planning directly without tool wrapper.
177
+ - `createGmsWorkflow(deps)`: lower-level LangGraph workflow factory.
178
+
179
+ ### Key result shape (`gms_plan_goal`)
180
+
181
+ ```ts
182
+ {
183
+ version: "1.0",
184
+ goalId: string,
185
+ status: "planned" | "failed" | "human_approval_required",
186
+ tasks: Task[],
187
+ executionOrder: string[],
188
+ traceId?: string,
189
+ interrupt?: unknown,
190
+ error?: string
191
+ }
192
+ ```
193
+
194
+ ### Advanced dependency wiring (explicit repositories)
195
+
196
+ ```ts
197
+ import {
198
+ createGmsPlanTool,
199
+ GoalMemoryRepository,
200
+ createEmbeddingProvider,
201
+ CAPABILITIES_COLLECTION,
202
+ } from "@farukada/langchain-ts-gms";
203
+
204
+ const embeddings = createEmbeddingProvider();
205
+ const goalRepository = new GoalMemoryRepository({ embeddings });
206
+ const capabilityRepository = new GoalMemoryRepository({
207
+ embeddings,
208
+ collectionName: CAPABILITIES_COLLECTION,
209
+ });
210
+ await goalRepository.bootstrap();
211
+
212
+ const planTool = createGmsPlanTool({ goalRepository, capabilityRepository });
213
+ agent.tools.push(planTool);
214
+ ```
215
+
216
+ ### Production checkpointer
217
+
218
+ By default, the GMS workflow uses an **in-memory checkpointer** (`MemorySaver`) — state is lost on process restart. For production, inject a persistent checkpointer via `createGmsWorkflow`:
219
+
220
+ ```ts
221
+ import { SqliteSaver } from "@langchain/langgraph-checkpoint-sqlite";
222
+ import {
223
+ createGmsWorkflow,
224
+ GoalMemoryRepository,
225
+ createEmbeddingProvider,
226
+ createChatModelProvider,
227
+ } from "@farukada/langchain-ts-gms";
228
+
229
+ const checkpointer = SqliteSaver.fromConnString("./gms.db");
230
+ const embeddings = createEmbeddingProvider();
231
+ const goalRepository = new GoalMemoryRepository({ embeddings });
232
+
233
+ const workflow = createGmsWorkflow({
234
+ goalRepository,
235
+ checkpointer, // persists workflow state across restarts
236
+ });
237
+ ```
238
+
239
+ The `checkpointer` option is accepted by `createGmsWorkflow` (via the `WorkflowDeps` interface). The higher-level `createGmsPlanTool` and `*FromEnv` factories use `MemorySaver` internally; to override it, use `createGmsWorkflow` directly.
240
+
241
+ ### Human-in-the-Loop (HITL)
242
+
243
+ When a plan exceeds the guardrail task-count threshold (default: 10 tasks), the workflow triggers a LangGraph `interrupt` and returns `status: "human_approval_required"`:
244
+
245
+ ```ts
246
+ const result = JSON.parse(await planTool.invoke({ goalDescription: "..." }));
247
+
248
+ if (result.status === "human_approval_required") {
249
+ // result.interrupt contains: { action, goalId, taskCount, message }
250
+ // Present the plan to a human for review, then resume the workflow
251
+ // using the thread_id (result.goalId) via the compiled workflow.
252
+ }
253
+ ```
254
+
255
+ The interrupt payload shape:
256
+
257
+ ```ts
258
+ { action: "approve_plan", goalId: string, taskCount: number, message: string }
259
+ ```
260
+
261
+ ### Capability seeding
262
+
263
+ The planner searches the `gms_capabilities` Qdrant collection for existing capabilities to inform task decomposition. Without seeded capabilities, the LLM decomposes blindly — plans still work but are lower quality.
264
+
265
+ Seed capabilities using the same `GoalMemoryRepository`:
266
+
267
+ ```ts
268
+ import {
269
+ GoalMemoryRepository,
270
+ createEmbeddingProvider,
271
+ CAPABILITIES_COLLECTION,
272
+ } from "@farukada/langchain-ts-gms";
273
+
274
+ const embeddings = createEmbeddingProvider();
275
+ const capRepo = new GoalMemoryRepository({
276
+ embeddings,
277
+ collectionName: CAPABILITIES_COLLECTION,
278
+ });
279
+ await capRepo.bootstrap();
280
+
281
+ await capRepo.upsert({
282
+ id: crypto.randomUUID(),
283
+ description: "Deploy Node.js services to Kubernetes",
284
+ status: "planned",
285
+ priority: "medium",
286
+ tasks: [],
287
+ createdAt: new Date().toISOString(),
288
+ updatedAt: new Date().toISOString(),
289
+ });
290
+ ```
291
+
292
+ The more relevant capabilities you seed, the better the planner's task decomposition quality.
293
+
294
+ <a id="package-exports"></a>
295
+
296
+ ## Package Exports
297
+
298
+ The package exposes granular sub-path exports for tree-shaking and targeted imports:
299
+
300
+ | Sub-path | Provides |
301
+ | ---------------------------------------------- | ------------------------------------------------------------- |
302
+ | `@farukada/langchain-ts-gms` | All public APIs (tools, repos, domain utils, schemas) |
303
+ | `@farukada/langchain-ts-gms/tool` | `createGmsPlanTool`, `createGmsLifecycleTools`, env factories |
304
+ | `@farukada/langchain-ts-gms/tools/*` | Individual tool factories (`planGoal`, `getGoal`, etc.) |
305
+ | `@farukada/langchain-ts-gms/helpers` | Input normalization, pagination, tree filtering |
306
+ | `@farukada/langchain-ts-gms/types` | `GmsToolDeps`, `GmsPlanResult`, `AllGmsTools` |
307
+ | `@farukada/langchain-ts-gms/schemas/planning` | `GmsToolInputSchema` |
308
+ | `@farukada/langchain-ts-gms/schemas/lifecycle` | All lifecycle tool input schemas |
309
+
310
+ ### Example: import individual tools
311
+
312
+ ```ts
313
+ import { createGetGoalTool } from "@farukada/langchain-ts-gms/tools/getGoal";
314
+ import { createUpdateTaskTool } from "@farukada/langchain-ts-gms/tools/updateTask";
315
+ ```
316
+
317
+ <a id="tool-catalog"></a>
318
+
319
+ ## Tool Catalog
320
+
321
+ ### Planning tool
322
+
323
+ - `gms_plan_goal`: create a hierarchical plan and dependency-safe `executionOrder`.
324
+
325
+ ### Lifecycle tools
326
+
327
+ - `gms_get_goal`: fetch goal with full hierarchical tasks.
328
+ - `gms_get_task`: fetch a single task by `goalId` + `taskId`.
329
+ - `gms_list_tasks`: list tasks with filters and pagination.
330
+ - `gms_search_tasks`: search tasks by text, status, priority, dependency presence.
331
+ - `gms_list_goals`: list goals with filters and pagination.
332
+ - `gms_update_goal`: update goal fields.
333
+ - `gms_update_task`: update task status/result/error.
334
+ - `gms_validate_goal_tree`: validate hierarchy and dependency invariants.
335
+ - `gms_get_progress`: get progress counters and completion rate.
336
+ - `gms_replan_goal`: replan using `append`, `replace_failed`, or `replace_all`.
337
+
338
+ ### Tool input/output reference
339
+
340
+ | Tool | Required input | Output focus |
341
+ | ------------------------ | ------------------ | ---------------------------------------------------------- |
342
+ | `gms_plan_goal` | `goalDescription` | `goalId`, `status`, hierarchical `tasks`, `executionOrder` |
343
+ | `gms_get_goal` | `goalId` | Full goal object with nested tasks |
344
+ | `gms_get_task` | `goalId`, `taskId` | Single task + `parentId` + dependency context |
345
+ | `gms_list_tasks` | `goalId` | Filtered/paginated task list + `total` |
346
+ | `gms_search_tasks` | `goalId` | Query/filter-based paginated task results |
347
+ | `gms_list_goals` | none | Filtered/paginated goals + `total` |
348
+ | `gms_update_goal` | `goalId` | Updated goal status/metadata fields |
349
+ | `gms_update_task` | `goalId`, `taskId` | Updated task snapshot |
350
+ | `gms_validate_goal_tree` | `goalId` | Invariant validation result (`valid`, `issues`) |
351
+ | `gms_get_progress` | `goalId` | Counters + completion rate |
352
+ | `gms_replan_goal` | `goalId` | Replan diff (`replacedTaskIds`, `newTaskIds`) |
353
+
354
+ <a id="configuration-reference"></a>
355
+
356
+ ## Configuration Reference
357
+
358
+ Runtime environment variables:
359
+
360
+ | Variable | Required | Default | Purpose |
361
+ | ---------------------------- | -------- | -------------------------------------- | ---------------------------------------------------- |
362
+ | `NODE_ENV` | No | `development` | Runtime mode |
363
+ | `LOG_LEVEL` | No | `info` | Minimum log level (`debug`, `info`, `warn`, `error`) |
364
+ | `QDRANT_URL` | No | `http://localhost:6333` | Qdrant endpoint |
365
+ | `QDRANT_API_KEY` | No | - | Qdrant authentication key |
366
+ | `OLLAMA_HOST` | No | `http://localhost:11434` | Ollama server URL |
367
+ | `OLLAMA_EMBEDDING_MODEL` | No | `nomic-embed-text` | Default embedding model |
368
+ | `OLLAMA_CHAT_MODEL` | No | `llama3.2:3b` | Default chat/planning model |
369
+ | `GMS_OLLAMA_EMBEDDING_MODEL` | No | falls back to `OLLAMA_EMBEDDING_MODEL` | GMS-specific embedding model override |
370
+ | `GMS_OLLAMA_CHAT_MODEL` | No | falls back to `OLLAMA_CHAT_MODEL` | GMS-specific chat model override |
371
+ | `LANGCHAIN_TRACING_V2` | No | `false` | LangChain tracing toggle |
372
+ | `LANGCHAIN_API_KEY` | No | - | LangSmith API key when tracing is enabled |
373
+
374
+ <a id="production-considerations"></a>
375
+
376
+ ## Production Considerations
377
+
378
+ - **Checkpointer**: Replace the default in-memory `MemorySaver` with a persistent store. See [Production checkpointer](#production-checkpointer).
379
+ - **Capabilities**: Seed the `gms_capabilities` collection for higher-quality plans. See [Capability seeding](#capability-seeding).
380
+ - **HITL**: Handle the `human_approval_required` status if plans exceed guardrail thresholds. See [Human-in-the-Loop](#human-in-the-loop-hitl).
381
+ - **Multi-tenancy**: Pass `tenantId` to isolate data per organization. See [Multi-tenancy](#multi-tenancy).
382
+
383
+ <a id="known-non-goals"></a>
384
+
385
+ ## Known Non-Goals
386
+
387
+ - GMS does not execute tasks; it only plans and manages goal/task state.
388
+ - GMS does not lock/claim tasks for concurrent workers in this package version.
389
+ - GMS does not include audit history/event sourcing for every lifecycle mutation.
390
+ - GMS does not enforce organization-specific policy packs out of the box; guardrails are extensible.
391
+
392
+ <a id="testing-and-ci"></a>
393
+
394
+ ## Testing and CI
395
+
396
+ ### Local checks
397
+
398
+ | Command | Purpose |
399
+ | ----------------------- | -------------------------------------- |
400
+ | `npm test` | Unit tests (CI-safe, no external deps) |
401
+ | `npm run test:ci` | CI-safe unit test suite |
402
+ | `npm run test:watch` | Watch mode for development |
403
+ | `npm run test:coverage` | Unit tests with V8 coverage |
404
+
405
+ ### CI pipeline
406
+
407
+ ```mermaid
408
+ flowchart LR
409
+ sourceChange[PushOrPullRequest]
410
+ validate[Validate]
411
+ integrationAgent[IntegrationAgent]
412
+ publish[PublishToNpm]
413
+
414
+ sourceChange --> validate
415
+ validate -->|"push to main"| integrationAgent --> publish
416
+ ```
417
+
418
+ <a id="documentation"></a>
419
+
420
+ ## Documentation
421
+
422
+ - [Documentation Index](./docs/README.md)
423
+ - [Architecture](./docs/architecture.md)
424
+ - [Operations Runbook](./docs/operations.md)
425
+ - [ADR 0001: Vector-Centric GMS](./docs/adr/0001-vector-centric-gms.md)
426
+
427
+ <a id="project-structure"></a>
428
+
429
+ ## Project Structure
430
+
431
+ ```text
432
+ src/
433
+ ├── app/ # Workflow, planning, guardrails
434
+ ├── lib/ # Public library API + tools
435
+ ├── config/ # Environment configuration
436
+ ├── domain/ # Core contracts and task utilities
437
+ └── infra/ # Qdrant, embeddings, observability
438
+ ```
439
+
440
+ <a id="license"></a>
441
+
442
+ ## License
443
+
444
+ MIT
@@ -0,0 +1,59 @@
1
+ import type { Task } from "../../domain/contracts.js";
2
+ /**
3
+ * Default forbidden patterns (case-insensitive) that block execution.
4
+ *
5
+ * @todo Consider making forbidden patterns configurable per-tenant or
6
+ * per-environment via WorkflowDeps / GuardrailConfig. This would
7
+ * allow teams to add domain-specific blockers without code changes.
8
+ */
9
+ export declare const DEFAULT_FORBIDDEN_PATTERNS: readonly string[];
10
+ /** Default maximum task count before requiring human approval. */
11
+ export declare const DEFAULT_MAX_TASK_COUNT = 10;
12
+ export interface GuardrailOptions {
13
+ /** Patterns (case-insensitive substrings) that block execution. Defaults to `DEFAULT_FORBIDDEN_PATTERNS`. */
14
+ forbiddenPatterns?: readonly string[];
15
+ }
16
+ export interface HumanApprovalOptions {
17
+ /** Maximum number of tasks (including nested) before requiring human approval. Defaults to `DEFAULT_MAX_TASK_COUNT`. */
18
+ maxTaskCount?: number;
19
+ }
20
+ /**
21
+ * Policy guardrail: checks proposed tasks (including nested) against forbidden patterns.
22
+ * Returns { allowed: false, reason } if any task violates policy.
23
+ *
24
+ * @param tasks – hierarchical task tree
25
+ * @param options – override forbidden patterns
26
+ * @param preFlat – optional pre-flattened tasks to avoid redundant flattening
27
+ */
28
+ export declare function checkGuardrail(tasks: Task[], options?: GuardrailOptions, preFlat?: Task[]): {
29
+ allowed: true;
30
+ } | {
31
+ allowed: false;
32
+ reason: string;
33
+ };
34
+ /**
35
+ * Determines if a plan requires human approval (e.g. many tasks, high-risk).
36
+ * Counts all tasks in the hierarchy.
37
+ *
38
+ * @param tasks – hierarchical task tree
39
+ * @param options – override max task count
40
+ * @param preFlat – optional pre-flattened tasks to avoid redundant flattening
41
+ */
42
+ export declare function requiresHumanApproval(tasks: Task[], options?: HumanApprovalOptions, preFlat?: Task[]): boolean;
43
+ /** Combined guardrail + human approval evaluation. Flattens the task tree once. */
44
+ export interface GuardrailResult {
45
+ check: {
46
+ allowed: true;
47
+ } | {
48
+ allowed: false;
49
+ reason: string;
50
+ };
51
+ needsHumanApproval: boolean;
52
+ flatCount: number;
53
+ }
54
+ /**
55
+ * Evaluate both policy guardrails and human-approval requirements in a single
56
+ * pass over the flattened task tree.
57
+ */
58
+ export declare function evaluateGuardrails(tasks: Task[], guardOpts?: GuardrailOptions, approvalOpts?: HumanApprovalOptions): GuardrailResult;
59
+ //# sourceMappingURL=guardrails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../../src/app/governance/guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAGtD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAQvD,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,6GAA6G;IAC7G,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,oBAAoB;IACnC,wHAAwH;IACxH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,GAAE,gBAAqB,EAC9B,OAAO,CAAC,EAAE,IAAI,EAAE,GACf;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAgBxD;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,GAAE,oBAAyB,EAClC,OAAO,CAAC,EAAE,IAAI,EAAE,GACf,OAAO,CAMT;AAED,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE;QAAE,OAAO,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,IAAI,EAAE,EACb,SAAS,GAAE,gBAAqB,EAChC,YAAY,GAAE,oBAAyB,GACtC,eAAe,CAOjB"}
@@ -0,0 +1,73 @@
1
+ import { flattenTasks } from "../../domain/taskUtils.js";
2
+ /**
3
+ * Default forbidden patterns (case-insensitive) that block execution.
4
+ *
5
+ * @todo Consider making forbidden patterns configurable per-tenant or
6
+ * per-environment via WorkflowDeps / GuardrailConfig. This would
7
+ * allow teams to add domain-specific blockers without code changes.
8
+ */
9
+ export const DEFAULT_FORBIDDEN_PATTERNS = [
10
+ "delete production",
11
+ "drop database",
12
+ "overwrite production",
13
+ "rm -rf /",
14
+ "format c:",
15
+ "wipe all",
16
+ "destroy data",
17
+ ];
18
+ /** Default maximum task count before requiring human approval. */
19
+ export const DEFAULT_MAX_TASK_COUNT = 10;
20
+ /**
21
+ * Policy guardrail: checks proposed tasks (including nested) against forbidden patterns.
22
+ * Returns { allowed: false, reason } if any task violates policy.
23
+ *
24
+ * @param tasks – hierarchical task tree
25
+ * @param options – override forbidden patterns
26
+ * @param preFlat – optional pre-flattened tasks to avoid redundant flattening
27
+ */
28
+ export function checkGuardrail(tasks, options = {}, preFlat) {
29
+ const patterns = options.forbiddenPatterns ?? DEFAULT_FORBIDDEN_PATTERNS;
30
+ const flat = preFlat ?? flattenTasks(tasks);
31
+ const lower = (s) => s.toLowerCase();
32
+ for (const task of flat) {
33
+ const desc = lower(task.description);
34
+ for (const pattern of patterns) {
35
+ if (desc.includes(lower(pattern))) {
36
+ return {
37
+ allowed: false,
38
+ reason: `Task violates policy: "${pattern}" detected in "${task.description}"`,
39
+ };
40
+ }
41
+ }
42
+ }
43
+ return { allowed: true };
44
+ }
45
+ /**
46
+ * Determines if a plan requires human approval (e.g. many tasks, high-risk).
47
+ * Counts all tasks in the hierarchy.
48
+ *
49
+ * @param tasks – hierarchical task tree
50
+ * @param options – override max task count
51
+ * @param preFlat – optional pre-flattened tasks to avoid redundant flattening
52
+ */
53
+ export function requiresHumanApproval(tasks, options = {}, preFlat) {
54
+ const max = options.maxTaskCount ?? DEFAULT_MAX_TASK_COUNT;
55
+ const flat = preFlat ?? flattenTasks(tasks);
56
+ if (flat.length > max)
57
+ return true;
58
+ // Any task with critical or high risk level triggers human approval
59
+ return flat.some((t) => t.riskLevel === "critical" || t.riskLevel === "high");
60
+ }
61
+ /**
62
+ * Evaluate both policy guardrails and human-approval requirements in a single
63
+ * pass over the flattened task tree.
64
+ */
65
+ export function evaluateGuardrails(tasks, guardOpts = {}, approvalOpts = {}) {
66
+ const flat = flattenTasks(tasks);
67
+ const check = checkGuardrail(tasks, guardOpts, flat);
68
+ const needsHumanApproval = check.allowed
69
+ ? requiresHumanApproval(tasks, approvalOpts, flat)
70
+ : false;
71
+ return { check, needsHumanApproval, flatCount: flat.length };
72
+ }
73
+ //# sourceMappingURL=guardrails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.js","sourceRoot":"","sources":["../../../src/app/governance/guardrails.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAsB;IAC3D,mBAAmB;IACnB,eAAe;IACf,sBAAsB;IACtB,UAAU;IACV,WAAW;IACX,UAAU;IACV,cAAc;CACf,CAAC;AAEF,kEAAkE;AAClE,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAYzC;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,UAA4B,EAAE,EAC9B,OAAgB;IAEhB,MAAM,QAAQ,GAAG,OAAO,CAAC,iBAAiB,IAAI,0BAA0B,CAAC;IACzE,MAAM,IAAI,GAAG,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBAClC,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,0BAA0B,OAAO,kBAAkB,IAAI,CAAC,WAAW,GAAG;iBAC/E,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAa,EACb,UAAgC,EAAE,EAClC,OAAgB;IAEhB,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,IAAI,sBAAsB,CAAC;IAC3D,MAAM,IAAI,GAAG,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC;IACnC,oEAAoE;IACpE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC;AAChF,CAAC;AASD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,YAA8B,EAAE,EAChC,eAAqC,EAAE;IAEvC,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,kBAAkB,GAAG,KAAK,CAAC,OAAO;QACtC,CAAC,CAAC,qBAAqB,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC;QAClD,CAAC,CAAC,KAAK,CAAC;IACV,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;AAC/D,CAAC"}