@mc1global/opencode-jarvis 0.3.1 → 0.6.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 (94) hide show
  1. package/QUICK-GUIDE.md +53 -0
  2. package/README.md +308 -89
  3. package/dist/application/azure-sync/index.d.ts +2 -0
  4. package/dist/application/azure-sync/index.d.ts.map +1 -1
  5. package/dist/application/azure-sync/index.js +1 -0
  6. package/dist/application/azure-sync/index.js.map +1 -1
  7. package/dist/application/azure-sync/poll-service.d.ts +94 -0
  8. package/dist/application/azure-sync/poll-service.d.ts.map +1 -0
  9. package/dist/application/azure-sync/poll-service.js +227 -0
  10. package/dist/application/azure-sync/poll-service.js.map +1 -0
  11. package/dist/application/bootstrap/healthcheck-use-cases.d.ts +68 -0
  12. package/dist/application/bootstrap/healthcheck-use-cases.d.ts.map +1 -0
  13. package/dist/application/bootstrap/healthcheck-use-cases.js +303 -0
  14. package/dist/application/bootstrap/healthcheck-use-cases.js.map +1 -0
  15. package/dist/application/bootstrap/index.d.ts +10 -0
  16. package/dist/application/bootstrap/index.d.ts.map +1 -0
  17. package/dist/application/bootstrap/index.js +8 -0
  18. package/dist/application/bootstrap/index.js.map +1 -0
  19. package/dist/application/bootstrap/use-cases.d.ts +55 -0
  20. package/dist/application/bootstrap/use-cases.d.ts.map +1 -0
  21. package/dist/application/bootstrap/use-cases.js +355 -0
  22. package/dist/application/bootstrap/use-cases.js.map +1 -0
  23. package/dist/application/rag/dtos.d.ts +6 -0
  24. package/dist/application/rag/dtos.d.ts.map +1 -1
  25. package/dist/application/rag/use-cases.d.ts +9 -1
  26. package/dist/application/rag/use-cases.d.ts.map +1 -1
  27. package/dist/application/rag/use-cases.js +121 -56
  28. package/dist/application/rag/use-cases.js.map +1 -1
  29. package/dist/domain/azure-sync/entities.d.ts +59 -2
  30. package/dist/domain/azure-sync/entities.d.ts.map +1 -1
  31. package/dist/domain/azure-sync/entities.js +59 -0
  32. package/dist/domain/azure-sync/entities.js.map +1 -1
  33. package/dist/domain/azure-sync/index.d.ts +5 -5
  34. package/dist/domain/azure-sync/index.d.ts.map +1 -1
  35. package/dist/domain/azure-sync/index.js +2 -2
  36. package/dist/domain/azure-sync/index.js.map +1 -1
  37. package/dist/domain/azure-sync/ports.d.ts +2 -0
  38. package/dist/domain/azure-sync/ports.d.ts.map +1 -1
  39. package/dist/domain/azure-sync/repositories.d.ts +22 -2
  40. package/dist/domain/azure-sync/repositories.d.ts.map +1 -1
  41. package/dist/domain/azure-sync/value-objects.d.ts +12 -0
  42. package/dist/domain/azure-sync/value-objects.d.ts.map +1 -1
  43. package/dist/domain/azure-sync/value-objects.js +21 -0
  44. package/dist/domain/azure-sync/value-objects.js.map +1 -1
  45. package/dist/domain/config/value-objects.d.ts +4 -0
  46. package/dist/domain/config/value-objects.d.ts.map +1 -1
  47. package/dist/domain/config/value-objects.js +2 -0
  48. package/dist/domain/config/value-objects.js.map +1 -1
  49. package/dist/domain/rag/repositories.d.ts +42 -0
  50. package/dist/domain/rag/repositories.d.ts.map +1 -1
  51. package/dist/domain/rag/services.d.ts +10 -0
  52. package/dist/domain/rag/services.d.ts.map +1 -1
  53. package/dist/domain/rag/services.js +38 -0
  54. package/dist/domain/rag/services.js.map +1 -1
  55. package/dist/hooks/first-run-guide.d.ts +33 -0
  56. package/dist/hooks/first-run-guide.d.ts.map +1 -0
  57. package/dist/hooks/first-run-guide.js +58 -0
  58. package/dist/hooks/first-run-guide.js.map +1 -0
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +76 -27
  61. package/dist/index.js.map +1 -1
  62. package/dist/infrastructure/azure-sync/azure-devops-client.d.ts +1 -0
  63. package/dist/infrastructure/azure-sync/azure-devops-client.d.ts.map +1 -1
  64. package/dist/infrastructure/azure-sync/azure-devops-client.js +11 -13
  65. package/dist/infrastructure/azure-sync/azure-devops-client.js.map +1 -1
  66. package/dist/infrastructure/azure-sync/index.d.ts +1 -0
  67. package/dist/infrastructure/azure-sync/index.d.ts.map +1 -1
  68. package/dist/infrastructure/azure-sync/index.js +2 -1
  69. package/dist/infrastructure/azure-sync/index.js.map +1 -1
  70. package/dist/infrastructure/azure-sync/sqlite-event-repository.d.ts +31 -0
  71. package/dist/infrastructure/azure-sync/sqlite-event-repository.d.ts.map +1 -0
  72. package/dist/infrastructure/azure-sync/sqlite-event-repository.js +105 -0
  73. package/dist/infrastructure/azure-sync/sqlite-event-repository.js.map +1 -0
  74. package/dist/infrastructure/rag/file-discovery.d.ts.map +1 -1
  75. package/dist/infrastructure/rag/file-discovery.js +1 -0
  76. package/dist/infrastructure/rag/file-discovery.js.map +1 -1
  77. package/dist/infrastructure/rag/file-index-registry.d.ts +18 -0
  78. package/dist/infrastructure/rag/file-index-registry.d.ts.map +1 -0
  79. package/dist/infrastructure/rag/file-index-registry.js +67 -0
  80. package/dist/infrastructure/rag/file-index-registry.js.map +1 -0
  81. package/dist/mcp-server.js +68 -2
  82. package/dist/mcp-server.js.map +1 -1
  83. package/dist/tools/azure-sync-event-tools.d.ts +13 -0
  84. package/dist/tools/azure-sync-event-tools.d.ts.map +1 -0
  85. package/dist/tools/azure-sync-event-tools.js +100 -0
  86. package/dist/tools/azure-sync-event-tools.js.map +1 -0
  87. package/dist/tools/bootstrap-tools.d.ts +15 -0
  88. package/dist/tools/bootstrap-tools.d.ts.map +1 -0
  89. package/dist/tools/bootstrap-tools.js +113 -0
  90. package/dist/tools/bootstrap-tools.js.map +1 -0
  91. package/dist/tools/rag-tools.d.ts.map +1 -1
  92. package/dist/tools/rag-tools.js +9 -2
  93. package/dist/tools/rag-tools.js.map +1 -1
  94. package/package.json +3 -2
package/QUICK-GUIDE.md ADDED
@@ -0,0 +1,53 @@
1
+ # JARVIS Plugin — Quick Reference Card
2
+
3
+ > Full documentation: see [README.md](README.md) or https://www.npmjs.com/package/@mc1global/opencode-jarvis
4
+
5
+ ## Setup in 60 Seconds
6
+
7
+ ```bash
8
+ # 1. Prerequisites (macOS)
9
+ curl -fsSL https://bun.sh/install | bash
10
+ brew install ollama && ollama serve && ollama pull embeddinggemma
11
+
12
+ # 2. Add plugin to your project
13
+ echo '{ "plugin": ["@mc1global/opencode-jarvis"] }' > opencode.json
14
+
15
+ # 3. Launch OpenCode — JARVIS auto-bootstraps everything
16
+ opencode
17
+ ```
18
+
19
+ ## First Session Checklist
20
+
21
+ | Step | Tool / Command |
22
+ |---|---|
23
+ | Run diagnostics | `/healthcheck` |
24
+ | Index codebase | `rag-index` tool |
25
+ | Index docs | `rag-oracle-index` tool with `directory="obsidian-vault"` |
26
+ | View board | `kanban-board-view` tool |
27
+
28
+ ## Key Commands
29
+
30
+ | Command | What it does |
31
+ |---|---|
32
+ | `/healthcheck` | Diagnose environment + show fix commands |
33
+ | `/sync-azure` | Sync kanban with Azure DevOps |
34
+ | `/start-card CD-XXX` | Start working on a card (full lifecycle) |
35
+
36
+ ## Key Skills (load via `skill()` tool)
37
+
38
+ | Skill | What it teaches |
39
+ |---|---|
40
+ | `jarvis-onboarding` | Setup, tools, orientation |
41
+ | `jarvis-kanban` | Card lifecycle, grooming, sprints |
42
+ | `jarvis-azure-sync` | Azure DevOps sync workflow |
43
+
44
+ ## Files Created by JARVIS
45
+
46
+ | Path | In Git? | Purpose |
47
+ |---|---|---|
48
+ | `config/jarvis.yaml` | Yes | Configuration |
49
+ | `AGENTS.md` | Yes | Agent instructions |
50
+ | `obsidian-vault/` | Yes | Documentation |
51
+ | `.jarvis/jarvis.db` | No | Local database |
52
+ | `.jarvis/rag/` | No | RAG embeddings |
53
+ | `~/.jarvis/registry.db` | No | Global workspace registry |
package/README.md CHANGED
@@ -1,84 +1,54 @@
1
1
  # @mc1global/opencode-jarvis
2
2
 
3
- A native [OpenCode](https://opencode.ai) plugin providing multi-agent development infrastructure: session memory, kanban project management, governance guardrails, token metrics tracking, RAG semantic search, Obsidian vault management, domain map analysis, workspace registry, environment management, and structured data tools.
3
+ A native [OpenCode](https://opencode.ai) plugin providing multi-agent development infrastructure: session memory, kanban project management, governance guardrails, token metrics tracking, RAG semantic search, Obsidian vault management, domain map analysis, workspace registry, environment management, CI/CD pipelines, Azure DevOps sync, and structured data tools.
4
4
 
5
5
  Built with **Domain-Driven Design**, **SOLID principles**, and strict TypeScript.
6
6
 
7
- ## Features
7
+ ## Prerequisites
8
8
 
9
- ### 82 Tools across 11 categories
9
+ | Requirement | Purpose | Required? |
10
+ |---|---|---|
11
+ | [OpenCode](https://opencode.ai) CLI | Host runtime for the plugin | **Yes** |
12
+ | [Bun](https://bun.sh) >= 1.0 | Production runtime (bun:sqlite, MCP server) | **Yes** |
13
+ | Node.js >= 20 | Test runner (Jest + ESM) | Dev only |
14
+ | [Ollama](https://ollama.ai) | Local embedding generation for RAG | For RAG features |
15
+ | `embeddinggemma` model | Default embedding model (768 dims) | For RAG features |
16
+ | [Dagger CLI](https://docs.dagger.io/install) | Container-based CI/CD gate execution | Optional |
17
+ | [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) | Azure DevOps board sync | Optional |
10
18
 
11
- | Category | Count | Tools | Description |
12
- | ----------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
13
- | **Context Memory** | 8 | `context-session-*`, `context-todo-*`, `context-note-*`, `context-search` | Session lifecycle, todos, notes, cross-context search |
14
- | **Kanban Cards** | 12 | `kanban-card-create`, `kanban-card-move`, `kanban-card-list`, `kanban-card-get`, `kanban-card-assign`, `kanban-card-assign-sprint`, `kanban-card-assign-epic`, `kanban-card-estimate`, `kanban-card-criteria`, `kanban-card-criteria-meet`, `kanban-card-delete`, `kanban-card-brief` | Card state machine, assignments, estimation, acceptance criteria, deletion, context briefings |
15
- | **Kanban Board** | 15 | `kanban-sprint-*`, `kanban-epic-*`, `kanban-board-*`, `kanban-wip-check` | Sprint lifecycle, epic lifecycle (start/complete/update), board views, WIP limit checks |
16
- | **Governance** | 2 | `governance-validate`, `governance-policies` | Policy validation and rule introspection |
17
- | **Token Metrics** | 7 | `metrics-record`, `metrics-history`, `metrics-agent-report`, `metrics-card-report`, `metrics-sprint-report`, `metrics-summary`, `metrics-estimate` | Usage tracking, cost reports by agent/card/sprint, workspace summaries with recommendations |
18
- | **RAG** | 8 | `rag-search`, `rag-index`, `rag-snippet`, `rag-update`, `rag-delete`, `rag-status`, `rag-oracle-search`, `rag-oracle-index` | Semantic code search via Vectra + Ollama embeddings |
19
- | **Data** | 3 | `data-yaml-get`, `data-json-get`, `data-csv-query` | Structured data file access with dot-notation paths and CSV filtering |
20
- | **Vault** | 11 | `vault-doc-*`, `vault-frontmatter-*`, `vault-table-*`, `vault-manage` | Obsidian vault document management, frontmatter, tables, smart facade |
21
- | **Agent Communication** | 4 | `agent-sessions`, `agent-send`, `agent-notify`, `agent-dispatch` | Inter-session communication, card dispatch to other agents |
22
- | **Domain Map** | 2 | `domain-map-analyze`, `domain-map-view` | DDD domain map analysis (greenfield + legacy modes) |
23
- | **Workspace Registry** | 4 | `workspace-info`, `workspace-list`, `workspace-update`, `workspace-link` | Cross-project workspace registry with dependency tracking |
24
- | **Environment** | 6 | `env-init`, `env-create`, `env-list`, `env-status`, `env-merge`, `env-delete` | Isolated container-use environments with kanban card linkage |
19
+ ## Quick Start
25
20
 
26
- ### 4 Hooks
21
+ ### 1. Install prerequisites
27
22
 
28
- | Hook | Type | Description |
29
- | ---------------------- | --------------------------------- | ----------------------------------------------------- |
30
- | **Context Compacting** | `experimental.session.compacting` | Injects session context when context window compacts |
31
- | **Shell Environment** | `shell.env` | Injects JARVIS env vars into shell sessions |
32
- | **Guardrails** | `tool.execute.before` | Governance policy enforcement on tool invocations |
33
- | **Event Handlers** | `event` | Token usage tracking and cross-context event handling |
23
+ **macOS:**
34
24
 
35
- ### 10 Governance Policies
25
+ ```bash
26
+ # Bun (required — SQLite runtime)
27
+ curl -fsSL https://bun.sh/install | bash
36
28
 
37
- 6 core policies (file size, tool validation, grooming, WIP limits, test requirements, naming conventions) + 4 security policies (env dump prevention, shell env file access, sensitive file protection, shell sensitive command blocking).
29
+ # Ollama (required RAG semantic search)
30
+ brew install ollama
31
+ ollama serve # start the server
32
+ ollama pull embeddinggemma # download the embedding model
38
33
 
39
- ## Architecture
34
+ # Optional: Azure DevOps sync
35
+ brew install azure-cli && az login
40
36
 
37
+ # Optional: CI/CD pipeline execution
38
+ brew install dagger/tap/dagger
41
39
  ```
42
- jarvis-plugin/
43
- src/
44
- domain/ # Pure business logic, zero external deps
45
- shared/ # WorkspaceId, EntityId, Result<T>
46
- context-memory/ # Session, Todo, Note entities + services
47
- kanban/ # Card state machine, Sprint, Epic, Grooming
48
- governance/ # 10 policy rules, validation service
49
- token-metrics/ # Token usage tracking entities
50
- rag/ # RAG value objects, configuration
51
- vault/ # Vault document, section, table entities
52
- domain-map/ # Bounded context detection, domain analysis
53
- workspace-registry/ # Cross-project workspace registration
54
- environment/ # Container-use environment management
55
- application/ # Use cases with DTOs (9 bounded contexts)
56
- infrastructure/ # SQLite repos, Vectra, Ollama, filesystem adapters
57
- tools/ # 13 tool modules (82 tools total)
58
- hooks/ # 4 hooks (guardrails, compacting, events, shell-env)
59
- tests/ # 1145+ tests across 37 test suites
60
- obsidian-vault/ # 62+ documentation files
61
- ```
62
-
63
- **Key constraints:**
64
-
65
- - Max 500 lines per file (no exceptions)
66
- - Domain layer has zero external dependencies
67
- - ESM modules (`"type": "module"`)
68
- - `exactOptionalPropertyTypes: true` + `verbatimModuleSyntax: true`
69
- - 9 bounded contexts with strict DDD boundaries
70
-
71
- ## Installation
72
40
 
73
- ### Prerequisites
41
+ **Linux:**
74
42
 
75
- - [OpenCode](https://opencode.ai) CLI installed
76
- - Node.js >= 20
77
- - For RAG tools: [Ollama](https://ollama.ai) with `embeddinggemma` model
43
+ ```bash
44
+ curl -fsSL https://bun.sh/install | bash
45
+ curl -fsSL https://ollama.ai/install.sh | sh
46
+ ollama serve && ollama pull embeddinggemma
47
+ ```
78
48
 
79
- ### From npm (recommended)
49
+ ### 2. Add the plugin to your project
80
50
 
81
- Add to your project's `opencode.json`:
51
+ Create `opencode.json` in your project root:
82
52
 
83
53
  ```json
84
54
  {
@@ -88,7 +58,96 @@ Add to your project's `opencode.json`:
88
58
 
89
59
  OpenCode installs npm plugins automatically at startup. Requires access to the `@mc1global` org on npm.
90
60
 
91
- ### From local files (development)
61
+ ### 3. First launch (automatic)
62
+
63
+ Run `opencode` in your project directory. JARVIS initializes everything:
64
+
65
+ ```
66
+ What JARVIS creates automatically on first load:
67
+
68
+ .jarvis/ SQLite database + RAG indexes (local, gitignored)
69
+ config/jarvis.yaml Default configuration (commit this)
70
+ obsidian-vault/ Documentation skeleton (commit this)
71
+ AGENTS.md Agent operational guide (commit this)
72
+ ```
73
+
74
+ On the **first session**, the agent receives automatic guidance via system prompt injection to run initial diagnostics.
75
+
76
+ ### 4. First session — recommended steps
77
+
78
+ The agent should run these on first use (JARVIS prompts automatically):
79
+
80
+ 1. **`/healthcheck`** — Verify all subsystems
81
+ 2. **`rag-index`** tool — Index the codebase for semantic search
82
+ 3. **`rag-oracle-index`** tool with `directory="obsidian-vault"` — Index documentation
83
+ 4. **`kanban-board-view`** tool — See the kanban board
84
+
85
+ ### 5. Verify your setup
86
+
87
+ The `jarvis-healthcheck` tool shows all dependencies with **copy-paste fix commands**:
88
+
89
+ ```
90
+ [PASS] Bun Runtime: Bun is available (v1.1.38)
91
+ [PASS] Ollama Connectivity: Ollama is reachable at http://localhost:11434
92
+ [PASS] Embedding Model: Model "embeddinggemma" is available
93
+ [PASS] SQLite Database: Database file exists
94
+ [PASS] Configuration: config/jarvis.yaml exists
95
+ [PASS] RAG Index: RAG index contains 42006 documents
96
+ [WARN] Dagger CLI (optional): Dagger is not installed
97
+ FIX: brew install dagger/tap/dagger
98
+ [WARN] Azure CLI (optional): Azure CLI is not installed
99
+ FIX: brew install azure-cli && az login
100
+
101
+ Summary: 6 pass, 2 warn, 0 fail (8 total)
102
+ Status: HEALTHY
103
+ ```
104
+
105
+ ## What Lives Where
106
+
107
+ ### In Git (committed, shared with team)
108
+
109
+ ```
110
+ opencode.json Plugin declaration
111
+ config/jarvis.yaml Configuration (auto-created, then customized)
112
+ AGENTS.md Agent operational guide (auto-generated)
113
+ obsidian-vault/ Documentation vault
114
+ .opencode/skills/ Workflow skills for the agent
115
+ .opencode/commands/ Slash commands (/healthcheck, /sync-azure, /start-card)
116
+ ```
117
+
118
+ ### Local per machine (NOT in git)
119
+
120
+ ```
121
+ .jarvis/jarvis.db SQLite: kanban, sessions, metrics, sync mappings
122
+ .jarvis/rag/ Vectra vector store (RAG embeddings)
123
+ ```
124
+
125
+ ### Global (shared across all projects)
126
+
127
+ ```
128
+ ~/.jarvis/registry.db Workspace registry (cross-project)
129
+ ~/.cache/opencode/ Plugin npm cache (managed by OpenCode)
130
+ ```
131
+
132
+ ## Available Skills and Commands
133
+
134
+ ### Skills (loaded on demand via `skill()` tool)
135
+
136
+ | Skill | Description |
137
+ |---|---|
138
+ | `jarvis-onboarding` | Setup, healthcheck, RAG indexing, tool reference |
139
+ | `jarvis-kanban` | Card lifecycle, grooming, sprints, gate tasks |
140
+ | `jarvis-azure-sync` | Azure DevOps push/pull/sync, PR creation |
141
+
142
+ ### Commands (slash commands in any session)
143
+
144
+ | Command | Description |
145
+ |---|---|
146
+ | `/healthcheck` | Run diagnostics with actionable fix guidance |
147
+ | `/sync-azure` | Execute Azure DevOps sync workflow |
148
+ | `/start-card CD-XXX` | Start working on a kanban card (full lifecycle) |
149
+
150
+ ## Installation (Local Development)
92
151
 
93
152
  ```bash
94
153
  # Clone
@@ -111,59 +170,219 @@ npm run build
111
170
  }
112
171
  ```
113
172
 
114
- ### RAG Setup (Optional)
173
+ ## MCP Server Mode
174
+
175
+ JARVIS also runs as a standalone MCP server (stdio transport) for Claude Desktop, Cursor, or other MCP clients:
115
176
 
116
177
  ```bash
117
- # Pull embedding model for semantic search
118
- ollama pull embeddinggemma
178
+ bun run src/mcp-server.ts --directory /path/to/project
179
+ ```
180
+
181
+ Configure tool filtering in `config/jarvis.yaml`:
182
+
183
+ ```yaml
184
+ mcp-server:
185
+ transport: "stdio"
186
+ enabledTools: null # null = all tools, or list specific tool names
187
+ ```
188
+
189
+ ## Features
190
+
191
+ ### 112 Tools across 13 categories
192
+
193
+ | Category | Count | Key Tools |
194
+ |---|---|---|
195
+ | **Context Memory** | 8 | `context-session-*`, `context-todo-*`, `context-note-*`, `context-search` |
196
+ | **Kanban Cards** | 12 | `kanban-card-create/move/list/get/assign/estimate/criteria/delete/brief` |
197
+ | **Kanban Board** | 15 | `kanban-sprint-*`, `kanban-epic-*`, `kanban-board-*`, `kanban-wip-check` |
198
+ | **Governance** | 2 | `governance-validate`, `governance-policies` |
199
+ | **Token Metrics** | 7 | `metrics-record/history/agent-report/card-report/sprint-report/summary/estimate` |
200
+ | **RAG** | 8 | `rag-search/index/snippet/update/delete/status/oracle-search/oracle-index` |
201
+ | **Data** | 3 | `data-yaml-get`, `data-json-get`, `data-csv-query` |
202
+ | **Vault** | 11 | `vault-doc-*`, `vault-frontmatter-*`, `vault-table-*`, `vault-manage` |
203
+ | **Agent** | 8 | `agent-sessions/send/notify/dispatch`, `agent-register/profile/list/spawn` |
204
+ | **Domain Map** | 2 | `domain-map-analyze`, `domain-map-view` |
205
+ | **Workspace** | 4 | `workspace-info/list/update/link` |
206
+ | **Environment** | 6 | `env-init/create/list/status/merge/delete` |
207
+ | **Pipeline** | 12 | `pipeline-init/activate/cancel/retry/run/gate/status/list/template/scaffold` |
208
+ | **Azure Sync** | 10 | `azure-sync-*`, `azure-pr-*` |
209
+ | **Bootstrap** | 2 | `jarvis-bootstrap`, `jarvis-healthcheck` |
210
+
211
+ ### 5 Hooks
212
+
213
+ | Hook | Type | Description |
214
+ |---|---|---|
215
+ | **Context Compacting** | `experimental.session.compacting` | Injects session context when context window compacts |
216
+ | **First-Run Guide** | `experimental.chat.system.transform` | Injects setup instructions on first session |
217
+ | **Shell Environment** | `shell.env` | Injects JARVIS env vars into shell sessions |
218
+ | **Guardrails** | `tool.execute.before` | Governance policy enforcement on tool invocations |
219
+ | **Event Handlers** | `event` | Token usage tracking and cross-context event handling |
220
+
221
+ ### 13 Governance Policies
222
+
223
+ Runtime-enforced via `tool.execute.before` hook. Covers: CSV/YAML/env file access, force push protection, SQLite CLI blocking, destructive shell ops, credential file protection, and more.
224
+
225
+ ## Configuration
226
+
227
+ All settings live in `config/jarvis.yaml`. The `ConfigService` deep-merges YAML overrides over hardcoded defaults. Available sections:
228
+
229
+ ```yaml
230
+ # RAG embedding settings
231
+ rag:
232
+ ollama:
233
+ url: "http://localhost:11434"
234
+ model: "embeddinggemma"
235
+ dimensions: 768
236
+ markdownSplitByHeaders: true
237
+
238
+ # Azure DevOps integration
239
+ azure-sync:
240
+ organization: "" # Set to enable Azure sync
241
+ project: ""
242
+ repository: ""
243
+ authMethod: "az-cli"
244
+ pollEnabled: false
245
+ pollIntervalSecs: 60
246
+
247
+ # Kanban workflow enforcement
248
+ kanban:
249
+ minTransitionIntervalSecs: 30
250
+ gateTasks: # Per-phase gate definitions
251
+
252
+ # MCP server settings
253
+ mcp-server:
254
+ transport: "stdio"
255
+ enabledTools: null # null = all tools
256
+
257
+ # Pipeline CI/CD
258
+ pipeline:
259
+ defaultTimeoutMs: 300000
260
+ ```
261
+
262
+ Never read YAML files directly — use `data-yaml-get` tool or `ConfigService` getters.
263
+
264
+ ## Architecture
119
265
 
120
- # Index your workspace (from within OpenCode)
121
- # Use the rag-index tool
122
266
  ```
267
+ jarvis-plugin/
268
+ src/
269
+ domain/ # Pure business logic, zero external deps
270
+ shared/ # WorkspaceId, EntityId, Result<T>
271
+ context-memory/ # Session, Todo, Note entities + services
272
+ kanban/ # Card state machine, Sprint, Epic, Grooming
273
+ governance/ # 13 policy rules, validation service
274
+ token-metrics/ # Token usage tracking entities
275
+ rag/ # RAG value objects, domain services
276
+ vault/ # Vault document, section, table entities
277
+ domain-map/ # Bounded context detection, domain analysis
278
+ workspace-registry/ # Cross-project workspace registration
279
+ environment/ # Container-use environment management
280
+ agent-registry/ # Agent profile management
281
+ pipeline/ # CI/CD pipeline entities, gate enforcement
282
+ config/ # Configuration value objects + defaults
283
+ application/ # Use cases with DTOs (11 bounded contexts)
284
+ infrastructure/ # SQLite repos, Vectra, Ollama, FS adapters
285
+ tools/ # 15 tool modules (112 tools total)
286
+ hooks/ # 5 hooks (guardrails, compacting, first-run, events, shell-env)
287
+ tests/ # 2435+ tests across 80 test suites
288
+ obsidian-vault/ # Structured documentation
289
+ config/ # jarvis.yaml configuration
290
+ ```
291
+
292
+ **Key constraints:**
293
+
294
+ - Max 500 lines per file (no exceptions)
295
+ - Domain layer has zero external dependencies
296
+ - ESM modules (`"type": "module"`)
297
+ - `exactOptionalPropertyTypes: true` + `verbatimModuleSyntax: true`
298
+ - 11 bounded contexts with strict DDD boundaries
299
+ - Production runtime: Bun (`bun:sqlite`); Tests: Node.js + Jest
300
+
301
+ ## Storage
302
+
303
+ All data is stored locally:
304
+
305
+ - `.jarvis/jarvis.db` — SQLite database (sessions, todos, notes, kanban, metrics, environments, pipelines)
306
+ - `.jarvis/rag/<workspace>/` — Vectra vector stores (RAG indexes)
307
+ - `.jarvis/rag/<workspace>/index-manifest.json` — File index registry (incremental indexing)
308
+ - `~/.jarvis/registry.db` — Central workspace registry (cross-project)
309
+
310
+ The `JARVIS_HOME` environment variable overrides `~/.jarvis/` default.
123
311
 
124
312
  ## Development
125
313
 
126
314
  ```bash
127
- # Run tests
315
+ # Run all tests
128
316
  npm test
129
317
 
130
- # Type check
318
+ # Type check (zero errors required)
131
319
  npm run lint
132
320
 
321
+ # Build
322
+ npm run build
323
+
324
+ # Single test file
325
+ node --experimental-vm-modules node_modules/.bin/jest src/tests/application/healthcheck.test.ts --no-coverage
326
+
133
327
  # Watch mode
134
328
  npm run dev
135
329
 
136
- # Check file line counts
137
- npm run check:lines
330
+ # RAG index (standalone, bypasses MCP timeouts)
331
+ npx tsx scripts/rag-index.ts --clear
138
332
  ```
139
333
 
140
- ## Storage
334
+ ## Troubleshooting
141
335
 
142
- All data is stored locally:
336
+ **Ollama connection refused**
337
+ - Ensure Ollama is running: `ollama serve`
338
+ - Check URL in `config/jarvis.yaml` under `rag.ollama.url` (default: `http://localhost:11434`)
143
339
 
144
- - `.jarvis/jarvis.db` SQLite database (sessions, todos, notes, kanban, metrics, environments)
145
- - `.jarvis/rag/<workspace>/` Vectra vector stores (RAG indexes)
146
- - `~/.jarvis/registry.db` Central workspace registry (cross-project)
340
+ **Embedding model not found**
341
+ - Pull the model: `ollama pull embeddinggemma`
342
+ - Verify: `ollama list` should show `embeddinggemma`
147
343
 
148
- The `JARVIS_HOME` environment variable overrides `~/.jarvis/` default.
344
+ **RAG index empty after rag-index**
345
+ - Run `jarvis-healthcheck` to verify Ollama connectivity
346
+ - Try full reindex: use `rag-index` tool with `clear: true`
347
+
348
+ **Plugin not loading in OpenCode**
349
+ - Verify `opencode.json` has `"plugin": ["@mc1global/opencode-jarvis"]`
350
+ - Check `~/.cache/opencode/node_modules/` for the installed package
351
+ - Ensure Bun is installed (required for production runtime)
352
+
353
+ **MCP server fails to start**
354
+ - Ensure Bun is installed: `bun --version`
355
+ - Run manually: `bun run src/mcp-server.ts --directory .`
356
+
357
+ **Azure sync not working**
358
+ - Set `organization` and `project` in `config/jarvis.yaml` under `azure-sync`
359
+ - Ensure Azure CLI is authenticated: `az login`
360
+ - Test connectivity: use `azure-sync-config` tool
361
+
362
+ **tsc errors in development**
363
+ - Remember: `exactOptionalPropertyTypes` requires conditional spreading for optional props
364
+ - Use `import type` for type-only imports (`verbatimModuleSyntax`)
365
+ - Array indexing returns `T | undefined` (`noUncheckedIndexedAccess`)
149
366
 
150
367
  ## Dependencies
151
368
 
152
- | Dependency | Purpose |
153
- | -------------------------- | ---------------------------------------------- |
154
- | `better-sqlite3` | Local SQLite database for all persistent state |
155
- | `js-yaml` | YAML file parsing for data tools |
156
- | `vectra` | Local vector store for RAG semantic search |
157
- | `ollama` | Embedding generation via local Ollama models |
158
- | `@langchain/textsplitters` | Code-aware text chunking for RAG indexing |
159
- | `@opencode-ai/plugin` | OpenCode plugin SDK (peer dependency) |
369
+ | Dependency | Purpose |
370
+ |---|---|
371
+ | `bun:sqlite` | Local SQLite database (production) |
372
+ | `better-sqlite3` | SQLite for tests (Node.js) |
373
+ | `js-yaml` | YAML file parsing |
374
+ | `vectra` | Local vector store for RAG |
375
+ | `ollama` | Embedding generation via local Ollama |
376
+ | `@langchain/textsplitters` | Code-aware text chunking for RAG |
377
+ | `@opencode-ai/plugin` | OpenCode plugin SDK (peer dependency) |
378
+ | `@modelcontextprotocol/sdk` | MCP server protocol (optional) |
160
379
 
161
380
  ## Test Coverage
162
381
 
163
- - **1145+ tests** across 37 test suites
382
+ - **2,435+ tests** across 80 test suites
164
383
  - Domain, application, infrastructure, and tools layers tested
165
384
  - In-memory SQLite for fast, isolated integration tests
166
- - `tsc --noEmit` zero errors
385
+ - `tsc --noEmit` zero errors with all strict flags
167
386
 
168
387
  ## License
169
388
 
@@ -12,5 +12,7 @@ export { TaskPushUseCases, buildTaskLocalId, parseTaskLocalId } from "./task-pus
12
12
  export type { CardForTaskPush, TaskPushDeps, TaskPushResult } from "./task-push-use-cases.js";
13
13
  export type { EpicFieldInput, CardFieldInput, TaskFieldInput } from "./field-builders.js";
14
14
  export type { ExtractedCardData, ExtractedEpicData } from "./reverse-field-builder.js";
15
+ export { AzurePollService, SyncEventUseCases } from "./poll-service.js";
16
+ export type { PollServiceDeps, PollNotification, PollEventSummary, SyncEventResponse } from "./poll-service.js";
15
17
  export type { DiscoverRequest, DiscoverResponse, PushRequest, PushResponse, PullRequest, PullResponse, BidiSyncRequest, BidiSyncResponse, SyncStatusRequest, SyncStatusResponse, ConfigStatusResponse, CreatePrRequest, PrResponse, PrReviewerInfo, ListPrRequest, ListPrResponse, CommentRequest, CommentResponse, } from "./dtos.js";
16
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/application/azure-sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAChG,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC9F,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1F,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACvF,YAAY,EACV,eAAe,EAAE,gBAAgB,EACjC,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,YAAY,EACzB,eAAe,EAAE,gBAAgB,EACjC,iBAAiB,EAAE,kBAAkB,EAAE,oBAAoB,EAC3D,eAAe,EAAE,UAAU,EAAE,cAAc,EAC3C,aAAa,EAAE,cAAc,EAC7B,cAAc,EAAE,eAAe,GAChC,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/application/azure-sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAChG,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC9F,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1F,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAChH,YAAY,EACV,eAAe,EAAE,gBAAgB,EACjC,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,YAAY,EACzB,eAAe,EAAE,gBAAgB,EACjC,iBAAiB,EAAE,kBAAkB,EAAE,oBAAoB,EAC3D,eAAe,EAAE,UAAU,EAAE,cAAc,EAC3C,aAAa,EAAE,cAAc,EAC7B,cAAc,EAAE,eAAe,GAChC,MAAM,WAAW,CAAC"}
@@ -7,4 +7,5 @@ export { AzurePrUseCases } from "./pr-use-cases.js";
7
7
  export { AzureFieldBuilder } from "./field-builders.js";
8
8
  export { ReverseFieldBuilder } from "./reverse-field-builder.js";
9
9
  export { TaskPushUseCases, buildTaskLocalId, parseTaskLocalId } from "./task-push-use-cases.js";
10
+ export { AzurePollService, SyncEventUseCases } from "./poll-service.js";
10
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/application/azure-sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/application/azure-sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAIhG,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Azure Sync Application — Poll Service
3
+ *
4
+ * Background service that periodically queries Azure DevOps for changes
5
+ * to mapped work items. Detects field edits, state changes, and revision
6
+ * bumps by comparing current rev against stored azureRevision in mappings.
7
+ *
8
+ * Emits events via a callback when changes are detected, and persists
9
+ * SyncEvent entities for later inspection by the agent.
10
+ *
11
+ * SOLID: SRP — polling orchestration and change detection only
12
+ * SOLID: OCP — new event types can be added without modifying detection loop
13
+ * SOLID: DIP — depends on repository/port abstractions
14
+ */
15
+ import type { AzureDevOpsPort } from "../../domain/azure-sync/ports.js";
16
+ import type { SyncMappingRepository, SyncEventRepository } from "../../domain/azure-sync/repositories.js";
17
+ import type { SyncEventType } from "../../domain/azure-sync/value-objects.js";
18
+ /** Notification payload emitted when changes are detected. */
19
+ export interface PollNotification {
20
+ readonly eventCount: number;
21
+ readonly summary: string;
22
+ readonly events: readonly PollEventSummary[];
23
+ }
24
+ /** Individual event summary for notifications. */
25
+ export interface PollEventSummary {
26
+ readonly workItemId: number;
27
+ readonly eventType: SyncEventType;
28
+ readonly changedBy: string;
29
+ readonly localId: string;
30
+ }
31
+ /** Dependencies for the poll service. */
32
+ export interface PollServiceDeps {
33
+ readonly azureClient: AzureDevOpsPort;
34
+ readonly syncMappingRepo: SyncMappingRepository;
35
+ readonly syncEventRepo: SyncEventRepository;
36
+ readonly org: string;
37
+ readonly project: string;
38
+ /** Callback invoked when changes are detected. */
39
+ readonly onChangesDetected?: (notification: PollNotification) => void;
40
+ /** Callback for error logging. */
41
+ readonly onError?: (error: string) => void;
42
+ }
43
+ /**
44
+ * Background polling service for Azure DevOps change detection.
45
+ * Call start() to begin periodic polling, stop() to halt.
46
+ */
47
+ export declare class AzurePollService {
48
+ private readonly deps;
49
+ private readonly intervalSecs;
50
+ private timer;
51
+ private _running;
52
+ private _pollCount;
53
+ private _lastPollAt;
54
+ constructor(deps: PollServiceDeps, intervalSecs: number);
55
+ /** Whether the service is currently running. */
56
+ get running(): boolean;
57
+ /** Number of completed poll cycles. */
58
+ get pollCount(): number;
59
+ /** ISO timestamp of the last poll. */
60
+ get lastPollAt(): string | undefined;
61
+ /** Start the polling loop. No-op if already running. */
62
+ start(): void;
63
+ /** Stop the polling loop. */
64
+ stop(): void;
65
+ /** Execute a single poll cycle. Exposed for testing. */
66
+ poll(): Promise<PollNotification | undefined>;
67
+ }
68
+ /** DTOs for event tool responses. */
69
+ export interface SyncEventResponse {
70
+ readonly id: string;
71
+ readonly mappingId: string;
72
+ readonly azureWorkItemId: number;
73
+ readonly eventType: string;
74
+ readonly status: string;
75
+ readonly changedBy: string;
76
+ readonly changedFields: string;
77
+ readonly previousRevision: number;
78
+ readonly newRevision: number;
79
+ readonly detectedAt: string;
80
+ }
81
+ /** Use cases for managing sync events (list, acknowledge, dismiss). */
82
+ export declare class SyncEventUseCases {
83
+ private readonly eventRepo;
84
+ constructor(eventRepo: SyncEventRepository);
85
+ /** List pending events. */
86
+ listPending(limit?: number): Promise<readonly SyncEventResponse[]>;
87
+ /** List recent events (all statuses). */
88
+ listRecent(limit?: number): Promise<readonly SyncEventResponse[]>;
89
+ /** Acknowledge an event by ID. */
90
+ acknowledge(eventId: string): Promise<string>;
91
+ /** Dismiss an event by ID. */
92
+ dismiss(eventId: string): Promise<string>;
93
+ }
94
+ //# sourceMappingURL=poll-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poll-service.d.ts","sourceRoot":"","sources":["../../../src/application/azure-sync/poll-service.ts"],"names":[],"mappings":"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"}