@0dai-dev/cli 4.3.5 → 4.3.7

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 (79) hide show
  1. package/README.md +12 -11
  2. package/bin/0dai.js +214 -40
  3. package/lib/ai/manifest/mcp-exposure-contract.json +121 -0
  4. package/lib/ai/meta/manifest/mcp-tool-tiers.json +435 -0
  5. package/lib/ai/registry/mcp-catalog.json +98 -0
  6. package/lib/commands/auth.js +55 -1
  7. package/lib/commands/compliance.js +1 -1
  8. package/lib/commands/detect.js +10 -4
  9. package/lib/commands/doctor.js +545 -26
  10. package/lib/commands/experience.js +40 -5
  11. package/lib/commands/export.js +73 -0
  12. package/lib/commands/feedback.js +157 -15
  13. package/lib/commands/gh.js +26 -0
  14. package/lib/commands/graph.js +9 -4
  15. package/lib/commands/heatmap.js +1 -1
  16. package/lib/commands/init.js +222 -30
  17. package/lib/commands/mcp.js +129 -21
  18. package/lib/commands/models.js +138 -41
  19. package/lib/commands/provider.js +30 -59
  20. package/lib/commands/quota.js +1 -1
  21. package/lib/commands/receipt.js +1 -1
  22. package/lib/commands/run.js +18 -7
  23. package/lib/commands/runner.js +31 -1
  24. package/lib/commands/status.js +44 -11
  25. package/lib/commands/swarm.js +130 -12
  26. package/lib/commands/trust.js +286 -0
  27. package/lib/commands/update.js +184 -38
  28. package/lib/commands/usage.js +1 -1
  29. package/lib/commands/validate.js +32 -3
  30. package/lib/commands/vault.js +46 -9
  31. package/lib/python/__init__.py +0 -0
  32. package/lib/python/agent_quotas.py +525 -0
  33. package/lib/python/anomaly_alert.py +397 -0
  34. package/lib/python/anti_pattern_detector.py +799 -0
  35. package/lib/python/auth.py +443 -0
  36. package/lib/python/capi_profile_guard.py +477 -0
  37. package/lib/python/compliance_report.py +581 -0
  38. package/lib/python/drift_detector.py +388 -0
  39. package/lib/python/experience_pipeline.py +1130 -0
  40. package/lib/python/graph.py +19 -0
  41. package/lib/python/graph_core.py +293 -0
  42. package/lib/python/graph_io.py +179 -0
  43. package/lib/python/graph_legacy.py +2052 -0
  44. package/lib/python/graph_legacy_helpers.py +221 -0
  45. package/lib/python/graph_outcomes_core.py +85 -0
  46. package/lib/python/graph_queries.py +171 -0
  47. package/lib/python/graph_slice.py +198 -0
  48. package/lib/python/graph_slicer.py +576 -0
  49. package/lib/python/graph_slicer_cli.py +60 -0
  50. package/lib/python/graph_validation.py +64 -0
  51. package/lib/python/heatmap.py +934 -0
  52. package/lib/python/json_utils.py +193 -0
  53. package/lib/python/mcp_exposure_check.py +247 -0
  54. package/lib/python/model_router.py +1434 -0
  55. package/lib/python/project_manager.py +621 -0
  56. package/lib/python/provider_profiles.py +1618 -0
  57. package/lib/python/provider_registry.py +1211 -0
  58. package/lib/python/provider_registry_cli.py +125 -0
  59. package/lib/python/receipt_png.py +727 -0
  60. package/lib/python/structural_memory.py +325 -0
  61. package/lib/python/swarm_cost.py +177 -0
  62. package/lib/python/usage_ledger.py +569 -0
  63. package/lib/scripts/mcp_tier_config.py +240 -0
  64. package/lib/shared.js +97 -14
  65. package/lib/tui/index.mjs +35174 -0
  66. package/lib/utils/activation_telemetry.js +230 -11
  67. package/lib/utils/constants.js +7 -1
  68. package/lib/utils/export-bundler.js +285 -0
  69. package/lib/utils/identity.js +198 -1
  70. package/lib/utils/mcp-auth.js +81 -15
  71. package/lib/utils/plan.js +1 -1
  72. package/lib/vault/index.js +19 -3
  73. package/lib/vault/storage.js +21 -2
  74. package/lib/wizard.js +5 -2
  75. package/package.json +9 -3
  76. package/scripts/build-python-bundle.js +106 -0
  77. package/scripts/build-tui.js +14 -1
  78. package/scripts/harvest_experience.py +523 -0
  79. package/scripts/postinstall.js +15 -9
@@ -0,0 +1,435 @@
1
+ {
2
+ "exposure": {
3
+ "free": {
4
+ "count": 49,
5
+ "tools": [
6
+ "get_project_manifest",
7
+ "get_project_context",
8
+ "get_codebase_map",
9
+ "get_commands",
10
+ "get_environment",
11
+ "get_ai_version",
12
+ "get_project_health",
13
+ "mcp_tier_load",
14
+ "get_bulletins",
15
+ "get_applied_lock",
16
+ "get_custom_stacks",
17
+ "get_discovery",
18
+ "get_personas",
19
+ "get_registry",
20
+ "get_telemetry_summary",
21
+ "citation_audit",
22
+ "get_specs",
23
+ "master_plan_read",
24
+ "search_experience",
25
+ "record_experience",
26
+ "score_candidates",
27
+ "get_federation",
28
+ "get_project_graph",
29
+ "get_model_ratings",
30
+ "get_anomaly_taxonomy",
31
+ "get_anomaly_events",
32
+ "get_anomaly_summary",
33
+ "get_agent_activity",
34
+ "get_ghost_critiques",
35
+ "get_token_telemetry",
36
+ "verdict_count",
37
+ "idle_watchdog_status",
38
+ "get_pool_state",
39
+ "pool_query_free",
40
+ "pool_health",
41
+ "debug_probe",
42
+ "parse_content",
43
+ "memory_add",
44
+ "memory_search",
45
+ "memory_list",
46
+ "memory_delete",
47
+ "memory_verify",
48
+ "memory_inject",
49
+ "gh_label_create",
50
+ "gh_issue_edit_body",
51
+ "gh_pr_diff",
52
+ "propose_file_change",
53
+ "session_productivity",
54
+ "session_productivity_pool"
55
+ ]
56
+ },
57
+ "pro": {
58
+ "count": 113,
59
+ "tools": [
60
+ "get_project_manifest",
61
+ "get_project_context",
62
+ "get_codebase_map",
63
+ "get_commands",
64
+ "get_environment",
65
+ "get_ai_version",
66
+ "get_project_health",
67
+ "mcp_tier_load",
68
+ "get_bulletins",
69
+ "get_applied_lock",
70
+ "get_custom_stacks",
71
+ "get_discovery",
72
+ "get_personas",
73
+ "get_registry",
74
+ "get_telemetry_summary",
75
+ "citation_audit",
76
+ "get_specs",
77
+ "master_plan_read",
78
+ "search_experience",
79
+ "record_experience",
80
+ "score_candidates",
81
+ "get_federation",
82
+ "get_project_graph",
83
+ "get_model_ratings",
84
+ "get_anomaly_taxonomy",
85
+ "get_anomaly_events",
86
+ "get_anomaly_summary",
87
+ "get_agent_activity",
88
+ "get_ghost_critiques",
89
+ "get_token_telemetry",
90
+ "verdict_count",
91
+ "idle_watchdog_status",
92
+ "get_pool_state",
93
+ "pool_query_free",
94
+ "pool_health",
95
+ "debug_probe",
96
+ "parse_content",
97
+ "memory_add",
98
+ "memory_search",
99
+ "memory_list",
100
+ "memory_delete",
101
+ "memory_verify",
102
+ "memory_inject",
103
+ "gh_label_create",
104
+ "gh_issue_edit_body",
105
+ "gh_pr_diff",
106
+ "propose_file_change",
107
+ "session_productivity",
108
+ "session_productivity_pool",
109
+ "get_swarm_status",
110
+ "swarm_delegate",
111
+ "peer_delegate_request",
112
+ "peer_delegate_list",
113
+ "peer_delegate_status",
114
+ "peer_delegate_accept",
115
+ "peer_delegate_decline",
116
+ "peer_delegate_complete",
117
+ "peer_delegate_sessions",
118
+ "swarm_run",
119
+ "run_task",
120
+ "watch_tasks",
121
+ "get_portfolio",
122
+ "estimate_task_cost",
123
+ "recommend_model",
124
+ "get_working_group_profiles",
125
+ "working_group_deliberate",
126
+ "get_working_group_history",
127
+ "working_group_research",
128
+ "get_audit_log",
129
+ "scan_secrets",
130
+ "get_compliance_report",
131
+ "get_role_policy",
132
+ "create_spec",
133
+ "update_decision",
134
+ "save_session",
135
+ "submit_feedback",
136
+ "undo_mutation",
137
+ "record_anomaly",
138
+ "pool_checkin",
139
+ "pool_checkout",
140
+ "loop_kick",
141
+ "task_cancel",
142
+ "idle_watchdog_pause",
143
+ "web_search",
144
+ "capture_screenshot",
145
+ "mcp__openrouter__list_models",
146
+ "mcp__openrouter__invoke",
147
+ "get_org_policy",
148
+ "get_maturity_score",
149
+ "get_mcp_catalog",
150
+ "get_agent_teams",
151
+ "get_plugins",
152
+ "check_approval",
153
+ "list_projects",
154
+ "get_project_health_multi",
155
+ "get_daily_digest",
156
+ "get_session",
157
+ "check_conflicts",
158
+ "get_activity_feed",
159
+ "get_knowledge_base",
160
+ "get_wal",
161
+ "get_prompt_history",
162
+ "get_observability",
163
+ "get_orchestration",
164
+ "get_graph_context",
165
+ "trace_task",
166
+ "get_distilled_rules",
167
+ "get_substrate_health",
168
+ "gh_pr_merge_safe",
169
+ "rebase_orchestrator",
170
+ "fallback_chain_resolver",
171
+ "memory_traverse",
172
+ "memory_search_v2"
173
+ ]
174
+ }
175
+ },
176
+ "discovery": {
177
+ "core": {
178
+ "count": 15,
179
+ "tools": [
180
+ "mcp_tier_load",
181
+ "memory_search",
182
+ "get_project_health",
183
+ "get_session",
184
+ "get_bulletins",
185
+ "get_project_manifest",
186
+ "get_codebase_map",
187
+ "get_commands",
188
+ "get_discovery",
189
+ "get_specs",
190
+ "search_experience",
191
+ "record_experience",
192
+ "get_activity_feed",
193
+ "check_approval",
194
+ "get_role_policy"
195
+ ]
196
+ },
197
+ "on_demand": {
198
+ "count": 81,
199
+ "tools": [
200
+ "get_project_context",
201
+ "get_environment",
202
+ "get_ai_version",
203
+ "get_applied_lock",
204
+ "get_custom_stacks",
205
+ "get_personas",
206
+ "get_registry",
207
+ "get_telemetry_summary",
208
+ "citation_audit",
209
+ "master_plan_read",
210
+ "score_candidates",
211
+ "get_federation",
212
+ "get_project_graph",
213
+ "get_model_ratings",
214
+ "get_anomaly_taxonomy",
215
+ "get_anomaly_events",
216
+ "get_anomaly_summary",
217
+ "get_agent_activity",
218
+ "get_ghost_critiques",
219
+ "get_token_telemetry",
220
+ "verdict_count",
221
+ "idle_watchdog_status",
222
+ "get_pool_state",
223
+ "pool_query_free",
224
+ "pool_health",
225
+ "debug_probe",
226
+ "parse_content",
227
+ "memory_add",
228
+ "memory_list",
229
+ "memory_verify",
230
+ "gh_pr_diff",
231
+ "session_productivity",
232
+ "session_productivity_pool",
233
+ "get_swarm_status",
234
+ "swarm_delegate",
235
+ "peer_delegate_request",
236
+ "peer_delegate_list",
237
+ "peer_delegate_status",
238
+ "peer_delegate_accept",
239
+ "peer_delegate_decline",
240
+ "peer_delegate_complete",
241
+ "peer_delegate_sessions",
242
+ "swarm_run",
243
+ "run_task",
244
+ "watch_tasks",
245
+ "get_portfolio",
246
+ "estimate_task_cost",
247
+ "recommend_model",
248
+ "get_working_group_profiles",
249
+ "working_group_deliberate",
250
+ "get_working_group_history",
251
+ "working_group_research",
252
+ "get_audit_log",
253
+ "scan_secrets",
254
+ "get_compliance_report",
255
+ "save_session",
256
+ "loop_kick",
257
+ "web_search",
258
+ "capture_screenshot",
259
+ "mcp__openrouter__list_models",
260
+ "mcp__openrouter__invoke",
261
+ "get_org_policy",
262
+ "get_maturity_score",
263
+ "get_mcp_catalog",
264
+ "get_agent_teams",
265
+ "get_plugins",
266
+ "list_projects",
267
+ "get_project_health_multi",
268
+ "get_daily_digest",
269
+ "check_conflicts",
270
+ "get_knowledge_base",
271
+ "get_wal",
272
+ "get_prompt_history",
273
+ "get_observability",
274
+ "get_orchestration",
275
+ "get_graph_context",
276
+ "trace_task",
277
+ "get_distilled_rules",
278
+ "get_substrate_health",
279
+ "memory_traverse",
280
+ "memory_search_v2"
281
+ ]
282
+ },
283
+ "hidden": {
284
+ "count": 17,
285
+ "tools": [
286
+ "memory_delete",
287
+ "memory_inject",
288
+ "gh_label_create",
289
+ "gh_issue_edit_body",
290
+ "propose_file_change",
291
+ "create_spec",
292
+ "update_decision",
293
+ "submit_feedback",
294
+ "undo_mutation",
295
+ "record_anomaly",
296
+ "pool_checkin",
297
+ "pool_checkout",
298
+ "task_cancel",
299
+ "idle_watchdog_pause",
300
+ "gh_pr_merge_safe",
301
+ "rebase_orchestrator",
302
+ "fallback_chain_resolver"
303
+ ]
304
+ }
305
+ },
306
+ "schema_version": 1,
307
+ "source": "scripts/mcp_tier_config.py",
308
+ "tiers": {
309
+ "free_only": {
310
+ "count": 49,
311
+ "tools": [
312
+ "get_project_manifest",
313
+ "get_project_context",
314
+ "get_codebase_map",
315
+ "get_commands",
316
+ "get_environment",
317
+ "get_ai_version",
318
+ "get_project_health",
319
+ "mcp_tier_load",
320
+ "get_bulletins",
321
+ "get_applied_lock",
322
+ "get_custom_stacks",
323
+ "get_discovery",
324
+ "get_personas",
325
+ "get_registry",
326
+ "get_telemetry_summary",
327
+ "citation_audit",
328
+ "get_specs",
329
+ "master_plan_read",
330
+ "search_experience",
331
+ "record_experience",
332
+ "score_candidates",
333
+ "get_federation",
334
+ "get_project_graph",
335
+ "get_model_ratings",
336
+ "get_anomaly_taxonomy",
337
+ "get_anomaly_events",
338
+ "get_anomaly_summary",
339
+ "get_agent_activity",
340
+ "get_ghost_critiques",
341
+ "get_token_telemetry",
342
+ "verdict_count",
343
+ "idle_watchdog_status",
344
+ "get_pool_state",
345
+ "pool_query_free",
346
+ "pool_health",
347
+ "debug_probe",
348
+ "parse_content",
349
+ "memory_add",
350
+ "memory_search",
351
+ "memory_list",
352
+ "memory_delete",
353
+ "memory_verify",
354
+ "memory_inject",
355
+ "gh_label_create",
356
+ "gh_issue_edit_body",
357
+ "gh_pr_diff",
358
+ "propose_file_change",
359
+ "session_productivity",
360
+ "session_productivity_pool"
361
+ ]
362
+ },
363
+ "pro_only": {
364
+ "count": 64,
365
+ "tools": [
366
+ "get_swarm_status",
367
+ "swarm_delegate",
368
+ "peer_delegate_request",
369
+ "peer_delegate_list",
370
+ "peer_delegate_status",
371
+ "peer_delegate_accept",
372
+ "peer_delegate_decline",
373
+ "peer_delegate_complete",
374
+ "peer_delegate_sessions",
375
+ "swarm_run",
376
+ "run_task",
377
+ "watch_tasks",
378
+ "get_portfolio",
379
+ "estimate_task_cost",
380
+ "recommend_model",
381
+ "get_working_group_profiles",
382
+ "working_group_deliberate",
383
+ "get_working_group_history",
384
+ "working_group_research",
385
+ "get_audit_log",
386
+ "scan_secrets",
387
+ "get_compliance_report",
388
+ "get_role_policy",
389
+ "create_spec",
390
+ "update_decision",
391
+ "save_session",
392
+ "submit_feedback",
393
+ "undo_mutation",
394
+ "record_anomaly",
395
+ "pool_checkin",
396
+ "pool_checkout",
397
+ "loop_kick",
398
+ "task_cancel",
399
+ "idle_watchdog_pause",
400
+ "web_search",
401
+ "capture_screenshot",
402
+ "mcp__openrouter__list_models",
403
+ "mcp__openrouter__invoke",
404
+ "get_org_policy",
405
+ "get_maturity_score",
406
+ "get_mcp_catalog",
407
+ "get_agent_teams",
408
+ "get_plugins",
409
+ "check_approval",
410
+ "list_projects",
411
+ "get_project_health_multi",
412
+ "get_daily_digest",
413
+ "get_session",
414
+ "check_conflicts",
415
+ "get_activity_feed",
416
+ "get_knowledge_base",
417
+ "get_wal",
418
+ "get_prompt_history",
419
+ "get_observability",
420
+ "get_orchestration",
421
+ "get_graph_context",
422
+ "trace_task",
423
+ "get_distilled_rules",
424
+ "get_substrate_health",
425
+ "gh_pr_merge_safe",
426
+ "rebase_orchestrator",
427
+ "fallback_chain_resolver",
428
+ "memory_traverse",
429
+ "memory_search_v2"
430
+ ]
431
+ }
432
+ },
433
+ "updated_at": "2026-05-30",
434
+ "upgrade_message": "This tool requires Pro plan ($15/mo). Run: 0dai upgrade"
435
+ }
@@ -0,0 +1,98 @@
1
+ {
2
+ "managed": true,
3
+ "schema": 1,
4
+ "description": "Stack-specific MCP server recommendations. During init/sync, 0dai merges these into .mcp.json based on detected stack.",
5
+ "common": {
6
+ "filesystem": {
7
+ "command": "npx",
8
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
9
+ "description": "Local filesystem access"
10
+ },
11
+ "sequential-thinking": {
12
+ "command": "npx",
13
+ "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
14
+ "description": "Structured multi-step reasoning. Call as first action for architectural work, multi-file refactors, non-obvious debugging, and plans longer than 3 steps."
15
+ },
16
+ "context7": {
17
+ "command": "npx",
18
+ "args": ["-y", "@upstash/context7-mcp@latest"],
19
+ "description": "Current library/framework/SDK documentation lookup. Call resolve-library-id then get-library-docs before writing code that uses a third-party API — training data may be outdated."
20
+ },
21
+ "fetch": {
22
+ "command": "npx",
23
+ "args": ["-y", "@modelcontextprotocol/server-fetch"],
24
+ "description": "External HTTP content (blog posts, RFCs, changelogs). Use context7 for library docs instead."
25
+ }
26
+ },
27
+ "stacks": {
28
+ "node": {
29
+ "servers": {}
30
+ },
31
+ "nextjs": {
32
+ "servers": {}
33
+ },
34
+ "react-native": {
35
+ "servers": {}
36
+ },
37
+ "python": {
38
+ "servers": {
39
+ "python-repl": {
40
+ "command": "npx",
41
+ "args": ["-y", "@anthropic-ai/mcp-server-python"],
42
+ "description": "Python REPL and execution"
43
+ }
44
+ }
45
+ },
46
+ "python-service": {
47
+ "servers": {
48
+ "python-repl": {
49
+ "command": "npx",
50
+ "args": ["-y", "@anthropic-ai/mcp-server-python"],
51
+ "description": "Python REPL and execution"
52
+ }
53
+ }
54
+ },
55
+ "fastapi": {
56
+ "servers": {
57
+ "python-repl": {
58
+ "command": "npx",
59
+ "args": ["-y", "@anthropic-ai/mcp-server-python"],
60
+ "description": "Python REPL and execution"
61
+ }
62
+ }
63
+ },
64
+ "data-ml": {
65
+ "servers": {
66
+ "python-repl": {
67
+ "command": "npx",
68
+ "args": ["-y", "@anthropic-ai/mcp-server-python"],
69
+ "description": "Python REPL and execution"
70
+ }
71
+ }
72
+ },
73
+ "go-service": {
74
+ "servers": {}
75
+ },
76
+ "flutter": {
77
+ "servers": {}
78
+ },
79
+ "fullstack-monorepo": {
80
+ "servers": {}
81
+ },
82
+ "django": {
83
+ "servers": {
84
+ "python-repl": {
85
+ "command": "npx",
86
+ "args": ["-y", "@anthropic-ai/mcp-server-python"],
87
+ "description": "Python REPL and execution"
88
+ }
89
+ }
90
+ },
91
+ "terraform": {
92
+ "servers": {}
93
+ },
94
+ "kubernetes": {
95
+ "servers": {}
96
+ }
97
+ }
98
+ }
@@ -471,8 +471,9 @@ async function cmdAuthStatus() {
471
471
  log(`${email} (${status.plan || auth.plan || "free"} plan)`);
472
472
  if (status.usage_today) {
473
473
  console.log(" Usage today:");
474
+ const limits = status.limits || {};
474
475
  for (const [k, v] of Object.entries(status.usage_today))
475
- console.log(` ${k}: ${v} / ${status.limits[k]}`);
476
+ console.log(` ${k}: ${v} / ${limits[k] ?? "?"}`);
476
477
  }
477
478
  const license = status.license || auth.license || { status: "inactive" };
478
479
  console.log(` Activation: ${license.status || "inactive"}${license.activation_id ? ` (${license.activation_id})` : ""}`);
@@ -481,6 +482,54 @@ async function cmdAuthStatus() {
481
482
  }
482
483
  }
483
484
 
485
+ // Disclosure text for the remote activation event.
486
+ // Exported so tests can assert the notice references the real payload fields.
487
+ const ACTIVATION_TELEMETRY_NOTICE =
488
+ "Telemetry: on activation, 0dai sends an event (free_tier_activated, timestamp, "
489
+ + "path=cli://activate-free, source=cli) to api.0dai.dev/v1/events via your "
490
+ + "authenticated session with a device identifier (X-Device-ID header). "
491
+ + "To opt out: set DO_NOT_TRACK=1 or ODAI_NO_TELEMETRY=1.";
492
+
493
+ /**
494
+ * Post a best-effort activation event to the remote analytics endpoint.
495
+ *
496
+ * Opt-out: set DO_NOT_TRACK=1 or ODAI_NO_TELEMETRY=1 in the environment.
497
+ * When opted out, the local activation log (ai/meta/telemetry/activation.jsonl)
498
+ * is NOT affected — only the remote HTTP POST is skipped.
499
+ *
500
+ * @param {object} [deps]
501
+ * @param {Function} [deps.apiCallFn] - injectable stand-in for apiCall (tests)
502
+ * @param {object} [deps.env] - injectable env (defaults to process.env)
503
+ * @param {Function} [deps.print] - injectable print fn (defaults to console.log)
504
+ */
505
+ async function trackFreeTierActivated(deps = {}) {
506
+ const env = deps.env || process.env;
507
+ const print = deps.print || console.log;
508
+ const callFn = deps.apiCallFn || apiCall;
509
+
510
+ // Honour standard cross-ecosystem opt-out AND 0dai-specific form.
511
+ if (env.DO_NOT_TRACK === "1" || env.ODAI_NO_TELEMETRY === "1") {
512
+ return; // remote POST skipped; local log is unaffected
513
+ }
514
+
515
+ // One-time honest disclosure: what is sent, where, and how to opt out.
516
+ print(ACTIVATION_TELEMETRY_NOTICE);
517
+
518
+ try {
519
+ await callFn("/v1/events", {
520
+ events: [{
521
+ event: "free_tier_activated",
522
+ timestamp: new Date().toISOString(),
523
+ path: "cli://activate-free",
524
+ page: "0dai activate free",
525
+ props: { source: "cli" },
526
+ }],
527
+ });
528
+ } catch {
529
+ // best-effort telemetry — network failure is non-fatal
530
+ }
531
+ }
532
+
484
533
  async function cmdActivateFree() {
485
534
  const ensureAuthenticated = makeEnsureAuthenticated(cmdAuthLogin);
486
535
  await ensureAuthenticated("activation");
@@ -488,6 +537,9 @@ async function cmdActivateFree() {
488
537
  log(`license ${license.status}`);
489
538
  console.log(` activation id: ${license.activation_id}`);
490
539
  console.log(` plan: ${license.plan || "free"}`);
540
+ if (license.status === "active") {
541
+ await trackFreeTierActivated();
542
+ }
491
543
  }
492
544
 
493
545
  async function cmdActivateStatus() {
@@ -523,4 +575,6 @@ module.exports = {
523
575
  parseActivationArgs,
524
576
  parseAuthLoginFlags,
525
577
  printDeviceLoginInstructions,
578
+ trackFreeTierActivated,
579
+ ACTIVATION_TELEMETRY_NOTICE,
526
580
  };
@@ -4,7 +4,7 @@ const shared = require("../shared");
4
4
  const { D, R, findRepoScript, log, spawnSync } = shared;
5
5
 
6
6
  function cmdCompliance(target, args) {
7
- const complianceScript = findRepoScript(target, "compliance_report.py");
7
+ const complianceScript = shared.resolvePythonScript(target, "compliance_report.py");
8
8
  if (!complianceScript) {
9
9
  log("compliance helper unavailable in this environment");
10
10
  console.log(` ${D}Expected scripts/compliance_report.py in repo checkout${R}`);
@@ -1,15 +1,21 @@
1
1
  "use strict";
2
2
  const shared = require("../shared");
3
- const { D, R, log, apiCall, collectMetadata } = shared;
3
+ const { D, R, log, apiCall, collectMetadata, buildProjectIdentity, hashManifestFiles } = shared;
4
4
 
5
5
  async function cmdDetect(target) {
6
6
  const OPTIONAL_CLIS = ["gemini", "aider", "opencode"];
7
- const { projectFiles, manifestContents, clis: localClis } = collectMetadata(target);
8
- // Send file contents AND local CLI inventory so server can do content-based detection
7
+ const metadata = collectMetadata(target);
8
+ const { projectFiles, manifestContents, clis: localClis } = metadata;
9
+ const identity = buildProjectIdentity(target, metadata);
10
+ // Privacy: send only filenames + SHA-256 hashes, never raw content (closes #4016).
11
+ // Local stack detection is pre-computed and passed as `stack`; server works from
12
+ // project_files + client-derived stack, not file content.
9
13
  const result = await apiCall("/v1/detect", {
10
14
  project_files: projectFiles,
11
- manifest_contents: manifestContents,
15
+ manifest_files: hashManifestFiles(manifestContents),
12
16
  available_clis: localClis,
17
+ project_name: identity.project_name,
18
+ stack: identity.stack,
13
19
  });
14
20
  if (result.error) { log(`error: ${result.error}`); return; }
15
21
  console.log(`stack: ${result.stack || "?"}`);