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.
- package/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AppLayout-6SPt_8Y_.js → AppLayout-Rvi759IS.js} +1 -1
- package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
- package/src/assets/web-panel/assets/{Dashboard-Br7kCwKJ.js → Dashboard-DBhFxXYQ.js} +2 -2
- package/src/assets/web-panel/assets/{index-tN-8TosE.js → index-uL0cZ8N_.js} +2 -2
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/codegen.js +303 -0
- package/src/commands/collab.js +482 -0
- package/src/commands/crosschain.js +382 -0
- package/src/commands/dbevo.js +388 -0
- package/src/commands/dev.js +411 -0
- package/src/commands/federation.js +427 -0
- package/src/commands/fusion.js +332 -0
- package/src/commands/governance.js +505 -0
- package/src/commands/hardening.js +110 -0
- package/src/commands/incentive.js +373 -0
- package/src/commands/inference.js +304 -0
- package/src/commands/infra.js +361 -0
- package/src/commands/kg.js +371 -0
- package/src/commands/marketplace.js +326 -0
- package/src/commands/mcp.js +97 -18
- package/src/commands/nlprog.js +329 -0
- package/src/commands/ops.js +408 -0
- package/src/commands/perception.js +385 -0
- package/src/commands/pqc.js +34 -0
- package/src/commands/privacy.js +345 -0
- package/src/commands/quantization.js +280 -0
- package/src/commands/recommend.js +336 -0
- package/src/commands/reputation.js +349 -0
- package/src/commands/runtime.js +500 -0
- package/src/commands/sla.js +352 -0
- package/src/commands/stress.js +252 -0
- package/src/commands/tech.js +268 -0
- package/src/commands/tenant.js +576 -0
- package/src/commands/trust.js +366 -0
- package/src/harness/mcp-client.js +330 -54
- package/src/index.js +112 -0
- package/src/lib/aiops.js +523 -0
- package/src/lib/autonomous-developer.js +524 -0
- package/src/lib/code-agent.js +442 -0
- package/src/lib/collaboration-governance.js +556 -0
- package/src/lib/community-governance.js +649 -0
- package/src/lib/content-recommendation.js +600 -0
- package/src/lib/cross-chain.js +669 -0
- package/src/lib/dbevo.js +669 -0
- package/src/lib/decentral-infra.js +445 -0
- package/src/lib/federation-hardening.js +587 -0
- package/src/lib/hardening-manager.js +409 -0
- package/src/lib/inference-network.js +407 -0
- package/src/lib/knowledge-graph.js +530 -0
- package/src/lib/mcp-client.js +3 -0
- package/src/lib/multimodal.js +698 -0
- package/src/lib/nl-programming.js +595 -0
- package/src/lib/perception.js +500 -0
- package/src/lib/pqc-manager.js +141 -9
- package/src/lib/privacy-computing.js +575 -0
- package/src/lib/protocol-fusion.js +535 -0
- package/src/lib/quantization.js +362 -0
- package/src/lib/reputation-optimizer.js +509 -0
- package/src/lib/skill-marketplace.js +397 -0
- package/src/lib/sla-manager.js +484 -0
- package/src/lib/stress-tester.js +383 -0
- package/src/lib/tech-learning-engine.js +651 -0
- package/src/lib/tenant-saas.js +831 -0
- package/src/lib/token-incentive.js +513 -0
- package/src/lib/trust-security.js +473 -0
- package/src/lib/universal-runtime.js +771 -0
- package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
package/src/commands/mcp.js
CHANGED
|
@@ -9,7 +9,11 @@ import chalk from "chalk";
|
|
|
9
9
|
import ora from "ora";
|
|
10
10
|
import { logger } from "../lib/logger.js";
|
|
11
11
|
import { bootstrap, shutdown } from "../runtime/bootstrap.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
MCPClient,
|
|
14
|
+
MCPServerConfig,
|
|
15
|
+
inferTransport,
|
|
16
|
+
} from "../harness/mcp-client.js";
|
|
13
17
|
import {
|
|
14
18
|
validateMcpServer,
|
|
15
19
|
annotateMcpCompatibility,
|
|
@@ -111,9 +115,15 @@ export function registerMcpCommand(program) {
|
|
|
111
115
|
? chalk.green(" [ok]")
|
|
112
116
|
: chalk.yellow(` [blocked: ${s._reason}]`);
|
|
113
117
|
logger.log(` ${chalk.cyan(s.name)}${auto}${flag}`);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
if (s.url) {
|
|
119
|
+
logger.log(
|
|
120
|
+
` ${chalk.gray("URL:")} ${s.url} ${chalk.gray(`[${s.transport || s._transport || "http"}]`)}`,
|
|
121
|
+
);
|
|
122
|
+
} else {
|
|
123
|
+
logger.log(
|
|
124
|
+
` ${chalk.gray("Command:")} ${s.command} ${s.args.join(" ")}`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
117
127
|
logger.log(
|
|
118
128
|
` ${chalk.gray("Compatible:")} ${s._modeCompatibility.join(", ") || "(none)"}`,
|
|
119
129
|
);
|
|
@@ -132,8 +142,20 @@ export function registerMcpCommand(program) {
|
|
|
132
142
|
.command("add")
|
|
133
143
|
.description("Add or update an MCP server configuration")
|
|
134
144
|
.argument("<name>", "Server name")
|
|
135
|
-
.
|
|
145
|
+
.option("-c, --command <cmd>", "Server command to run (stdio transport)")
|
|
136
146
|
.option("-a, --args <args>", "Command arguments (comma-separated)")
|
|
147
|
+
.option(
|
|
148
|
+
"-u, --url <url>",
|
|
149
|
+
"Server URL (http / https / ws / wss transports)",
|
|
150
|
+
)
|
|
151
|
+
.option(
|
|
152
|
+
"-t, --transport <kind>",
|
|
153
|
+
"Transport kind: stdio | http | https | sse | ws | wss",
|
|
154
|
+
)
|
|
155
|
+
.option(
|
|
156
|
+
"-H, --header <header...>",
|
|
157
|
+
"HTTP header to include on requests (KEY=VALUE, repeatable)",
|
|
158
|
+
)
|
|
137
159
|
.option("--auto-connect", "Auto-connect on startup")
|
|
138
160
|
.option(
|
|
139
161
|
"--mode <mode>",
|
|
@@ -142,6 +164,17 @@ export function registerMcpCommand(program) {
|
|
|
142
164
|
.option("--json", "Output as JSON")
|
|
143
165
|
.action(async (name, options) => {
|
|
144
166
|
try {
|
|
167
|
+
if (!options.command && !options.url) {
|
|
168
|
+
logger.error(
|
|
169
|
+
"Provide either -c <command> (stdio) or -u <url> (http/ws).",
|
|
170
|
+
);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
if (options.command && options.url) {
|
|
174
|
+
logger.error("Use either -c <command> or -u <url>, not both.");
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
|
|
145
178
|
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
146
179
|
if (!ctx.db) {
|
|
147
180
|
logger.error("Database not available");
|
|
@@ -154,9 +187,43 @@ export function registerMcpCommand(program) {
|
|
|
154
187
|
? options.args.split(",").map((a) => a.trim())
|
|
155
188
|
: [];
|
|
156
189
|
|
|
190
|
+
// Parse -H KEY=VALUE into { headers }
|
|
191
|
+
const headers = {};
|
|
192
|
+
if (Array.isArray(options.header)) {
|
|
193
|
+
for (const raw of options.header) {
|
|
194
|
+
const eq = raw.indexOf("=");
|
|
195
|
+
if (eq <= 0) {
|
|
196
|
+
logger.warn(
|
|
197
|
+
`Ignored malformed --header "${raw}" (expected KEY=VALUE)`,
|
|
198
|
+
);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
headers[raw.slice(0, eq).trim()] = raw.slice(eq + 1);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const transport =
|
|
206
|
+
options.transport ||
|
|
207
|
+
(options.url ? inferTransport({ url: options.url }) : "stdio");
|
|
208
|
+
|
|
209
|
+
if (options.url) {
|
|
210
|
+
try {
|
|
211
|
+
new URL(options.url);
|
|
212
|
+
} catch (_e) {
|
|
213
|
+
logger.error(`Invalid URL: ${options.url}`);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
157
218
|
const mode = resolveMode(options);
|
|
158
219
|
const check = validateMcpServer(
|
|
159
|
-
{
|
|
220
|
+
{
|
|
221
|
+
name,
|
|
222
|
+
command: options.command,
|
|
223
|
+
args,
|
|
224
|
+
url: options.url,
|
|
225
|
+
transport,
|
|
226
|
+
},
|
|
160
227
|
mode,
|
|
161
228
|
);
|
|
162
229
|
if (!check.allowed) {
|
|
@@ -166,25 +233,37 @@ export function registerMcpCommand(program) {
|
|
|
166
233
|
}
|
|
167
234
|
|
|
168
235
|
config.add(name, {
|
|
169
|
-
command: options.command,
|
|
236
|
+
command: options.command || null,
|
|
170
237
|
args,
|
|
238
|
+
url: options.url || null,
|
|
239
|
+
transport,
|
|
240
|
+
env: {},
|
|
171
241
|
autoConnect: !!options.autoConnect,
|
|
242
|
+
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
172
243
|
});
|
|
173
244
|
|
|
245
|
+
const payload = {
|
|
246
|
+
name,
|
|
247
|
+
command: options.command || null,
|
|
248
|
+
args,
|
|
249
|
+
url: options.url || null,
|
|
250
|
+
transport,
|
|
251
|
+
autoConnect: !!options.autoConnect,
|
|
252
|
+
};
|
|
253
|
+
|
|
174
254
|
if (options.json) {
|
|
175
|
-
console.log(
|
|
176
|
-
JSON.stringify({
|
|
177
|
-
name,
|
|
178
|
-
command: options.command,
|
|
179
|
-
args,
|
|
180
|
-
autoConnect: !!options.autoConnect,
|
|
181
|
-
}),
|
|
182
|
-
);
|
|
255
|
+
console.log(JSON.stringify(payload));
|
|
183
256
|
} else {
|
|
184
257
|
logger.success(`MCP server "${chalk.cyan(name)}" configured`);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
258
|
+
if (options.url) {
|
|
259
|
+
logger.log(
|
|
260
|
+
` ${chalk.gray("URL:")} ${options.url} ${chalk.gray(`[${transport}]`)}`,
|
|
261
|
+
);
|
|
262
|
+
} else {
|
|
263
|
+
logger.log(
|
|
264
|
+
` ${chalk.gray("Command:")} ${options.command} ${args.join(" ")}`,
|
|
265
|
+
);
|
|
266
|
+
}
|
|
188
267
|
}
|
|
189
268
|
|
|
190
269
|
await shutdown();
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc nlprog` — CLI surface for Phase 28 Natural Language Programming.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
INTENT,
|
|
9
|
+
TRANSLATION_STATUS,
|
|
10
|
+
STYLE_CATEGORY,
|
|
11
|
+
ensureNlProgrammingTables,
|
|
12
|
+
classifyIntent,
|
|
13
|
+
extractEntities,
|
|
14
|
+
detectTechStack,
|
|
15
|
+
scoreCompleteness,
|
|
16
|
+
translate,
|
|
17
|
+
getTranslation,
|
|
18
|
+
listTranslations,
|
|
19
|
+
updateTranslationStatus,
|
|
20
|
+
refineTranslation,
|
|
21
|
+
removeTranslation,
|
|
22
|
+
addConvention,
|
|
23
|
+
getConvention,
|
|
24
|
+
listConventions,
|
|
25
|
+
removeConvention,
|
|
26
|
+
getNlProgrammingStats,
|
|
27
|
+
} from "../lib/nl-programming.js";
|
|
28
|
+
|
|
29
|
+
function _dbFromCtx(cmd) {
|
|
30
|
+
const root = cmd?.parent?.parent ?? cmd?.parent;
|
|
31
|
+
return root?._db;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function registerNlProgCommand(program) {
|
|
35
|
+
const nlp = new Command("nlprog")
|
|
36
|
+
.description("Natural language programming system (Phase 28)")
|
|
37
|
+
.hook("preAction", (thisCmd) => {
|
|
38
|
+
const db = _dbFromCtx(thisCmd);
|
|
39
|
+
if (db) ensureNlProgrammingTables(db);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
/* ── Catalogs ────────────────────────────────────── */
|
|
43
|
+
|
|
44
|
+
nlp
|
|
45
|
+
.command("intents")
|
|
46
|
+
.description("List supported intent types")
|
|
47
|
+
.option("--json", "JSON output")
|
|
48
|
+
.action((opts) => {
|
|
49
|
+
const intents = Object.values(INTENT);
|
|
50
|
+
if (opts.json) return console.log(JSON.stringify(intents, null, 2));
|
|
51
|
+
for (const i of intents) console.log(` ${i}`);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
nlp
|
|
55
|
+
.command("statuses")
|
|
56
|
+
.description("List translation statuses")
|
|
57
|
+
.option("--json", "JSON output")
|
|
58
|
+
.action((opts) => {
|
|
59
|
+
const statuses = Object.values(TRANSLATION_STATUS);
|
|
60
|
+
if (opts.json) return console.log(JSON.stringify(statuses, null, 2));
|
|
61
|
+
for (const s of statuses) console.log(` ${s}`);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
nlp
|
|
65
|
+
.command("style-categories")
|
|
66
|
+
.description("List style analysis categories")
|
|
67
|
+
.option("--json", "JSON output")
|
|
68
|
+
.action((opts) => {
|
|
69
|
+
const cats = Object.values(STYLE_CATEGORY);
|
|
70
|
+
if (opts.json) return console.log(JSON.stringify(cats, null, 2));
|
|
71
|
+
for (const c of cats) console.log(` ${c}`);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/* ── Analysis (stateless) ───────────────────────── */
|
|
75
|
+
|
|
76
|
+
nlp
|
|
77
|
+
.command("classify <text>")
|
|
78
|
+
.description("Classify intent of natural language input")
|
|
79
|
+
.option("--json", "JSON output")
|
|
80
|
+
.action((text, opts) => {
|
|
81
|
+
const result = classifyIntent(text);
|
|
82
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
83
|
+
console.log(`Intent: ${result.intent}`);
|
|
84
|
+
console.log(`Confidence: ${result.confidence}`);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
nlp
|
|
88
|
+
.command("extract <text>")
|
|
89
|
+
.description("Extract entities from natural language input")
|
|
90
|
+
.option("--json", "JSON output")
|
|
91
|
+
.action((text, opts) => {
|
|
92
|
+
const result = extractEntities(text);
|
|
93
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
94
|
+
if (result.count === 0) return console.log("No entities found.");
|
|
95
|
+
console.log(`Found ${result.count} entity(ies):`);
|
|
96
|
+
for (const e of result.entities) {
|
|
97
|
+
console.log(` [${e.type}] ${e.value}`);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
nlp
|
|
102
|
+
.command("detect-stack <text>")
|
|
103
|
+
.description("Detect technology stack from text")
|
|
104
|
+
.option("--json", "JSON output")
|
|
105
|
+
.action((text, opts) => {
|
|
106
|
+
const result = detectTechStack(text);
|
|
107
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
108
|
+
if (result.detected.length === 0)
|
|
109
|
+
return console.log("No tech stack detected.");
|
|
110
|
+
console.log(`Primary: ${result.primary}`);
|
|
111
|
+
console.log(`All: ${result.detected.join(", ")}`);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/* ── Translation ────────────────────────────────── */
|
|
115
|
+
|
|
116
|
+
nlp
|
|
117
|
+
.command("translate <text>")
|
|
118
|
+
.description("Translate natural language to spec (heuristic)")
|
|
119
|
+
.option("-i, --intent <intent>", "Override intent classification")
|
|
120
|
+
.option("-s, --spec <json>", "Attach spec JSON")
|
|
121
|
+
.option("-a, --ambiguities <json>", "Ambiguity list JSON")
|
|
122
|
+
.option("--json", "JSON output")
|
|
123
|
+
.action((text, opts) => {
|
|
124
|
+
const db = _dbFromCtx(nlp);
|
|
125
|
+
const result = translate(db, {
|
|
126
|
+
text,
|
|
127
|
+
intent: opts.intent,
|
|
128
|
+
spec: opts.spec,
|
|
129
|
+
ambiguities: opts.ambiguities,
|
|
130
|
+
});
|
|
131
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
132
|
+
if (result.translated) {
|
|
133
|
+
console.log(`Translation: ${result.translationId}`);
|
|
134
|
+
console.log(`Intent: ${result.intent}`);
|
|
135
|
+
console.log(`Completeness: ${result.completeness}`);
|
|
136
|
+
} else console.log(`Failed: ${result.reason}`);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
nlp
|
|
140
|
+
.command("show <id>")
|
|
141
|
+
.description("Show translation details")
|
|
142
|
+
.option("--json", "JSON output")
|
|
143
|
+
.action((id, opts) => {
|
|
144
|
+
const db = _dbFromCtx(nlp);
|
|
145
|
+
const t = getTranslation(db, id);
|
|
146
|
+
if (!t) return console.log("Translation not found.");
|
|
147
|
+
if (opts.json) return console.log(JSON.stringify(t, null, 2));
|
|
148
|
+
console.log(`ID: ${t.id}`);
|
|
149
|
+
console.log(`Input: ${t.input_text.slice(0, 80)}`);
|
|
150
|
+
console.log(`Intent: ${t.intent}`);
|
|
151
|
+
console.log(`Status: ${t.status}`);
|
|
152
|
+
console.log(`Completeness: ${t.completeness_score}`);
|
|
153
|
+
if (t.entities) console.log(`Entities: ${t.entities.slice(0, 60)}`);
|
|
154
|
+
if (t.tech_stack) console.log(`Tech Stack: ${t.tech_stack}`);
|
|
155
|
+
if (t.ambiguities)
|
|
156
|
+
console.log(`Ambiguities: ${t.ambiguities.slice(0, 60)}`);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
nlp
|
|
160
|
+
.command("list")
|
|
161
|
+
.description("List translations")
|
|
162
|
+
.option("-i, --intent <intent>", "Filter by intent")
|
|
163
|
+
.option("-s, --status <status>", "Filter by status")
|
|
164
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
165
|
+
.option("--json", "JSON output")
|
|
166
|
+
.action((opts) => {
|
|
167
|
+
const db = _dbFromCtx(nlp);
|
|
168
|
+
const results = listTranslations(db, {
|
|
169
|
+
intent: opts.intent,
|
|
170
|
+
status: opts.status,
|
|
171
|
+
limit: opts.limit,
|
|
172
|
+
});
|
|
173
|
+
if (opts.json) return console.log(JSON.stringify(results, null, 2));
|
|
174
|
+
if (results.length === 0) return console.log("No translations.");
|
|
175
|
+
for (const t of results) {
|
|
176
|
+
console.log(
|
|
177
|
+
` ${t.intent.padEnd(18)} ${t.status.padEnd(10)} comp:${String(t.completeness_score).padEnd(6)} ${t.input_text.slice(0, 40).padEnd(42)} ${t.id.slice(0, 8)}`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
nlp
|
|
183
|
+
.command("status <id> <status>")
|
|
184
|
+
.description("Update translation status (draft/complete/refined)")
|
|
185
|
+
.option("--json", "JSON output")
|
|
186
|
+
.action((id, status, opts) => {
|
|
187
|
+
const db = _dbFromCtx(nlp);
|
|
188
|
+
const result = updateTranslationStatus(db, id, status);
|
|
189
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
190
|
+
console.log(
|
|
191
|
+
result.updated
|
|
192
|
+
? `Status updated to: ${result.status}`
|
|
193
|
+
: `Failed: ${result.reason}`,
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
nlp
|
|
198
|
+
.command("refine <id>")
|
|
199
|
+
.description("Refine a translation with updated spec")
|
|
200
|
+
.option("-s, --spec <json>", "Updated spec JSON")
|
|
201
|
+
.option("-a, --ambiguities <json>", "Updated ambiguities JSON")
|
|
202
|
+
.option("--json", "JSON output")
|
|
203
|
+
.action((id, opts) => {
|
|
204
|
+
const db = _dbFromCtx(nlp);
|
|
205
|
+
const result = refineTranslation(db, id, {
|
|
206
|
+
spec: opts.spec,
|
|
207
|
+
ambiguities: opts.ambiguities,
|
|
208
|
+
});
|
|
209
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
210
|
+
if (result.refined)
|
|
211
|
+
console.log(`Refined (completeness: ${result.completeness})`);
|
|
212
|
+
else console.log(`Failed: ${result.reason}`);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
nlp
|
|
216
|
+
.command("remove <id>")
|
|
217
|
+
.description("Remove a translation")
|
|
218
|
+
.option("--json", "JSON output")
|
|
219
|
+
.action((id, opts) => {
|
|
220
|
+
const db = _dbFromCtx(nlp);
|
|
221
|
+
const result = removeTranslation(db, id);
|
|
222
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
223
|
+
console.log(
|
|
224
|
+
result.removed ? "Translation removed." : `Failed: ${result.reason}`,
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
/* ── Conventions ────────────────────────────────── */
|
|
229
|
+
|
|
230
|
+
nlp
|
|
231
|
+
.command("convention-add")
|
|
232
|
+
.description("Add a project convention")
|
|
233
|
+
.requiredOption(
|
|
234
|
+
"-c, --category <cat>",
|
|
235
|
+
"Category (naming/architecture/testing/style/imports/components)",
|
|
236
|
+
)
|
|
237
|
+
.requiredOption("-p, --pattern <text>", "Pattern description")
|
|
238
|
+
.option("-e, --examples <json>", "Examples JSON")
|
|
239
|
+
.option("-f, --confidence <n>", "Confidence (0-1)", parseFloat)
|
|
240
|
+
.option("-s, --source-files <json>", "Source files JSON")
|
|
241
|
+
.option("--json", "JSON output")
|
|
242
|
+
.action((opts) => {
|
|
243
|
+
const db = _dbFromCtx(nlp);
|
|
244
|
+
const result = addConvention(db, {
|
|
245
|
+
category: opts.category,
|
|
246
|
+
pattern: opts.pattern,
|
|
247
|
+
examples: opts.examples,
|
|
248
|
+
confidence: opts.confidence,
|
|
249
|
+
sourceFiles: opts.sourceFiles,
|
|
250
|
+
});
|
|
251
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
252
|
+
if (result.added) console.log(`Convention added: ${result.conventionId}`);
|
|
253
|
+
else console.log(`Failed: ${result.reason}`);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
nlp
|
|
257
|
+
.command("convention-show <id>")
|
|
258
|
+
.description("Show convention details")
|
|
259
|
+
.option("--json", "JSON output")
|
|
260
|
+
.action((id, opts) => {
|
|
261
|
+
const db = _dbFromCtx(nlp);
|
|
262
|
+
const c = getConvention(db, id);
|
|
263
|
+
if (!c) return console.log("Convention not found.");
|
|
264
|
+
if (opts.json) return console.log(JSON.stringify(c, null, 2));
|
|
265
|
+
console.log(`ID: ${c.id}`);
|
|
266
|
+
console.log(`Category: ${c.category}`);
|
|
267
|
+
console.log(`Pattern: ${c.pattern}`);
|
|
268
|
+
console.log(`Confidence: ${c.confidence}`);
|
|
269
|
+
if (c.examples) console.log(`Examples: ${c.examples.slice(0, 60)}`);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
nlp
|
|
273
|
+
.command("conventions")
|
|
274
|
+
.description("List project conventions")
|
|
275
|
+
.option("-c, --category <cat>", "Filter by category")
|
|
276
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
277
|
+
.option("--json", "JSON output")
|
|
278
|
+
.action((opts) => {
|
|
279
|
+
const db = _dbFromCtx(nlp);
|
|
280
|
+
const results = listConventions(db, {
|
|
281
|
+
category: opts.category,
|
|
282
|
+
limit: opts.limit,
|
|
283
|
+
});
|
|
284
|
+
if (opts.json) return console.log(JSON.stringify(results, null, 2));
|
|
285
|
+
if (results.length === 0) return console.log("No conventions.");
|
|
286
|
+
for (const c of results) {
|
|
287
|
+
console.log(
|
|
288
|
+
` ${c.category.padEnd(14)} conf:${String(c.confidence).padEnd(5)} ${c.pattern.slice(0, 40).padEnd(42)} ${c.id.slice(0, 8)}`,
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
nlp
|
|
294
|
+
.command("convention-remove <id>")
|
|
295
|
+
.description("Remove a convention")
|
|
296
|
+
.option("--json", "JSON output")
|
|
297
|
+
.action((id, opts) => {
|
|
298
|
+
const db = _dbFromCtx(nlp);
|
|
299
|
+
const result = removeConvention(db, id);
|
|
300
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
301
|
+
console.log(
|
|
302
|
+
result.removed ? "Convention removed." : `Failed: ${result.reason}`,
|
|
303
|
+
);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
/* ── Stats ──────────────────────────────────────── */
|
|
307
|
+
|
|
308
|
+
nlp
|
|
309
|
+
.command("stats")
|
|
310
|
+
.description("NL Programming statistics")
|
|
311
|
+
.option("--json", "JSON output")
|
|
312
|
+
.action((opts) => {
|
|
313
|
+
const db = _dbFromCtx(nlp);
|
|
314
|
+
const s = getNlProgrammingStats(db);
|
|
315
|
+
if (opts.json) return console.log(JSON.stringify(s, null, 2));
|
|
316
|
+
console.log(
|
|
317
|
+
`Translations: ${s.translations.total} (avg completeness: ${s.translations.avgCompleteness})`,
|
|
318
|
+
);
|
|
319
|
+
for (const [intent, count] of Object.entries(s.translations.byIntent)) {
|
|
320
|
+
if (count > 0) console.log(` ${intent.padEnd(18)} ${count}`);
|
|
321
|
+
}
|
|
322
|
+
console.log(`Conventions: ${s.conventions.total}`);
|
|
323
|
+
for (const [cat, count] of Object.entries(s.conventions.byCategory)) {
|
|
324
|
+
if (count > 0) console.log(` ${cat.padEnd(14)} ${count}`);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
program.addCommand(nlp);
|
|
329
|
+
}
|