ghost-dragon 4.2.1

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 (226) hide show
  1. package/.github/workflows/ci.yml +23 -0
  2. package/CHANGELOG.md +96 -0
  3. package/README.md +193 -0
  4. package/bootstrap.ps1 +83 -0
  5. package/bootstrap.sh +71 -0
  6. package/dist/agent/loop.d.ts +68 -0
  7. package/dist/agent/loop.d.ts.map +1 -0
  8. package/dist/agent/loop.js +135 -0
  9. package/dist/agent/mcp.d.ts +33 -0
  10. package/dist/agent/mcp.d.ts.map +1 -0
  11. package/dist/agent/mcp.js +107 -0
  12. package/dist/agent/session.d.ts +16 -0
  13. package/dist/agent/session.d.ts.map +1 -0
  14. package/dist/agent/session.js +55 -0
  15. package/dist/agent/skills.d.ts +36 -0
  16. package/dist/agent/skills.d.ts.map +1 -0
  17. package/dist/agent/skills.js +153 -0
  18. package/dist/agent/stack.d.ts +21 -0
  19. package/dist/agent/stack.d.ts.map +1 -0
  20. package/dist/agent/stack.js +158 -0
  21. package/dist/agent/task.d.ts +21 -0
  22. package/dist/agent/task.d.ts.map +1 -0
  23. package/dist/agent/task.js +45 -0
  24. package/dist/agent/tools.d.ts +44 -0
  25. package/dist/agent/tools.d.ts.map +1 -0
  26. package/dist/agent/tools.js +262 -0
  27. package/dist/agent/trace.d.ts +34 -0
  28. package/dist/agent/trace.d.ts.map +1 -0
  29. package/dist/agent/trace.js +72 -0
  30. package/dist/agent.d.ts +46 -0
  31. package/dist/agent.d.ts.map +1 -0
  32. package/dist/agent.js +103 -0
  33. package/dist/auth.d.ts +74 -0
  34. package/dist/auth.d.ts.map +1 -0
  35. package/dist/auth.js +116 -0
  36. package/dist/brain/anthropic.d.ts +19 -0
  37. package/dist/brain/anthropic.d.ts.map +1 -0
  38. package/dist/brain/anthropic.js +74 -0
  39. package/dist/brain/claude-cli.d.ts +20 -0
  40. package/dist/brain/claude-cli.d.ts.map +1 -0
  41. package/dist/brain/claude-cli.js +79 -0
  42. package/dist/brain/ghost-ember.d.ts +28 -0
  43. package/dist/brain/ghost-ember.d.ts.map +1 -0
  44. package/dist/brain/ghost-ember.js +97 -0
  45. package/dist/brain/index.d.ts +22 -0
  46. package/dist/brain/index.d.ts.map +1 -0
  47. package/dist/brain/index.js +95 -0
  48. package/dist/brain/openai-compat.d.ts +21 -0
  49. package/dist/brain/openai-compat.d.ts.map +1 -0
  50. package/dist/brain/openai-compat.js +119 -0
  51. package/dist/brain/router/classify.d.ts +23 -0
  52. package/dist/brain/router/classify.d.ts.map +1 -0
  53. package/dist/brain/router/classify.js +160 -0
  54. package/dist/brain/router/execute.d.ts +23 -0
  55. package/dist/brain/router/execute.d.ts.map +1 -0
  56. package/dist/brain/router/execute.js +84 -0
  57. package/dist/brain/router/index.d.ts +26 -0
  58. package/dist/brain/router/index.d.ts.map +1 -0
  59. package/dist/brain/router/index.js +118 -0
  60. package/dist/brain/router/routing-memory.d.ts +27 -0
  61. package/dist/brain/router/routing-memory.d.ts.map +1 -0
  62. package/dist/brain/router/routing-memory.js +77 -0
  63. package/dist/brain/router/select.d.ts +32 -0
  64. package/dist/brain/router/select.d.ts.map +1 -0
  65. package/dist/brain/router/select.js +146 -0
  66. package/dist/brain/router/two-hop.d.ts +23 -0
  67. package/dist/brain/router/two-hop.d.ts.map +1 -0
  68. package/dist/brain/router/two-hop.js +39 -0
  69. package/dist/brain/router/verify.d.ts +37 -0
  70. package/dist/brain/router/verify.d.ts.map +1 -0
  71. package/dist/brain/router/verify.js +111 -0
  72. package/dist/brain/types.d.ts +55 -0
  73. package/dist/brain/types.d.ts.map +1 -0
  74. package/dist/brain/types.js +16 -0
  75. package/dist/brain/worker.d.ts +27 -0
  76. package/dist/brain/worker.d.ts.map +1 -0
  77. package/dist/brain/worker.js +71 -0
  78. package/dist/commands/ai.d.ts +24 -0
  79. package/dist/commands/ai.d.ts.map +1 -0
  80. package/dist/commands/ai.js +137 -0
  81. package/dist/commands/alerts.d.ts +19 -0
  82. package/dist/commands/alerts.d.ts.map +1 -0
  83. package/dist/commands/alerts.js +114 -0
  84. package/dist/commands/billing.d.ts +13 -0
  85. package/dist/commands/billing.d.ts.map +1 -0
  86. package/dist/commands/billing.js +55 -0
  87. package/dist/commands/chat.d.ts +22 -0
  88. package/dist/commands/chat.d.ts.map +1 -0
  89. package/dist/commands/chat.js +422 -0
  90. package/dist/commands/config.d.ts +18 -0
  91. package/dist/commands/config.d.ts.map +1 -0
  92. package/dist/commands/config.js +136 -0
  93. package/dist/commands/doctor.d.ts +11 -0
  94. package/dist/commands/doctor.d.ts.map +1 -0
  95. package/dist/commands/doctor.js +73 -0
  96. package/dist/commands/global.d.ts +11 -0
  97. package/dist/commands/global.d.ts.map +1 -0
  98. package/dist/commands/global.js +253 -0
  99. package/dist/commands/keep.d.ts +12 -0
  100. package/dist/commands/keep.d.ts.map +1 -0
  101. package/dist/commands/keep.js +58 -0
  102. package/dist/commands/lifecycle.d.ts +17 -0
  103. package/dist/commands/lifecycle.d.ts.map +1 -0
  104. package/dist/commands/lifecycle.js +267 -0
  105. package/dist/commands/login.d.ts +16 -0
  106. package/dist/commands/login.d.ts.map +1 -0
  107. package/dist/commands/login.js +234 -0
  108. package/dist/commands/maintenance.d.ts +12 -0
  109. package/dist/commands/maintenance.d.ts.map +1 -0
  110. package/dist/commands/maintenance.js +76 -0
  111. package/dist/commands/mcp.d.ts +16 -0
  112. package/dist/commands/mcp.d.ts.map +1 -0
  113. package/dist/commands/mcp.js +56 -0
  114. package/dist/commands/memory.d.ts +13 -0
  115. package/dist/commands/memory.d.ts.map +1 -0
  116. package/dist/commands/memory.js +218 -0
  117. package/dist/commands/osint.d.ts +14 -0
  118. package/dist/commands/osint.d.ts.map +1 -0
  119. package/dist/commands/osint.js +161 -0
  120. package/dist/commands/pentest.d.ts +13 -0
  121. package/dist/commands/pentest.d.ts.map +1 -0
  122. package/dist/commands/pentest.js +131 -0
  123. package/dist/commands/scale.d.ts +14 -0
  124. package/dist/commands/scale.d.ts.map +1 -0
  125. package/dist/commands/scale.js +191 -0
  126. package/dist/commands/serve.d.ts +16 -0
  127. package/dist/commands/serve.d.ts.map +1 -0
  128. package/dist/commands/serve.js +167 -0
  129. package/dist/commands/tui.d.ts +17 -0
  130. package/dist/commands/tui.d.ts.map +1 -0
  131. package/dist/commands/tui.js +138 -0
  132. package/dist/commands/wyrm.d.ts +20 -0
  133. package/dist/commands/wyrm.d.ts.map +1 -0
  134. package/dist/commands/wyrm.js +274 -0
  135. package/dist/config.d.ts +67 -0
  136. package/dist/config.d.ts.map +1 -0
  137. package/dist/config.js +54 -0
  138. package/dist/index.d.ts +16 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +85 -0
  141. package/dist/manifest.d.ts +31 -0
  142. package/dist/manifest.d.ts.map +1 -0
  143. package/dist/manifest.js +83 -0
  144. package/dist/ui.d.ts +57 -0
  145. package/dist/ui.d.ts.map +1 -0
  146. package/dist/ui.js +174 -0
  147. package/dist/utils.d.ts +33 -0
  148. package/dist/utils.d.ts.map +1 -0
  149. package/dist/utils.js +155 -0
  150. package/dist/wyrm/mcp.d.ts +37 -0
  151. package/dist/wyrm/mcp.d.ts.map +1 -0
  152. package/dist/wyrm/mcp.js +137 -0
  153. package/docs/SYSTEM-PREMORTEM.md +397 -0
  154. package/dragon-manifest.toml +241 -0
  155. package/dragon.py +177 -0
  156. package/install/launchd/lk.ghosts.dragonkeep.plist +57 -0
  157. package/install/systemd/dragonkeep.service +40 -0
  158. package/media/dragon-silver-lockup.svg +931 -0
  159. package/media/dragon-silver-mark.svg +931 -0
  160. package/media/dragon-silver.png +0 -0
  161. package/package.json +45 -0
  162. package/specs/001-godmode/constitution.md +54 -0
  163. package/specs/001-godmode/plan.md +30 -0
  164. package/specs/001-godmode/spec.md +64 -0
  165. package/specs/001-godmode/tasks.md +35 -0
  166. package/specs/002-premortem-positioning/premortem.md +211 -0
  167. package/src/agent/loop.ts +165 -0
  168. package/src/agent/mcp.ts +92 -0
  169. package/src/agent/session.ts +48 -0
  170. package/src/agent/skills.ts +138 -0
  171. package/src/agent/stack.ts +154 -0
  172. package/src/agent/task.ts +55 -0
  173. package/src/agent/tools.ts +255 -0
  174. package/src/agent/trace.ts +76 -0
  175. package/src/agent.ts +114 -0
  176. package/src/auth.ts +133 -0
  177. package/src/brain/anthropic.ts +83 -0
  178. package/src/brain/claude-cli.ts +78 -0
  179. package/src/brain/ghost-ember.ts +94 -0
  180. package/src/brain/index.ts +99 -0
  181. package/src/brain/openai-compat.ts +115 -0
  182. package/src/brain/router/classify.ts +167 -0
  183. package/src/brain/router/execute.ts +80 -0
  184. package/src/brain/router/index.ts +125 -0
  185. package/src/brain/router/routing-memory.ts +71 -0
  186. package/src/brain/router/select.ts +156 -0
  187. package/src/brain/router/two-hop.ts +62 -0
  188. package/src/brain/router/verify.ts +123 -0
  189. package/src/brain/types.ts +61 -0
  190. package/src/brain/worker.ts +72 -0
  191. package/src/commands/ai.ts +144 -0
  192. package/src/commands/alerts.ts +131 -0
  193. package/src/commands/billing.ts +59 -0
  194. package/src/commands/chat.ts +318 -0
  195. package/src/commands/config.ts +137 -0
  196. package/src/commands/doctor.ts +71 -0
  197. package/src/commands/global.ts +256 -0
  198. package/src/commands/keep.ts +67 -0
  199. package/src/commands/lifecycle.ts +273 -0
  200. package/src/commands/login.ts +184 -0
  201. package/src/commands/maintenance.ts +54 -0
  202. package/src/commands/mcp.ts +57 -0
  203. package/src/commands/memory.ts +229 -0
  204. package/src/commands/osint.ts +171 -0
  205. package/src/commands/pentest.ts +140 -0
  206. package/src/commands/scale.ts +185 -0
  207. package/src/commands/serve.ts +171 -0
  208. package/src/commands/tui.ts +126 -0
  209. package/src/commands/wyrm.ts +269 -0
  210. package/src/config.ts +93 -0
  211. package/src/index.ts +92 -0
  212. package/src/manifest.ts +104 -0
  213. package/src/ui.ts +188 -0
  214. package/src/utils.ts +153 -0
  215. package/src/wyrm/mcp.ts +130 -0
  216. package/test/auth.test.ts +70 -0
  217. package/test/brain.test.ts +39 -0
  218. package/test/security.test.ts +104 -0
  219. package/test/skills.test.ts +38 -0
  220. package/test/ui.test.ts +46 -0
  221. package/tsconfig.json +19 -0
  222. package/worker/package-lock.json +1527 -0
  223. package/worker/package.json +17 -0
  224. package/worker/src/index.ts +76 -0
  225. package/worker/tsconfig.json +15 -0
  226. package/worker/wrangler.toml +26 -0
@@ -0,0 +1,397 @@
1
+ # Dragon Stack · System Pre-Mortem
2
+
3
+ Scope: the **whole stack** under Ghost Protocol's offensive-security
4
+ banner — PhantomDragon AI (engine), PhantomDragon Control (operator
5
+ dashboard), DragonNet (OSINT investigation platform), Phantom Memory
6
+ (persistent engagement memory), Wyrm (cross-tool memory backbone),
7
+ and Dragon CLI (unified shell). This pre-mortem imagines it's 12
8
+ months from now and the integrated stack has been abandoned.
9
+
10
+ This is a *system* pre-mortem. Individual products have their own
11
+ under `~/Git Projects/<product>/docs/PRE-MORTEM.md`. Here we focus on
12
+ what breaks **between** them.
13
+
14
+ > Re-read at every quarterly review, before any cross-tool refactor,
15
+ > and after any incident that crosses product boundaries. Update
16
+ > probabilities as we learn.
17
+
18
+ ---
19
+
20
+ ## #1 · Cross-system schema drift
21
+
22
+ **Probability: HIGH · Impact: SEVERE**
23
+
24
+ Each product evolves on its own cadence. PhantomDragon's
25
+ `findings.json` shape, DragonNet's `entities` table, Phantom Memory's
26
+ SQLite schema, and Wyrm's `data` records all carry implicit
27
+ contracts. There is no single source of truth and no contract test.
28
+
29
+ **How it kills us:** PhantomDragon v3.6 renames `meta.target` to
30
+ `meta.target_url`. Phantom Memory still reads `meta.target`. The
31
+ `/v1/memory` endpoint silently records empty targets for new scans.
32
+ Three months later, the operator notices "no memory for upalis.com"
33
+ even though they scanned it last week. Trust evaporates.
34
+
35
+ **Controls in v1:**
36
+ - Phantom Memory uses defensive `data.get("meta", {}).get(...)` so a
37
+ field rename produces nulls, not crashes.
38
+ - The dragon CLI's `dragon status` could compare versions across
39
+ products (not yet implemented).
40
+
41
+ **Mitigations deferred:**
42
+ - A single canonical schema package (e.g. `@dragon/shared-schemas`)
43
+ imported by every product. Engine emits via Pydantic, dashboards
44
+ consume via TypeScript types generated from JSON Schema.
45
+ - `dragon doctor` contract test that runs sample data from each
46
+ product's outputs through the other products' parsers; fails
47
+ CI when shapes mismatch.
48
+ - A version field in every persisted record (`meta.schema_version`)
49
+ with explicit upgrade paths.
50
+
51
+ **Death-avoidance metric:** Days since a schema field rename
52
+ without coordinating updates across all consumers. >0 days =
53
+ yellow; >7 days = red.
54
+
55
+ ---
56
+
57
+ ## #2 · The unified-CLI mirage
58
+
59
+ **Probability: HIGH · Impact: MEDIUM**
60
+
61
+ `dragon` exists. But if operators settle into Tool A's native UI
62
+ (PhantomDragon Control's dashboard) and Tool B's native CLI
63
+ (PhantomDragon's `phantomdragon.py`), the unified CLI never gets the
64
+ exercise it needs. Bug rot sets in. The cross-tool flows that only
65
+ the CLI knows about silently break.
66
+
67
+ **How it kills us:** Six months in, `dragon scan` has rotted because
68
+ the PhantomDragon CLI has new flags the wrapper doesn't pass through.
69
+ `dragon osint` doesn't exist because no one needed it badly enough
70
+ to add it. Operators conclude the CLI was a nice idea that didn't
71
+ land.
72
+
73
+ **Controls in v1:**
74
+ - Dragon CLI is the *recommended* entry point in the onboarding
75
+ doc.
76
+ - `dragon scan` flags mirror the engine's flag surface 1:1.
77
+
78
+ **Mitigations deferred:**
79
+ - The dragon CLI should be the **only** documented entry point in
80
+ external docs (README, blog posts, customer-facing). Native
81
+ binaries remain available but are internal.
82
+ - `dragon up` one-command bootstrap so new operators never know
83
+ the underlying ports.
84
+ - `dragon status` becomes the canonical "is everything OK" view —
85
+ no operator should ever need to `ss -tlnp | grep`.
86
+
87
+ **Death-avoidance metric:** Ratio of CLI invocations to native
88
+ binary invocations across operator sessions. Target ≥3:1 by month 3.
89
+
90
+ ---
91
+
92
+ ## #3 · Two memory systems, one operator
93
+
94
+ **Probability: HIGH · Impact: HIGH**
95
+
96
+ Phantom Memory (`~/.copilot/phantom-memory.db`, SQLite) and Wyrm
97
+ (`~/.copilot/session-store.db`, also SQLite + HTTP :3333) both claim
98
+ to be the cross-tool memory store. Today they don't overlap — Phantom
99
+ Memory holds scan/OSINT/credential data, Wyrm holds session/quest/
100
+ context data. But the boundary is fuzzy.
101
+
102
+ **How it kills us:** A future feature wants to query "what targets
103
+ has Ryan worked on this quarter?" — both DBs have a partial answer.
104
+ The query is built against Wyrm. Two months later someone builds
105
+ the same query against Phantom Memory because they didn't know
106
+ Wyrm had it. Two truths, no reconciliation, and now the AI brain
107
+ gets *different* context depending on which path it took.
108
+
109
+ **Controls in v1:**
110
+ - Phantom Memory is documented as "scan + OSINT + creds";
111
+ Wyrm is "sessions + quests + decisions". Different concerns.
112
+
113
+ **Mitigations deferred:**
114
+ - One-paragraph "where data lives" doc in `dragon-cli/docs/`.
115
+ - A federated query endpoint (`dragon memory query "..."` that hits
116
+ both stores and merges results with provenance).
117
+ - A long-term decision: either fold Phantom Memory *into* Wyrm
118
+ as a new entity kind, or extract Wyrm's session/quest layer
119
+ into Phantom Memory. One store, two access paths.
120
+
121
+ **Death-avoidance metric:** Number of queries that get a different
122
+ answer from Phantom Memory vs Wyrm for the same logical question.
123
+ Should be 0.
124
+
125
+ ---
126
+
127
+ ## #4 · No multi-tenant isolation
128
+
129
+ **Probability: MEDIUM · Impact: SEVERE (for PTaaS)**
130
+
131
+ PhantomDragon Control's `reports/` is single-operator. Phantom Memory
132
+ is single-DB. DragonNet has investigation membership and roles
133
+ (good) but no account isolation at the DB level. The day Ghost
134
+ Protocol takes its second PTaaS customer, this becomes a problem.
135
+
136
+ **How it kills us:** Customer A logs in and sees scans that include
137
+ PII from Customer B's penetration test (because Phantom Memory's
138
+ "all targets" view doesn't know about tenancy). One incident →
139
+ contract terminated, GDPR exposure, reputational hit.
140
+
141
+ **Controls in v1:**
142
+ - Deploys are explicitly single-operator. No customer is live yet.
143
+ - PhantomDragon PTaaS (separate spec-kit project at
144
+ `~/Git Projects/phantomdragon-ptaas/`) does account-level isolation
145
+ in its own DB.
146
+
147
+ **Mitigations deferred:**
148
+ - Phantom Memory gains an `operator_id` / `tenant_id` foreign key
149
+ on every table.
150
+ - PhantomDragon Control gains auth + per-operator reports/ dir
151
+ before any external deploy.
152
+ - The dragon CLI carries a `--operator` context that gates queries.
153
+
154
+ **Death-avoidance metric:** Days until first non-Ryan operator gets
155
+ access to the stack. Becomes red the moment that's <30 days away
156
+ without multi-tenant work shipped.
157
+
158
+ ---
159
+
160
+ ## #5 · Single-laptop disaster
161
+
162
+ **Probability: MEDIUM · Impact: SEVERE**
163
+
164
+ The entire engagement memory — every scan finding, every OSINT
165
+ entity, every credential exposure across years — lives in one
166
+ SQLite file on Ryan's laptop. Disk failure = years gone.
167
+
168
+ **How it kills us:** Laptop dies. Ryan reformats. Phantom Memory
169
+ was "going to be backed up next week." Engagements with paying
170
+ customers reference finding IDs that are now permanently lost.
171
+
172
+ **Controls in v1:**
173
+ - Wyrm has R2 cloud backup (Wyrm task #171).
174
+ - `reports/` is a git-tracked directory in some cases.
175
+
176
+ **Mitigations deferred:**
177
+ - `dragon backup` command that snapshots Phantom Memory + reports/
178
+ + DragonNet's Postgres dump + Wyrm DB to encrypted R2.
179
+ - Nightly cron via systemd timer (operator opt-in).
180
+ - `dragon restore` for round-trip verification.
181
+
182
+ **Death-avoidance metric:** Days since last successful Phantom
183
+ Memory backup to a different physical drive. <7 = green, 7-30 =
184
+ yellow, >30 = red.
185
+
186
+ ---
187
+
188
+ ## #6 · Auth fragmentation
189
+
190
+ **Probability: MEDIUM · Impact: MEDIUM**
191
+
192
+ DragonNet: magic-link + JWT + TOTP. PhantomDragon Control: no auth
193
+ (binds to localhost). Wyrm: bearer token from `~/.wyrm/http-config.json`.
194
+ The dragon CLI: trusts the operator's shell.
195
+
196
+ **How it kills us:** First deploy to a LAN — PhantomDragon Control
197
+ suddenly readable by anyone in the office network. The cross-link
198
+ from PhantomDragon Control → DragonNet does *not* pass auth state,
199
+ so the operator has to re-login every time they click "OSINT this".
200
+ That friction means they stop using the integration.
201
+
202
+ **Controls in v1:**
203
+ - Documented as "localhost-only" until auth ships.
204
+ - DragonNet's auth is solid — magic-link + TOTP + JWT session.
205
+
206
+ **Mitigations deferred:**
207
+ - Adopt DragonNet's auth as the canonical layer; PhantomDragon
208
+ Control consumes its sessions via shared cookie.
209
+ - A common origin (`http://localhost:4000` reverse-proxied to all
210
+ services) so the same session cookie applies everywhere.
211
+ - The dragon CLI does an auth handshake on `dragon up`.
212
+
213
+ **Death-avoidance metric:** Days since the stack ran with any
214
+ service bound to 0.0.0.0 without auth. Becomes red the moment any
215
+ such bind exists in production.
216
+
217
+ ---
218
+
219
+ ## #7 · Darkweb collectors create legal exposure
220
+
221
+ **Probability: MEDIUM · Impact: HIGH**
222
+
223
+ TORWATCH crawls operator-supplied .onion seeds. PASTEDRAGNET probes
224
+ pastebin.com mirrors. TELEGAZER scrapes Telegram public channels.
225
+ NIGHTGLASS reads operator-supplied breach corpora. Each of these is
226
+ defensible on its own — they touch only public previews or operator-
227
+ provided data. But the *combination* could be read by a hostile
228
+ prosecutor as "systematic collection of breach data."
229
+
230
+ **How it kills us:** Sri Lanka's Computer Crimes Act 2007 is broad
231
+ enough that a determined regulator could call any of this "unauthorized
232
+ access" if the seed list includes a credential market URL or the
233
+ breach corpus came from somewhere borderline. Defense cost alone
234
+ sinks Ghost Protocol.
235
+
236
+ **Controls in v1:**
237
+ - Every darkweb collector has an explicit operator-supplied input
238
+ (env var or breach DB).
239
+ - TORWATCH refuses to fetch without an explicit Tor proxy set.
240
+ - No collector invents seeds, channels, or breach data.
241
+
242
+ **Mitigations deferred:**
243
+ - A `dragon legal pre-flight <jurisdiction>` command that prints
244
+ the legal posture for each enabled collector in that
245
+ jurisdiction.
246
+ - Explicit per-investigation consent flag: "I represent that the
247
+ target authorizes this investigation."
248
+ - Tamper-evident audit log of every collector run (already in
249
+ DragonNet's `audit` table; surface it via UI).
250
+ - Geofenced collectors that auto-disable in jurisdictions where
251
+ they're risky (operator-configurable).
252
+
253
+ **Death-avoidance metric:** Number of investigations where a
254
+ darkweb collector ran without an authorization record in the
255
+ audit log. Should be 0.
256
+
257
+ ---
258
+
259
+ ## #8 · AI brain context bloat
260
+
261
+ **Probability: MEDIUM · Impact: MEDIUM**
262
+
263
+ `phantom_memory.ai_brain_context()` truncates at 4000 chars. For a
264
+ target with 3 scans this is generous. For a target with 50 scans
265
+ across 2 years, 500 OSINT entities, and 1000 credential exposures,
266
+ 4000 chars is nowhere near enough. The brain ends up with a
267
+ truncated, randomly-ordered view of history.
268
+
269
+ **How it kills us:** A heavy long-term target's scan produces worse
270
+ results in month 18 than in month 1 because the context system can't
271
+ prioritize what matters. Operator concludes "the AI got dumber"
272
+ when actually we got smarter — we just don't know how to use the
273
+ extra knowledge.
274
+
275
+ **Controls in v1:**
276
+ - 4000-char cap is documented as MVP.
277
+ - Persistent findings + last-resolved are surfaced first
278
+ (highest signal).
279
+
280
+ **Mitigations deferred:**
281
+ - Tiered context: critical findings → high → medium-recency tech →
282
+ recent OSINT → credential exposures. Each tier has its own cap.
283
+ - Vector embeddings on findings so the brain pulls semantically
284
+ relevant prior findings, not just chronological ones.
285
+ - A `dragon memory context <target> --max-tokens N` flag for
286
+ larger budgets.
287
+
288
+ **Death-avoidance metric:** Average char usage of brain context as
289
+ % of cap. >85% means we're saturating; should expand or tier.
290
+
291
+ ---
292
+
293
+ ## #9 · Cross-tool data flow has no replay
294
+
295
+ **Probability: LOW · Impact: HIGH**
296
+
297
+ When PhantomDragon Control pushes a scan to Phantom Memory and
298
+ Phantom Memory pushes to Wyrm, the flow is fire-and-forget. If any
299
+ step fails (Phantom Memory disk full, Wyrm offline, network blip),
300
+ data silently goes missing. No queue. No retry.
301
+
302
+ **How it kills us:** Disk-full or Wyrm offline for an hour during a
303
+ scan. The scan completes successfully in PhantomDragon's reports/.
304
+ Phantom Memory ingestion fails silently. Operator notices weeks
305
+ later that "memory has gaps." Cannot reconstruct which scans were
306
+ ingested without parsing every reports/ dir against memory.
307
+
308
+ **Controls in v1:**
309
+ - `phantom_memory.ingest_reports_dir()` is idempotent — re-running
310
+ recovers any missed scans.
311
+ - The `control_api.py` startup auto-runs `ingest_reports_dir()`.
312
+
313
+ **Mitigations deferred:**
314
+ - A persistent retry queue (`~/.copilot/phantom-memory-queue.json`)
315
+ for failed pushes to Wyrm.
316
+ - `dragon memory verify` command that diffs reports/ against
317
+ Phantom Memory and reports any gaps.
318
+ - `dragon memory reingest --since 2026-04-01` for time-bounded
319
+ recovery.
320
+
321
+ **Death-avoidance metric:** Count of reports/ scans not present in
322
+ Phantom Memory after a `dragon status memory` check. Should be 0.
323
+
324
+ ---
325
+
326
+ ## #10 · Operator-onboarding cliff
327
+
328
+ **Probability: LOW · Impact: HIGH (if hiring)**
329
+
330
+ The stack assumes the operator (Ryan) built it. A new operator
331
+ joining tomorrow would face: 3 repos to clone, 5 services to start,
332
+ 2 database systems to migrate, 1 unified CLI to install but with
333
+ spotty docs, and a mental model that lives only in Ryan's head.
334
+
335
+ **How it kills us:** Ghost Protocol hires a second operator. They
336
+ spend 3 days getting the local stack running. They never quite
337
+ understand which features go through which dashboard. They produce
338
+ slower, worse engagements for the first month. Either Ryan refuses
339
+ to hire again, or the new operator quits.
340
+
341
+ **Controls in v1:**
342
+ - `dragon init` auto-detects product paths.
343
+ - This pre-mortem + the skills under `~/.copilot/skills/` exist.
344
+
345
+ **Mitigations deferred:**
346
+ - `dragon up` one-command bootstrap (clones missing repos, runs
347
+ migrations, starts services, opens the dashboard).
348
+ - A 1-page operator playbook ("here's how an engagement flows
349
+ through the stack").
350
+ - Onboarding video / Loom (operator-facing, 10 min).
351
+ - `dragon doctor` to verify the local install matches the
352
+ reference shape.
353
+
354
+ **Death-avoidance metric:** Time-to-first-real-scan for a new
355
+ operator. Target < 30 minutes from `git clone dragon-cli` to a
356
+ successful `dragon scan example.com`.
357
+
358
+ ---
359
+
360
+ ## Death-avoidance dashboard
361
+
362
+ Track monthly. Anything red triggers a remediation session.
363
+
364
+ | Metric | Green | Yellow | Red |
365
+ |---|---|---|---|
366
+ | Days since cross-tool schema rename without coordination | 0 | 1-7 | >7 |
367
+ | Ratio of dragon-CLI to native-CLI invocations | ≥3:1 | 1-3:1 | <1:1 |
368
+ | Phantom Memory vs Wyrm divergence for same logical query | 0 | 1-3 | >3 |
369
+ | Days until first non-Ryan operator | >30 | 7-30 | <7 |
370
+ | Days since last Phantom Memory backup to second drive | <7 | 7-30 | >30 |
371
+ | Days running 0.0.0.0 without auth | 0 (localhost only) | — | any |
372
+ | Investigations with darkweb collectors lacking authorization record | 0 | 1-3 | >3 |
373
+ | Avg brain-context char usage as % of cap | <70% | 70-90% | >90% |
374
+ | Reports not present in Phantom Memory after status check | 0 | 1-3 | >3 |
375
+ | Time-to-first-scan for new operator | <30min | 30-90min | >90min |
376
+
377
+ ## Re-read schedule
378
+
379
+ - Every quarterly review
380
+ - Before any cross-tool refactor
381
+ - After any incident crossing product boundaries
382
+ - When any metric crosses into yellow
383
+
384
+ ## The single thread
385
+
386
+ Eight of these ten causes-of-death converge on the same root: **the
387
+ stack treats its products as independent, but operators experience
388
+ them as one system.** Schema drift, the CLI mirage, the two-memory
389
+ problem, auth fragmentation, AI context bloat, the data-flow replay
390
+ gap, and the onboarding cliff all stem from missing federation
391
+ discipline.
392
+
393
+ The fix is structural, not feature-by-feature: **the dragon CLI must
394
+ be the federation layer.** Every cross-tool flow goes through it.
395
+ Every health check, every backup, every schema contract, every auth
396
+ handshake. The CLI is not a convenience — it's the integration
397
+ substrate.
@@ -0,0 +1,241 @@
1
+ # Ghost Protocol · Dragon Stack Manifest
2
+ # Declares every product in the stack so `dragon up`, `dragon update`,
3
+ # `dragon install`, and `dragon stop` can manage the whole portfolio
4
+ # from a single command.
5
+ #
6
+ # Copyright 2026 Ghost Protocol (Pvt) Ltd. All Rights Reserved.
7
+ # Author: Ryan Sebastian <ryan@ghosts.lk>
8
+
9
+ manifest_version = "1.0"
10
+ default_root = "~/Git Projects"
11
+
12
+ # Each [[product]] entry declares:
13
+ # key - short slug used by `dragon install <key>` etc.
14
+ # name - display name
15
+ # repo - GitHub repo (owner/name)
16
+ # dir - local checkout dir name (under default_root)
17
+ # stack - "operator" | "commercial" | "daemon" | "library"
18
+ # kind - "rust" | "node" | "python" | "monorepo" | "docker"
19
+ # install - command(s) to bring up the local install
20
+ # start - command to start the runtime (optional)
21
+ # stop - command/signal to stop it (optional)
22
+ # port - service port if applicable
23
+ # requires - list of other product keys that MUST be installed first
24
+
25
+ # ── Operator stack ────────────────────────────────────────────────
26
+
27
+ [[product]]
28
+ key = "phantom-dragon-ai"
29
+ name = "PhantomDragon AI"
30
+ repo = "Ghosts-Protocol-Pvt-Ltd/phantom-dragon-ai"
31
+ dir = "Phantom Dragon AI"
32
+ stack = "operator"
33
+ kind = "python"
34
+ install = ["pip install -e ."]
35
+ start = "python3 -m phantom_dragon_ai.control_api"
36
+ port = 4091
37
+
38
+ [[product]]
39
+ key = "dragon-console"
40
+ name = "Dragon Console"
41
+ repo = "ghosts-lk/dragon-console"
42
+ dir = "phantomdragon-control"
43
+ stack = "operator"
44
+ kind = "node"
45
+ install = ["npm install"]
46
+ start = "npm run dev"
47
+ port = 4090
48
+ requires = ["phantom-dragon-ai"]
49
+ # Dragon Console is the GUI sibling of the `dragon` CLI — houses
50
+ # PhantomDragon (offensive), Phantom Memory, DragonNet (cross-link),
51
+ # DragonKeep (cross-link + defensive queue view), and commercial
52
+ # modules. Local dir stays "phantomdragon-control" until the repo is
53
+ # renamed on GitHub (gh repo rename ghosts-lk/dragon-console).
54
+
55
+ [[product]]
56
+ key = "dragonhunt"
57
+ name = "DragonHunt (lead-gen)"
58
+ repo = "Ghosts-Protocol-Pvt-Ltd/DragonHunt"
59
+ dir = "DragonHunt"
60
+ stack = "operator"
61
+ kind = "node"
62
+ install = ["npm install"]
63
+ # Reads ./.env (JWT_SECRET, PD_API, port). The 'safe' scan posture calls
64
+ # control_api at :4091, so phantom-dragon-ai must be up first. Dragon Console
65
+ # proxies to this at :3334 with DRAGONHUNT_TOKEN (see its .env.local).
66
+ start = "npm run dev"
67
+ port = 3334
68
+ requires = ["phantom-dragon-ai"]
69
+
70
+ [[product]]
71
+ key = "dragonnet"
72
+ name = "DragonNet OSINT API"
73
+ repo = "ghosts-lk/dragonnet"
74
+ dir = "DragonNet"
75
+ stack = "operator"
76
+ kind = "monorepo"
77
+ install = ["pnpm install"]
78
+ # Dashboard at :4081 is deprecated as of 2026-05-23 — its UI lives
79
+ # inside Dragon Console under /investigations now. We only start the
80
+ # Fastify API at :4080 going forward.
81
+ start = "pnpm --filter @dragonnet/api dev"
82
+ port = 4080
83
+
84
+ [[product]]
85
+ key = "dragonkeep"
86
+ name = "DragonKeep"
87
+ repo = "Ghosts-Protocol-Pvt-Ltd/DragonKeep"
88
+ dir = "DragonKeep"
89
+ stack = "operator"
90
+ kind = "rust"
91
+ install = ["cargo build --release"]
92
+ start = "./target/release/dragonkeep monitor"
93
+
94
+ [[product]]
95
+ key = "dragon-cli"
96
+ name = "Dragon CLI"
97
+ repo = "ghosts-lk/dragon-cli"
98
+ dir = "dragon-cli"
99
+ stack = "operator"
100
+ kind = "node"
101
+ install = ["npm install", "npm run build", "npm link"]
102
+
103
+ [[product]]
104
+ key = "dragonchronicle"
105
+ name = "DragonChronicle"
106
+ repo = "ghosts-lk/dragonchronicle"
107
+ dir = "DragonChronicle"
108
+ stack = "library"
109
+ kind = "python"
110
+ install = ["pip install -e ."]
111
+
112
+ [[product]]
113
+ key = "dragonscan-sdk"
114
+ name = "DragonScan SDK"
115
+ repo = "ghosts-lk/dragonscansdk"
116
+ dir = "DragonScanSDK"
117
+ stack = "library"
118
+ kind = "python"
119
+ install = ["pip install -e ."]
120
+
121
+ [[product]]
122
+ key = "dragonagent"
123
+ name = "DragonAgent"
124
+ repo = "ghosts-lk/dragonagent"
125
+ dir = "DragonAgent"
126
+ stack = "library"
127
+ kind = "python"
128
+ install = ["pip install -e ."]
129
+ requires = ["dragonscan-sdk"]
130
+
131
+ [[product]]
132
+ key = "dragonpilot"
133
+ name = "DragonPilot"
134
+ repo = "ghosts-lk/dragonpilot"
135
+ dir = "DragonPilot"
136
+ stack = "library"
137
+ kind = "node"
138
+ install = ["npm link"]
139
+
140
+ [[product]]
141
+ key = "dragonlens"
142
+ name = "DragonLens VS Code"
143
+ repo = "ghosts-lk/dragonlens"
144
+ dir = "DragonLens"
145
+ stack = "library"
146
+ kind = "node"
147
+ install = ["npm install", "npm run compile"]
148
+
149
+ # ── MCP servers ───────────────────────────────────────────────────
150
+
151
+ [[product]]
152
+ key = "phantom-memory-mcp"
153
+ name = "Phantom Memory MCP"
154
+ repo = "ghosts-lk/phantom-memory-mcp"
155
+ dir = "phantom-memory-mcp"
156
+ stack = "daemon"
157
+ kind = "python"
158
+ install = ["pip install -e ."]
159
+
160
+ [[product]]
161
+ key = "dragonkeep-mcp"
162
+ name = "DragonKeep MCP"
163
+ repo = "ghosts-lk/dragonkeep-mcp"
164
+ dir = "dragonkeep-mcp"
165
+ stack = "daemon"
166
+ kind = "python"
167
+ install = ["pip install -e ."]
168
+
169
+ [[product]]
170
+ key = "dragonnet-mcp"
171
+ name = "DragonNet MCP"
172
+ repo = "ghosts-lk/dragonnet-mcp"
173
+ dir = "dragonnet-mcp"
174
+ stack = "daemon"
175
+ kind = "python"
176
+ install = ["pip install -e ."]
177
+
178
+ [[product]]
179
+ key = "dragon-meta-mcp"
180
+ name = "Dragon Meta MCP"
181
+ repo = "ghosts-lk/dragon-meta-mcp"
182
+ dir = "dragon-meta-mcp"
183
+ stack = "daemon"
184
+ kind = "python"
185
+ install = ["pip install -e ."]
186
+ requires = ["phantom-memory-mcp", "dragonkeep-mcp", "dragonnet-mcp"]
187
+
188
+ # ── Commercial stack ──────────────────────────────────────────────
189
+
190
+ [[product]]
191
+ key = "phantomdragon-ptaas"
192
+ name = "PhantomDragon PTaaS"
193
+ repo = "ghosts-lk/phantomdragon-ptaas"
194
+ dir = "phantomdragon-ptaas"
195
+ stack = "commercial"
196
+ kind = "monorepo"
197
+ install = ["pnpm install"]
198
+ start = "pnpm dev"
199
+ port = 4092
200
+
201
+ [[product]]
202
+ key = "dragonscribe"
203
+ name = "DragonScribe"
204
+ repo = "ghosts-lk/dragonscribe"
205
+ dir = "dragonscribe"
206
+ stack = "commercial"
207
+ kind = "monorepo"
208
+ install = ["pnpm install"]
209
+ start = "pnpm dev"
210
+ port = 4093
211
+
212
+ [[product]]
213
+ key = "dragonreef"
214
+ name = "DragonReef"
215
+ repo = "ghosts-lk/dragonreef"
216
+ dir = "dragonreef"
217
+ stack = "commercial"
218
+ kind = "monorepo"
219
+ install = ["pnpm install"]
220
+ start = "pnpm dev"
221
+ port = 4094
222
+
223
+ # ── Memory backbone ───────────────────────────────────────────────
224
+
225
+ [[product]]
226
+ key = "wyrm"
227
+ name = "Wyrm MCP"
228
+ repo = "ghosts-lk/Wyrm"
229
+ dir = "Wyrm"
230
+ stack = "daemon"
231
+ kind = "monorepo"
232
+ # Wyrm has no root package.json or pnpm workspace — install + build run
233
+ # inside packages/mcp-server. (Earlier `pnpm install` / `pnpm build`
234
+ # entries silently no-op'd here and made `dragon up` look successful
235
+ # while leaving Wyrm uninstalled.)
236
+ install = [
237
+ "npm install --prefix packages/mcp-server",
238
+ "npm run build --prefix packages/mcp-server",
239
+ ]
240
+ start = "node packages/mcp-server/dist/http-server.js"
241
+ port = 3333