chainlesschain 0.47.9 → 0.49.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 (70) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AppLayout-6SPt_8Y_.js → AppLayout-Rvi759IS.js} +1 -1
  5. package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
  6. package/src/assets/web-panel/assets/{Dashboard-Br7kCwKJ.js → Dashboard-DBhFxXYQ.js} +2 -2
  7. package/src/assets/web-panel/assets/{index-tN-8TosE.js → index-uL0cZ8N_.js} +2 -2
  8. package/src/assets/web-panel/index.html +2 -2
  9. package/src/commands/codegen.js +303 -0
  10. package/src/commands/collab.js +482 -0
  11. package/src/commands/crosschain.js +382 -0
  12. package/src/commands/dbevo.js +388 -0
  13. package/src/commands/dev.js +411 -0
  14. package/src/commands/federation.js +427 -0
  15. package/src/commands/fusion.js +332 -0
  16. package/src/commands/governance.js +505 -0
  17. package/src/commands/hardening.js +110 -0
  18. package/src/commands/incentive.js +373 -0
  19. package/src/commands/inference.js +304 -0
  20. package/src/commands/infra.js +361 -0
  21. package/src/commands/kg.js +371 -0
  22. package/src/commands/marketplace.js +326 -0
  23. package/src/commands/mcp.js +97 -18
  24. package/src/commands/nlprog.js +329 -0
  25. package/src/commands/ops.js +408 -0
  26. package/src/commands/perception.js +385 -0
  27. package/src/commands/pqc.js +34 -0
  28. package/src/commands/privacy.js +345 -0
  29. package/src/commands/quantization.js +280 -0
  30. package/src/commands/recommend.js +336 -0
  31. package/src/commands/reputation.js +349 -0
  32. package/src/commands/runtime.js +500 -0
  33. package/src/commands/sla.js +352 -0
  34. package/src/commands/stress.js +252 -0
  35. package/src/commands/tech.js +268 -0
  36. package/src/commands/tenant.js +576 -0
  37. package/src/commands/trust.js +366 -0
  38. package/src/harness/mcp-client.js +330 -54
  39. package/src/index.js +112 -0
  40. package/src/lib/aiops.js +523 -0
  41. package/src/lib/autonomous-developer.js +524 -0
  42. package/src/lib/code-agent.js +442 -0
  43. package/src/lib/collaboration-governance.js +556 -0
  44. package/src/lib/community-governance.js +649 -0
  45. package/src/lib/content-recommendation.js +600 -0
  46. package/src/lib/cross-chain.js +669 -0
  47. package/src/lib/dbevo.js +669 -0
  48. package/src/lib/decentral-infra.js +445 -0
  49. package/src/lib/federation-hardening.js +587 -0
  50. package/src/lib/hardening-manager.js +409 -0
  51. package/src/lib/inference-network.js +407 -0
  52. package/src/lib/knowledge-graph.js +530 -0
  53. package/src/lib/mcp-client.js +3 -0
  54. package/src/lib/multimodal.js +698 -0
  55. package/src/lib/nl-programming.js +595 -0
  56. package/src/lib/perception.js +500 -0
  57. package/src/lib/pqc-manager.js +141 -9
  58. package/src/lib/privacy-computing.js +575 -0
  59. package/src/lib/protocol-fusion.js +535 -0
  60. package/src/lib/quantization.js +362 -0
  61. package/src/lib/reputation-optimizer.js +509 -0
  62. package/src/lib/skill-marketplace.js +397 -0
  63. package/src/lib/sla-manager.js +484 -0
  64. package/src/lib/stress-tester.js +383 -0
  65. package/src/lib/tech-learning-engine.js +651 -0
  66. package/src/lib/tenant-saas.js +831 -0
  67. package/src/lib/token-incentive.js +513 -0
  68. package/src/lib/trust-security.js +473 -0
  69. package/src/lib/universal-runtime.js +771 -0
  70. package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
@@ -0,0 +1,336 @@
1
+ /**
2
+ * `cc recommend` — CLI surface for Phase 48 Smart Content Recommendation.
3
+ */
4
+
5
+ import { Command } from "commander";
6
+
7
+ import {
8
+ CONTENT_TYPES,
9
+ RECOMMENDATION_STATUS,
10
+ FEEDBACK_VALUES,
11
+ DEFAULT_CONFIG,
12
+ ensureRecommendationTables,
13
+ getProfile,
14
+ createProfile,
15
+ updateProfile,
16
+ deleteProfile,
17
+ listProfiles,
18
+ applyDecay,
19
+ scoreContent,
20
+ generateRecommendations,
21
+ getRecommendation,
22
+ listRecommendations,
23
+ markViewed,
24
+ provideFeedback,
25
+ dismissRecommendation,
26
+ getRecommendationStats,
27
+ getTopInterests,
28
+ suggestTopics,
29
+ } from "../lib/content-recommendation.js";
30
+
31
+ function _dbFromCtx(cmd) {
32
+ const root = cmd?.parent?.parent ?? cmd?.parent;
33
+ return root?._db;
34
+ }
35
+
36
+ export function registerRecommendCommand(program) {
37
+ const rec = new Command("recommend")
38
+ .description("Smart content recommendation (Phase 48)")
39
+ .hook("preAction", (thisCmd) => {
40
+ const db = _dbFromCtx(thisCmd);
41
+ if (db) ensureRecommendationTables(db);
42
+ });
43
+
44
+ /* ── Catalogs ────────────────────────────────────── */
45
+
46
+ rec
47
+ .command("content-types")
48
+ .description("List supported content types")
49
+ .option("--json", "JSON output")
50
+ .action((opts) => {
51
+ const types = Object.values(CONTENT_TYPES);
52
+ if (opts.json) return console.log(JSON.stringify(types, null, 2));
53
+ for (const t of types)
54
+ console.log(` ${t.id.padEnd(12)} ${t.name} — ${t.description}`);
55
+ });
56
+
57
+ rec
58
+ .command("statuses")
59
+ .description("List recommendation statuses")
60
+ .option("--json", "JSON output")
61
+ .action((opts) => {
62
+ const statuses = Object.values(RECOMMENDATION_STATUS);
63
+ if (opts.json) return console.log(JSON.stringify(statuses, null, 2));
64
+ for (const s of statuses) console.log(` ${s}`);
65
+ });
66
+
67
+ rec
68
+ .command("feedback-values")
69
+ .description("List feedback values")
70
+ .option("--json", "JSON output")
71
+ .action((opts) => {
72
+ const vals = Object.values(FEEDBACK_VALUES);
73
+ if (opts.json) return console.log(JSON.stringify(vals, null, 2));
74
+ for (const v of vals) console.log(` ${v}`);
75
+ });
76
+
77
+ /* ── Profile Management ──────────────────────────── */
78
+
79
+ rec
80
+ .command("profile <user-id>")
81
+ .description("Show user interest profile")
82
+ .option("--json", "JSON output")
83
+ .action((userId, opts) => {
84
+ const db = _dbFromCtx(rec);
85
+ const p = getProfile(db, userId);
86
+ if (!p) return console.log("Profile not found.");
87
+ if (opts.json) return console.log(JSON.stringify(p, null, 2));
88
+ console.log(`User: ${p.user_id}`);
89
+ console.log(`Updated: ${new Date(p.last_updated).toISOString()}`);
90
+ console.log(`Updates: ${p.update_count}`);
91
+ console.log(`Decay: ${p.decay_factor}`);
92
+ console.log(`Topics:`);
93
+ for (const [t, w] of Object.entries(p.topics))
94
+ console.log(` ${t}: ${w}`);
95
+ });
96
+
97
+ rec
98
+ .command("create-profile <user-id>")
99
+ .description("Create interest profile for a user")
100
+ .option("-t, --topics <json>", "Topic weights JSON")
101
+ .option("-w, --weights <json>", "Interaction weights JSON")
102
+ .option("--json", "JSON output")
103
+ .action((userId, opts) => {
104
+ const db = _dbFromCtx(rec);
105
+ const topics = opts.topics ? JSON.parse(opts.topics) : {};
106
+ const interactionWeights = opts.weights ? JSON.parse(opts.weights) : {};
107
+ const result = createProfile(db, userId, { topics, interactionWeights });
108
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
109
+ if (result.profileId) console.log(`Profile created: ${result.profileId}`);
110
+ else console.log(`Failed: ${result.reason}`);
111
+ });
112
+
113
+ rec
114
+ .command("update-profile <user-id>")
115
+ .description("Update interest profile")
116
+ .option("-t, --topics <json>", "Topic weights JSON")
117
+ .option("-w, --weights <json>", "Interaction weights JSON")
118
+ .option("-d, --decay <factor>", "Decay factor", parseFloat)
119
+ .option("--json", "JSON output")
120
+ .action((userId, opts) => {
121
+ const db = _dbFromCtx(rec);
122
+ const params = {};
123
+ if (opts.topics) params.topics = JSON.parse(opts.topics);
124
+ if (opts.weights) params.interactionWeights = JSON.parse(opts.weights);
125
+ if (opts.decay !== undefined) params.decayFactor = opts.decay;
126
+ const result = updateProfile(db, userId, params);
127
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
128
+ console.log(
129
+ result.updated ? "Profile updated." : `Failed: ${result.reason}`,
130
+ );
131
+ });
132
+
133
+ rec
134
+ .command("delete-profile <user-id>")
135
+ .description("Delete interest profile")
136
+ .option("--json", "JSON output")
137
+ .action((userId, opts) => {
138
+ const db = _dbFromCtx(rec);
139
+ const result = deleteProfile(db, userId);
140
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
141
+ console.log(
142
+ result.deleted ? "Profile deleted." : `Failed: ${result.reason}`,
143
+ );
144
+ });
145
+
146
+ rec
147
+ .command("profiles")
148
+ .description("List all interest profiles")
149
+ .option("--limit <n>", "Max results", parseInt)
150
+ .option("--json", "JSON output")
151
+ .action((opts) => {
152
+ const db = _dbFromCtx(rec);
153
+ const profiles = listProfiles(db, { limit: opts.limit });
154
+ if (opts.json) return console.log(JSON.stringify(profiles, null, 2));
155
+ if (profiles.length === 0) return console.log("No profiles.");
156
+ for (const p of profiles) {
157
+ const topicCount = Object.keys(p.topics).length;
158
+ console.log(
159
+ ` ${p.user_id.padEnd(20)} ${topicCount} topics updated ${new Date(p.last_updated).toISOString()}`,
160
+ );
161
+ }
162
+ });
163
+
164
+ rec
165
+ .command("decay <user-id>")
166
+ .description("Apply time decay to profile topics")
167
+ .option("--json", "JSON output")
168
+ .action((userId, opts) => {
169
+ const db = _dbFromCtx(rec);
170
+ const result = applyDecay(db, userId);
171
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
172
+ if (result.applied)
173
+ console.log(`Decay applied. ${result.topicCount} topics remaining.`);
174
+ else console.log(`Failed: ${result.reason}`);
175
+ });
176
+
177
+ /* ── Recommendation Generation ───────────────────── */
178
+
179
+ rec
180
+ .command("generate <user-id>")
181
+ .description(
182
+ "Generate recommendations from content pool (JSON stdin or --pool)",
183
+ )
184
+ .option("-p, --pool <json>", "Content pool as JSON array")
185
+ .option("-l, --limit <n>", "Max recommendations", parseInt)
186
+ .option("-m, --min-score <n>", "Minimum score", parseFloat)
187
+ .option("--json", "JSON output")
188
+ .action((userId, opts) => {
189
+ const db = _dbFromCtx(rec);
190
+ if (!opts.pool) {
191
+ return console.log("Provide --pool as JSON array of content items.");
192
+ }
193
+ const pool = JSON.parse(opts.pool);
194
+ const result = generateRecommendations(db, userId, pool, {
195
+ limit: opts.limit,
196
+ minScore: opts.minScore,
197
+ });
198
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
199
+ if (result.reason) return console.log(`Failed: ${result.reason}`);
200
+ console.log(`Generated ${result.generated} recommendations.`);
201
+ });
202
+
203
+ /* ── Recommendation CRUD ─────────────────────────── */
204
+
205
+ rec
206
+ .command("show <rec-id>")
207
+ .description("Show recommendation details")
208
+ .option("--json", "JSON output")
209
+ .action((recId, opts) => {
210
+ const db = _dbFromCtx(rec);
211
+ const r = getRecommendation(db, recId);
212
+ if (!r) return console.log("Recommendation not found.");
213
+ if (opts.json) return console.log(JSON.stringify(r, null, 2));
214
+ console.log(`ID: ${r.id}`);
215
+ console.log(`User: ${r.user_id}`);
216
+ console.log(`Content: ${r.content_id} (${r.content_type})`);
217
+ console.log(`Title: ${r.title}`);
218
+ console.log(`Score: ${r.score}`);
219
+ console.log(`Reason: ${r.reason}`);
220
+ console.log(`Status: ${r.status}`);
221
+ if (r.feedback) console.log(`Feedback: ${r.feedback}`);
222
+ });
223
+
224
+ rec
225
+ .command("list <user-id>")
226
+ .description("List recommendations for a user")
227
+ .option("-s, --status <status>", "Filter by status")
228
+ .option("-t, --type <type>", "Filter by content type")
229
+ .option("-m, --min-score <n>", "Minimum score", parseFloat)
230
+ .option("--limit <n>", "Max results", parseInt)
231
+ .option("--json", "JSON output")
232
+ .action((userId, opts) => {
233
+ const db = _dbFromCtx(rec);
234
+ const recs = listRecommendations(db, userId, {
235
+ status: opts.status,
236
+ contentType: opts.type,
237
+ limit: opts.limit,
238
+ minScore: opts.minScore,
239
+ });
240
+ if (opts.json) return console.log(JSON.stringify(recs, null, 2));
241
+ if (recs.length === 0) return console.log("No recommendations.");
242
+ for (const r of recs) {
243
+ const fb = r.feedback ? ` [${r.feedback}]` : "";
244
+ console.log(
245
+ ` ${r.score.toFixed(3)} ${r.status.padEnd(10)} ${r.title || r.content_id}${fb}`,
246
+ );
247
+ }
248
+ });
249
+
250
+ rec
251
+ .command("view <rec-id>")
252
+ .description("Mark recommendation as viewed")
253
+ .option("--json", "JSON output")
254
+ .action((recId, opts) => {
255
+ const db = _dbFromCtx(rec);
256
+ const result = markViewed(db, recId);
257
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
258
+ console.log(
259
+ result.marked ? "Marked as viewed." : `Failed: ${result.reason}`,
260
+ );
261
+ });
262
+
263
+ rec
264
+ .command("feedback <rec-id> <value>")
265
+ .description("Provide feedback (like / dislike / later)")
266
+ .option("--json", "JSON output")
267
+ .action((recId, value, opts) => {
268
+ const db = _dbFromCtx(rec);
269
+ const result = provideFeedback(db, recId, value);
270
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
271
+ console.log(
272
+ result.recorded ? "Feedback recorded." : `Failed: ${result.reason}`,
273
+ );
274
+ });
275
+
276
+ rec
277
+ .command("dismiss <rec-id>")
278
+ .description("Dismiss a recommendation")
279
+ .option("--json", "JSON output")
280
+ .action((recId, opts) => {
281
+ const db = _dbFromCtx(rec);
282
+ const result = dismissRecommendation(db, recId);
283
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
284
+ console.log(result.dismissed ? "Dismissed." : `Failed: ${result.reason}`);
285
+ });
286
+
287
+ /* ── Stats & Insights ────────────────────────────── */
288
+
289
+ rec
290
+ .command("stats <user-id>")
291
+ .description("Recommendation statistics")
292
+ .option("--json", "JSON output")
293
+ .action((userId, opts) => {
294
+ const db = _dbFromCtx(rec);
295
+ const stats = getRecommendationStats(db, userId);
296
+ if (opts.json) return console.log(JSON.stringify(stats, null, 2));
297
+ console.log(`Total: ${stats.total}`);
298
+ console.log(`Pending: ${stats.pending}`);
299
+ console.log(`Viewed: ${stats.viewed}`);
300
+ console.log(`Dismissed: ${stats.dismissed}`);
301
+ console.log(
302
+ `Feedback: ${stats.feedbackCount} (${(stats.feedbackRate * 100).toFixed(1)}%)`,
303
+ );
304
+ console.log(`Avg score: ${stats.avgScore}`);
305
+ });
306
+
307
+ rec
308
+ .command("top-interests <user-id>")
309
+ .description("Show top interests from profile")
310
+ .option("--limit <n>", "Max results", parseInt)
311
+ .option("--json", "JSON output")
312
+ .action((userId, opts) => {
313
+ const db = _dbFromCtx(rec);
314
+ const interests = getTopInterests(db, userId, { limit: opts.limit });
315
+ if (opts.json) return console.log(JSON.stringify(interests, null, 2));
316
+ if (interests.length === 0) return console.log("No interests found.");
317
+ for (const i of interests)
318
+ console.log(` ${i.topic.padEnd(20)} ${i.weight}`);
319
+ });
320
+
321
+ rec
322
+ .command("suggest <user-id>")
323
+ .description("Suggest profile adjustments from feedback patterns")
324
+ .option("--json", "JSON output")
325
+ .action((userId, opts) => {
326
+ const db = _dbFromCtx(rec);
327
+ const suggestions = suggestTopics(db, userId);
328
+ if (opts.json) return console.log(JSON.stringify(suggestions, null, 2));
329
+ if (suggestions.length === 0)
330
+ return console.log("No suggestions — need more feedback.");
331
+ for (const s of suggestions)
332
+ console.log(` ${s.action.padEnd(8)} ${s.topic} by ${s.amount}`);
333
+ });
334
+
335
+ program.addCommand(rec);
336
+ }
@@ -0,0 +1,349 @@
1
+ /**
2
+ * Reputation commands
3
+ * chainlesschain reputation observe|score|list|decay-preview|anomalies|optimize|status|analytics|apply
4
+ */
5
+
6
+ import chalk from "chalk";
7
+ import { logger } from "../lib/logger.js";
8
+ import { bootstrap, shutdown } from "../runtime/bootstrap.js";
9
+ import {
10
+ ensureReputationTables,
11
+ addObservation,
12
+ computeScore,
13
+ listScores,
14
+ detectAnomalies,
15
+ startOptimization,
16
+ getOptimizationStatus,
17
+ getAnalytics,
18
+ listOptimizationRuns,
19
+ applyOptimizedParams,
20
+ OPTIMIZATION_OBJECTIVES,
21
+ } from "../lib/reputation-optimizer.js";
22
+
23
+ function _dbFromCtx(ctx) {
24
+ if (!ctx.db) {
25
+ logger.error("Database not available");
26
+ process.exit(1);
27
+ }
28
+ const db = ctx.db.getDatabase();
29
+ ensureReputationTables(db);
30
+ return db;
31
+ }
32
+
33
+ export function registerReputationCommand(program) {
34
+ const rep = program
35
+ .command("reputation")
36
+ .alias("rep")
37
+ .description(
38
+ "Reputation optimizer — observations, decay, anomaly detection, Bayesian optimization",
39
+ );
40
+
41
+ rep
42
+ .command("observe <did> <score>")
43
+ .description("Record a reputation observation (score in [0,1])")
44
+ .option(
45
+ "-k, --kind <kind>",
46
+ "Observation kind (generic|task|review|vote)",
47
+ "generic",
48
+ )
49
+ .option("-w, --weight <n>", "Observation weight", parseFloat, 1)
50
+ .option("--json", "Output as JSON")
51
+ .action(async (did, score, options) => {
52
+ try {
53
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
54
+ const db = _dbFromCtx(ctx);
55
+ const obs = addObservation(db, did, Number(score), {
56
+ kind: options.kind,
57
+ weight: options.weight,
58
+ });
59
+ if (options.json) {
60
+ console.log(JSON.stringify(obs, null, 2));
61
+ } else {
62
+ logger.success(`Observation recorded`);
63
+ logger.log(` ${chalk.bold("DID:")} ${chalk.cyan(obs.did)}`);
64
+ logger.log(` ${chalk.bold("Score:")} ${obs.score}`);
65
+ logger.log(` ${chalk.bold("Kind:")} ${obs.kind}`);
66
+ }
67
+ await shutdown();
68
+ } catch (err) {
69
+ logger.error(`Failed: ${err.message}`);
70
+ process.exit(1);
71
+ }
72
+ });
73
+
74
+ rep
75
+ .command("score <did>")
76
+ .description("Compute aggregated reputation score for a DID")
77
+ .option(
78
+ "-d, --decay <model>",
79
+ "Decay model (none|exponential|linear|step)",
80
+ "none",
81
+ )
82
+ .option("--lambda <n>", "Exponential decay lambda", parseFloat)
83
+ .option("--alpha <n>", "Linear decay alpha", parseFloat)
84
+ .option("--json", "Output as JSON")
85
+ .action(async (did, options) => {
86
+ try {
87
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
88
+ _dbFromCtx(ctx);
89
+ const result = computeScore(did, {
90
+ decay: options.decay,
91
+ lambda: options.lambda,
92
+ alpha: options.alpha,
93
+ });
94
+ if (options.json) {
95
+ console.log(JSON.stringify(result, null, 2));
96
+ } else {
97
+ logger.log(
98
+ ` ${chalk.bold("DID:")} ${chalk.cyan(result.did)}`,
99
+ );
100
+ logger.log(` ${chalk.bold("Score:")} ${result.score}`);
101
+ logger.log(` ${chalk.bold("Observations:")} ${result.observations}`);
102
+ logger.log(` ${chalk.bold("Decay:")} ${result.decay}`);
103
+ }
104
+ await shutdown();
105
+ } catch (err) {
106
+ logger.error(`Failed: ${err.message}`);
107
+ process.exit(1);
108
+ }
109
+ });
110
+
111
+ rep
112
+ .command("list")
113
+ .description("List all tracked DIDs with computed scores")
114
+ .option("-d, --decay <model>", "Decay model", "none")
115
+ .option("--limit <n>", "Maximum entries", parseInt, 50)
116
+ .option("--json", "Output as JSON")
117
+ .action(async (options) => {
118
+ try {
119
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
120
+ _dbFromCtx(ctx);
121
+ const rows = listScores({
122
+ decay: options.decay,
123
+ limit: options.limit,
124
+ });
125
+ if (options.json) {
126
+ console.log(JSON.stringify(rows, null, 2));
127
+ } else if (rows.length === 0) {
128
+ logger.info("No reputation data recorded.");
129
+ } else {
130
+ for (const r of rows) {
131
+ logger.log(
132
+ ` ${chalk.cyan(r.did.slice(0, 24).padEnd(24))} score=${r.score} obs=${r.observations}`,
133
+ );
134
+ }
135
+ }
136
+ await shutdown();
137
+ } catch (err) {
138
+ logger.error(`Failed: ${err.message}`);
139
+ process.exit(1);
140
+ }
141
+ });
142
+
143
+ rep
144
+ .command("anomalies")
145
+ .description("Detect anomalies in current reputation scores")
146
+ .option(
147
+ "-m, --method <method>",
148
+ "Detection method (z_score|iqr)",
149
+ "z_score",
150
+ )
151
+ .option("-t, --threshold <n>", "Detection threshold", parseFloat)
152
+ .option(
153
+ "-d, --decay <model>",
154
+ "Decay model applied before detection",
155
+ "none",
156
+ )
157
+ .option("--json", "Output as JSON")
158
+ .action(async (options) => {
159
+ try {
160
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
161
+ _dbFromCtx(ctx);
162
+ const result = detectAnomalies({
163
+ method: options.method,
164
+ threshold: options.threshold,
165
+ decay: options.decay,
166
+ });
167
+ if (options.json) {
168
+ console.log(JSON.stringify(result, null, 2));
169
+ } else {
170
+ logger.log(` ${chalk.bold("Method:")} ${result.method}`);
171
+ logger.log(` ${chalk.bold("Samples:")} ${result.totalSamples}`);
172
+ if (result.message) {
173
+ logger.info(` ${result.message}`);
174
+ } else {
175
+ logger.log(` ${chalk.bold("Summary:")} ${result.summary}`);
176
+ for (const a of result.anomalies) {
177
+ logger.log(
178
+ ` ${chalk.yellow(a.did.slice(0, 24))} score=${a.score} ${a.reason}`,
179
+ );
180
+ }
181
+ }
182
+ }
183
+ await shutdown();
184
+ } catch (err) {
185
+ logger.error(`Failed: ${err.message}`);
186
+ process.exit(1);
187
+ }
188
+ });
189
+
190
+ rep
191
+ .command("optimize")
192
+ .description("Run parameter optimization over the reputation algorithm")
193
+ .option(
194
+ "-o, --objective <name>",
195
+ "Objective (accuracy|fairness|resilience|convergence_speed)",
196
+ "accuracy",
197
+ )
198
+ .option("-i, --iterations <n>", "Iteration count", parseInt, 50)
199
+ .option("--json", "Output as JSON")
200
+ .action(async (options) => {
201
+ try {
202
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
203
+ const db = _dbFromCtx(ctx);
204
+ const run = startOptimization(db, {
205
+ objective: options.objective,
206
+ iterations: options.iterations,
207
+ });
208
+ if (options.json) {
209
+ console.log(JSON.stringify(run, null, 2));
210
+ } else {
211
+ logger.success(`Optimization ${run.status}`);
212
+ logger.log(
213
+ ` ${chalk.bold("Run ID:")} ${chalk.cyan(run.runId)}`,
214
+ );
215
+ logger.log(` ${chalk.bold("Objective:")} ${run.objective}`);
216
+ logger.log(` ${chalk.bold("Iterations:")} ${run.iterations}`);
217
+ logger.log(` ${chalk.bold("Best score:")} ${run.bestScore}`);
218
+ logger.log(
219
+ ` ${chalk.bold("Best params:")} ${JSON.stringify(run.bestParams)}`,
220
+ );
221
+ for (const rec of run.analytics.recommendations) {
222
+ logger.log(` ${chalk.green("→")} ${rec}`);
223
+ }
224
+ }
225
+ await shutdown();
226
+ } catch (err) {
227
+ logger.error(`Failed: ${err.message}`);
228
+ process.exit(1);
229
+ }
230
+ });
231
+
232
+ rep
233
+ .command("status <run-id>")
234
+ .description("Show optimization run status")
235
+ .option("--json", "Output as JSON")
236
+ .action(async (runId, options) => {
237
+ try {
238
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
239
+ _dbFromCtx(ctx);
240
+ const run = getOptimizationStatus(runId);
241
+ if (options.json) {
242
+ console.log(JSON.stringify(run, null, 2));
243
+ } else {
244
+ logger.log(
245
+ ` ${chalk.bold("Run ID:")} ${chalk.cyan(run.runId)}`,
246
+ );
247
+ logger.log(` ${chalk.bold("Status:")} ${run.status}`);
248
+ logger.log(` ${chalk.bold("Objective:")} ${run.objective}`);
249
+ logger.log(` ${chalk.bold("Best score:")} ${run.bestScore}`);
250
+ logger.log(
251
+ ` ${chalk.bold("Best params:")} ${JSON.stringify(run.bestParams)}`,
252
+ );
253
+ }
254
+ await shutdown();
255
+ } catch (err) {
256
+ logger.error(`Failed: ${err.message}`);
257
+ process.exit(1);
258
+ }
259
+ });
260
+
261
+ rep
262
+ .command("analytics <run-id>")
263
+ .description("Show analytics for an optimization run")
264
+ .option("--json", "Output as JSON")
265
+ .action(async (runId, options) => {
266
+ try {
267
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
268
+ _dbFromCtx(ctx);
269
+ const a = getAnalytics(runId);
270
+ if (options.json) {
271
+ console.log(JSON.stringify(a, null, 2));
272
+ } else {
273
+ logger.log(` ${chalk.bold("Run ID:")} ${chalk.cyan(a.runId)}`);
274
+ logger.log(` ${chalk.bold("Distribution:")}`);
275
+ for (const b of a.reputationDistribution.buckets) {
276
+ logger.log(` ${b.label.padEnd(15)} ${b.count}`);
277
+ }
278
+ logger.log(
279
+ ` ${chalk.bold("Anomalies:")} ${a.anomalies.summary || a.anomalies.message || ""}`,
280
+ );
281
+ for (const r of a.recommendations) {
282
+ logger.log(` ${chalk.green("→")} ${r}`);
283
+ }
284
+ }
285
+ await shutdown();
286
+ } catch (err) {
287
+ logger.error(`Failed: ${err.message}`);
288
+ process.exit(1);
289
+ }
290
+ });
291
+
292
+ rep
293
+ .command("runs")
294
+ .description("List optimization run history")
295
+ .option("--limit <n>", "Maximum entries", parseInt, 10)
296
+ .option("--json", "Output as JSON")
297
+ .action(async (options) => {
298
+ try {
299
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
300
+ _dbFromCtx(ctx);
301
+ const rows = listOptimizationRuns({ limit: options.limit });
302
+ if (options.json) {
303
+ console.log(JSON.stringify(rows, null, 2));
304
+ } else if (rows.length === 0) {
305
+ logger.info("No optimization runs recorded.");
306
+ } else {
307
+ for (const r of rows) {
308
+ logger.log(
309
+ ` ${chalk.cyan(r.runId.slice(0, 8))} ${r.objective.padEnd(20)} iters=${r.iterations} best=${r.bestScore} [${r.status}]`,
310
+ );
311
+ }
312
+ }
313
+ await shutdown();
314
+ } catch (err) {
315
+ logger.error(`Failed: ${err.message}`);
316
+ process.exit(1);
317
+ }
318
+ });
319
+
320
+ rep
321
+ .command("apply <run-id>")
322
+ .description("Mark an optimization run as applied")
323
+ .action(async (runId) => {
324
+ try {
325
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
326
+ _dbFromCtx(ctx);
327
+ const r = applyOptimizedParams(runId);
328
+ logger.success(`Applied run ${runId.slice(0, 8)}`);
329
+ logger.log(` ${chalk.bold("Params:")} ${JSON.stringify(r.params)}`);
330
+ await shutdown();
331
+ } catch (err) {
332
+ logger.error(`Failed: ${err.message}`);
333
+ process.exit(1);
334
+ }
335
+ });
336
+
337
+ rep
338
+ .command("objectives")
339
+ .description("List supported optimization objectives")
340
+ .option("--json", "Output as JSON")
341
+ .action((options) => {
342
+ const values = Object.values(OPTIMIZATION_OBJECTIVES);
343
+ if (options.json) {
344
+ console.log(JSON.stringify(values, null, 2));
345
+ } else {
346
+ for (const v of values) logger.log(` ${chalk.cyan(v)}`);
347
+ }
348
+ });
349
+ }