@miphamai/cli 0.33.2 → 0.34.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.
@@ -929,6 +929,553 @@ const sisCleanupCmd: CommandHandler = async (ctx) => {
929
929
  return { content: lines.join('\n') }
930
930
  }
931
931
 
932
+ // ═══════════════════════════════════════════════════════════════
933
+ // CRSI Critique — Self-Critique Hook (RLAIF)
934
+ // ═══════════════════════════════════════════════════════════════
935
+
936
+ const crsiCritiqueCmd: CommandHandler = (ctx, args) => {
937
+ const t = resolveT(ctx)
938
+ const engine = ctx.engine
939
+ const sc = engine.getSelfCritique?.()
940
+ if (!sc) {
941
+ return { content: 'SelfCritique 未初始化。请确认 Mipham Code 版本 >= v0.34.0。' }
942
+ }
943
+
944
+ const sub = args[0]?.toLowerCase()
945
+ const config = sc.getConfig()
946
+
947
+ if (sub === 'on' || sub === 'enable') {
948
+ sc.setEnabled(true)
949
+ return {
950
+ content: [
951
+ '## 🔍 Self-Critique: ON',
952
+ '',
953
+ `Model: **${config.model || 'auto (fastest available)'}**`,
954
+ `Threshold: **${(config.threshold * 100).toFixed(0)}%**`,
955
+ `Target tools: **${config.targetTools.join(', ')}**`,
956
+ '',
957
+ 'The AI will now critique its own tool calls before execution.',
958
+ 'Safe + correct + necessary checks run before every targeted tool call.',
959
+ '',
960
+ '💡 `/crsi critique off` to disable | `/crsi critique status` for current config',
961
+ ].join('\n'),
962
+ }
963
+ }
964
+
965
+ if (sub === 'off' || sub === 'disable') {
966
+ sc.setEnabled(false)
967
+ return {
968
+ content: '## 🔍 Self-Critique: OFF\n\nTool calls will execute without pre-flight critique.',
969
+ }
970
+ }
971
+
972
+ // status (default)
973
+ const lines: string[] = [
974
+ '## 🔍 Self-Critique Status',
975
+ '',
976
+ `State: **${config.enabled ? '🟢 Enabled' : '⚫ Disabled'}**`,
977
+ `Model: **${config.model || 'auto (fastest available)'}**`,
978
+ `Threshold: **${(config.threshold * 100).toFixed(0)}%** (below this → correction or block)`,
979
+ `Target tools: **${config.targetTools.length > 0 ? config.targetTools.join(', ') : 'all'}**`,
980
+ `Timeout: **${config.timeoutMs}ms**`,
981
+ '',
982
+ '──',
983
+ '🔍 `/crsi critique on` — Enable self-critique',
984
+ '🔍 `/crsi critique off` — Disable self-critique',
985
+ '',
986
+ '*Inspired by Anthropic RLAIF — AI critiques its own actions before execution.*',
987
+ ]
988
+
989
+ return { content: lines.join('\n') }
990
+ }
991
+
992
+ // ═══════════════════════════════════════════════════════════════
993
+ // CRSI Interpret — Tool-Call Behavior Dashboard
994
+ // ═══════════════════════════════════════════════════════════════
995
+
996
+ const crsiInterpretCmd: CommandHandler = (ctx, args) => {
997
+ const t = resolveT(ctx)
998
+ const engine = ctx.engine
999
+ const toolFilter = args[0]?.toLowerCase()
1000
+
1001
+ const lines: string[] = ['## 🧠 CRSI Tool-Call Interpretability', '']
1002
+
1003
+ // ── Error Signature Analysis ──
1004
+ const db = engine.getErrorSignatureDB?.()
1005
+ if (db) {
1006
+ const sigs = toolFilter
1007
+ ? db.getActive().filter((s) => s.toolName.toLowerCase() === toolFilter)
1008
+ : db.getActive()
1009
+
1010
+ if (sigs.length === 0) {
1011
+ lines.push(
1012
+ toolFilter
1013
+ ? `No error signatures for tool \`${toolFilter}\`. CRSI immune memory is clean for this tool.`
1014
+ : 'No active error signatures. CRSI immune memory is clean.',
1015
+ )
1016
+ } else {
1017
+ lines.push(`### 🛡️ Error Signatures${toolFilter ? ` — \`${toolFilter}\`` : ''}`, '')
1018
+ for (const sig of sigs.slice(0, 15)) {
1019
+ const bar =
1020
+ '█'.repeat(Math.round(sig.successRate * 10)) +
1021
+ '░'.repeat(10 - Math.round(sig.successRate * 10))
1022
+ lines.push(`- **${sig.toolName}**: \`${sig.pattern.slice(0, 60)}\``)
1023
+ lines.push(
1024
+ ` Success: ${bar} ${Math.round(sig.successRate * 100)}% | ${sig.occurrences}x | ${sig.fixStrategy}`,
1025
+ )
1026
+ lines.push(` Fix: \`${sig.fixAction.slice(0, 80)}\``)
1027
+ lines.push('')
1028
+ }
1029
+ if (sigs.length > 15) lines.push(`... and ${sigs.length - 15} more signatures`, '')
1030
+ }
1031
+ }
1032
+
1033
+ // ── CRSI Reflection Summary ──
1034
+ const autoMemory = engine.getAutoMemory?.()
1035
+ if (autoMemory) {
1036
+ const count = autoMemory.sessionReflectionCount ?? 0
1037
+ if (count > 0) {
1038
+ lines.push('### 📊 CRSI Reflection Summary', '')
1039
+ lines.push(`Turn reflections analyzed: **${count}**`)
1040
+ lines.push('')
1041
+ }
1042
+ }
1043
+
1044
+ // ── Usage Tracker by Tool ──
1045
+ const usage = engine.getUsageTracker?.()
1046
+ if (usage) {
1047
+ const summary = usage.getSummary()
1048
+ lines.push('### 💰 Token Usage', '')
1049
+ lines.push(`API input tokens: ${summary.apiInputTokens.toLocaleString()}`)
1050
+ lines.push(`API output tokens: ${summary.apiOutputTokens.toLocaleString()}`)
1051
+ lines.push(`Estimated tokens: ${summary.estimatedTokens.toLocaleString()}`)
1052
+ lines.push('')
1053
+ }
1054
+
1055
+ // ── System Health ──
1056
+ const meta = engine.getMetaRuleEngine?.()
1057
+ if (meta) {
1058
+ try {
1059
+ const analysis = meta.analyze()
1060
+ if (analysis.systemHealth) {
1061
+ const h = analysis.systemHealth
1062
+ const bar = '█'.repeat(Math.round(h.score / 10)) + '░'.repeat(10 - Math.round(h.score / 10))
1063
+ lines.push('### 🏥 System Health', '')
1064
+ lines.push(`Overall: ${bar} **${h.score}/100**`)
1065
+ lines.push(`Assessment: ${h.assessment}`)
1066
+ if (h.components) {
1067
+ lines.push('')
1068
+ for (const [comp, score] of Object.entries(h.components)) {
1069
+ const cbar =
1070
+ '▮'.repeat(Math.round((score as number) / 10)) +
1071
+ '▯'.repeat(10 - Math.round((score as number) / 10))
1072
+ lines.push(` ${comp.padEnd(20)} ${cbar} ${score}/100`)
1073
+ }
1074
+ }
1075
+ lines.push('')
1076
+ }
1077
+ } catch {
1078
+ // Meta analysis unavailable
1079
+ }
1080
+ }
1081
+
1082
+ // ── Constitution Health ──
1083
+ const constitution = engine.getConstitutionLoader?.()
1084
+ if (constitution) {
1085
+ const c = constitution.load()
1086
+ const blocks = c.principles.filter((p) => p.enforce === 'block').length
1087
+ const warns = c.principles.filter((p) => p.enforce === 'warn').length
1088
+ const autos = c.principles.filter((p) => p.enforce === 'auto').length
1089
+ lines.push('### ⚖️ Constitution', '')
1090
+ lines.push(
1091
+ `Principles: **${c.principles.length}** (🚫 ${blocks} block | ⚠️ ${warns} warn | 🔄 ${autos} auto)`,
1092
+ )
1093
+ lines.push(`Version: v${c.version}`)
1094
+ lines.push('')
1095
+ }
1096
+
1097
+ if (lines.length <= 2) {
1098
+ lines.push('_Start using tools to populate CRSI interpretability data._')
1099
+ }
1100
+
1101
+ lines.push('──')
1102
+ lines.push('🔍 Filter by tool: `/crsi interpret <tool-name>` (e.g. `/crsi interpret Bash`)')
1103
+
1104
+ return { content: lines.join('\n') }
1105
+ }
1106
+
1107
+ // ═══════════════════════════════════════════════════════════════
1108
+ // CRSI Red-Team — Adversarial Self-Testing
1109
+ // ═══════════════════════════════════════════════════════════════
1110
+
1111
+ const crsiRedTeamCmd: CommandHandler = async (ctx) => {
1112
+ const t = resolveT(ctx)
1113
+ const engine = ctx.engine
1114
+
1115
+ const constitution = engine.getConstitutionLoader?.()
1116
+ const preflight = engine.getPreFlightChecker?.()
1117
+
1118
+ if (!constitution || !preflight) {
1119
+ return { content: 'Red-Team 需要 ConstitutionLoader 和 PreFlightChecker 均已初始化。' }
1120
+ }
1121
+
1122
+ const { RedTeam: RT } = await import('../../src/core/red-team.js')
1123
+ const redTeam = new RT()
1124
+ const report = redTeam.run(constitution, preflight)
1125
+
1126
+ const lines: string[] = [
1127
+ '## 🔴 CRSI Red-Team Report',
1128
+ '',
1129
+ `Overall Score: **${report.score}/100**`,
1130
+ '',
1131
+ `| Metric | Count |`,
1132
+ `|--------|------|`,
1133
+ `| Total attacks | ${report.total} |`,
1134
+ `| 🛡️ Correctly blocked | ${report.blocked} |`,
1135
+ `| 🔴 Passed through (GAP) | ${report.passedThrough} |`,
1136
+ `| ⚠️ False positives | ${report.falsePositives} |`,
1137
+ '',
1138
+ ]
1139
+
1140
+ // Per-principle breakdown
1141
+ lines.push('### By Principle', '')
1142
+ for (const [pid, stats] of Object.entries(report.byPrinciple)) {
1143
+ const pct = stats.total > 0 ? Math.round((stats.blocked / stats.total) * 100) : 100
1144
+ const bar = '█'.repeat(Math.round(pct / 10)) + '░'.repeat(10 - Math.round(pct / 10))
1145
+ const icon = pct === 100 ? '✅' : pct >= 80 ? '⚠️' : '🔴'
1146
+ lines.push(`- ${icon} **${pid}**: ${bar} ${pct}% (${stats.blocked}/${stats.total})`)
1147
+ }
1148
+ lines.push('')
1149
+
1150
+ // Detail: passed-through attacks
1151
+ const gaps = report.results.filter((r) => r.attack.shouldBlock && !r.blocked)
1152
+ if (gaps.length > 0) {
1153
+ lines.push('### 🔴 Security Gaps (Should Have Been Blocked)', '')
1154
+ for (const g of gaps) {
1155
+ lines.push(`- **${g.attack.principleId}**: ${g.attack.description}`)
1156
+ lines.push(
1157
+ ` Tool: \`${g.attack.toolName}\` → Params: \`${JSON.stringify(g.attack.params).slice(0, 80)}\``,
1158
+ )
1159
+ }
1160
+ lines.push('')
1161
+ }
1162
+
1163
+ // Detail: caught attacks
1164
+ const caught = report.results.filter((r) => r.blocked)
1165
+ if (caught.length > 0) {
1166
+ lines.push('### 🛡️ Successfully Blocked', '')
1167
+ for (const c of caught) {
1168
+ lines.push(`- ${c.attack.principleId}: ${c.attack.description} → caught by **${c.caughtBy}**`)
1169
+ }
1170
+ lines.push('')
1171
+ }
1172
+
1173
+ if (report.score === 100) {
1174
+ lines.push('🎉 **All attacks blocked!** The SIS immune system is fully operational.')
1175
+ } else if (report.score >= 80) {
1176
+ lines.push(
1177
+ '⚠️ Good coverage. Review the gaps above and add audit patterns to `ai-guardrails.yml`.',
1178
+ )
1179
+ } else {
1180
+ lines.push('🔴 **Critical gaps detected.** Prioritize fixing the passed-through attacks above.')
1181
+ }
1182
+
1183
+ return { content: lines.join('\n') }
1184
+ }
1185
+
1186
+ // ═══════════════════════════════════════════════════════════════
1187
+ // Auto-Dream: Background Memory Consolidation
1188
+ // ═══════════════════════════════════════════════════════════════
1189
+
1190
+ const dreamCmd: CommandHandler = async (ctx, args) => {
1191
+ const t = resolveT(ctx)
1192
+ const aggressive = args.includes('--aggressive') || args.includes('-a')
1193
+ const status = args.includes('--status') || args.includes('-s')
1194
+
1195
+ const engine = ctx.engine.getDreamEngine?.()
1196
+ if (!engine) {
1197
+ return { content: 'DreamEngine 未初始化。请确认 Mipham Code 版本 >= v0.34.0。' }
1198
+ }
1199
+
1200
+ if (status) {
1201
+ const history = engine.getDreamHistory()
1202
+ if (history.length === 0) {
1203
+ return { content: '🌙 尚未运行过 Auto-Dream。使用 `/dream` 手动触发首次梦境整合。' }
1204
+ }
1205
+ const lines: string[] = ['## 🌙 Auto-Dream 历史', '']
1206
+ for (const entry of history.slice(0, 5)) {
1207
+ const ts = new Date(entry.timestamp).toLocaleString('zh-CN')
1208
+ const total = entry.actions.length
1209
+ const applied = entry.actions.filter((a) => a.autoApplied).length
1210
+ const flagged = entry.actions.filter((a) => !a.autoApplied).length
1211
+ lines.push(`- **${ts}**: ${total} 行动 (${applied} 自动应用, ${flagged} 标记审查)`)
1212
+ }
1213
+ return { content: lines.join('\n') }
1214
+ }
1215
+
1216
+ const report = engine.dream({ aggressive })
1217
+ const lines: string[] = [
1218
+ '## 🌙 Auto-Dream 完成',
1219
+ '',
1220
+ `记忆整合: ${report.beforeCount} → ${report.afterCount}`,
1221
+ ...(report.phases.deduplicated > 0 ? [`- 去重: ${report.phases.deduplicated} 条`] : []),
1222
+ ...(report.phases.contradictionsFound > 0
1223
+ ? [`- 矛盾冲突: ${report.phases.contradictionsFound} 处 (需人工裁决)`]
1224
+ : []),
1225
+ ...(report.phases.merged > 0 ? [`- 合并: ${report.phases.merged} 组`] : []),
1226
+ ...(report.phases.solidified > 0
1227
+ ? [`- 模糊标记: ${report.phases.solidified} 条 (建议固化)`]
1228
+ : []),
1229
+ ...(report.phases.pruned > 0 ? [`- 清理过期: ${report.phases.pruned} 条`] : []),
1230
+ '',
1231
+ ]
1232
+
1233
+ const flagged = report.actions.filter((a) => !a.autoApplied)
1234
+ if (flagged.length > 0 && !aggressive) {
1235
+ lines.push(`⚠️ ${flagged.length} 项待审查。使用 \`/dream --aggressive\` 自动应用所有操作。`)
1236
+ lines.push('')
1237
+ for (const action of flagged) {
1238
+ lines.push(`- [ ] **${action.type}**: ${action.description}`)
1239
+ }
1240
+ }
1241
+
1242
+ if (report.actions.length === 0) {
1243
+ lines.push('✅ 记忆干净,无需整理。')
1244
+ }
1245
+
1246
+ return { content: lines.join('\n') }
1247
+ }
1248
+
1249
+ // ═══════════════════════════════════════════════════════════════
1250
+ // Constitution
1251
+ // ═══════════════════════════════════════════════════════════════
1252
+
1253
+ const constitutionCmd: CommandHandler = (ctx, args) => {
1254
+ const t = resolveT(ctx)
1255
+ const engine = ctx.engine
1256
+ const constitution = engine.getConstitutionLoader?.()
1257
+ if (!constitution) {
1258
+ return { content: 'ConstitutionLoader 未初始化。请确认 Mipham Code 版本 >= v0.34.0。' }
1259
+ }
1260
+
1261
+ const subCmd = args[0]?.toLowerCase()
1262
+
1263
+ // /constitution reload
1264
+ if (subCmd === 'reload') {
1265
+ const c = constitution.reload()
1266
+ return {
1267
+ content: [
1268
+ '## ⚖️ Constitution Reloaded',
1269
+ '',
1270
+ `Version: **v${c.version}**`,
1271
+ `Principles: **${c.principles.length}**`,
1272
+ `Path: \`${constitution.getPath()}\``,
1273
+ '',
1274
+ c.principles.map((p) => `- **${p.id}** [${p.enforce}]: ${p.text}`).join('\n'),
1275
+ ].join('\n'),
1276
+ }
1277
+ }
1278
+
1279
+ // /constitution view (default)
1280
+ const c = constitution.load()
1281
+ const lines: string[] = [
1282
+ '## ⚖️ Mipham Constitution',
1283
+ '',
1284
+ `Version: **v${c.version}** | Principles: **${c.principles.length}** | Path: \`${constitution.getPath()}\``,
1285
+ '',
1286
+ '---',
1287
+ '',
1288
+ ]
1289
+
1290
+ for (const p of c.principles) {
1291
+ const icon = p.enforce === 'block' ? '🚫' : p.enforce === 'warn' ? '⚠️' : '🔄'
1292
+ lines.push(`### ${icon} ${p.id} [${p.enforce}]`)
1293
+ lines.push('')
1294
+ lines.push(p.text)
1295
+ if (p.rationale) lines.push(` *${p.rationale}*`)
1296
+ if (p.scope) lines.push(` Scope: \`${p.scope}\``)
1297
+ if (p.tools) lines.push(` Tools: ${p.tools.join(', ')}`)
1298
+ lines.push('')
1299
+ }
1300
+
1301
+ lines.push('---')
1302
+ lines.push('')
1303
+ lines.push('🔧 `/constitution reload` — 重新加载(修改 ai-guardrails.yml 后使用)')
1304
+ lines.push('📝 编辑: `vi ~/.mipham/ai-guardrails.yml`')
1305
+ lines.push('🗑️ 重置: 删除 `~/.mipham/ai-guardrails.yml` 后执行 `/constitution reload`')
1306
+ lines.push('')
1307
+ lines.push(
1308
+ '*Inspired by Anthropic Constitutional AI. Mipham enforces these principles at runtime — auditable on every action.*',
1309
+ )
1310
+
1311
+ return { content: lines.join('\n') }
1312
+ }
1313
+
1314
+ // ═══════════════════════════════════════════════════════════════
1315
+ // Bug Report
1316
+ // ═══════════════════════════════════════════════════════════════
1317
+
1318
+ const bugReportCmd: CommandHandler = async (ctx) => {
1319
+ const t = resolveT(ctx)
1320
+ const engine = ctx.engine
1321
+ const lines: string[] = [
1322
+ '## 🐛 Bug Report',
1323
+ '',
1324
+ '> Copy the report below and paste it into your GitHub Issue.',
1325
+ '',
1326
+ '---',
1327
+ '',
1328
+ ]
1329
+
1330
+ // ── Version & Runtime ──
1331
+ lines.push('### Environment', '')
1332
+ lines.push(`- **Mipham Code**: v${ctx.version}`)
1333
+ lines.push(`- **Session**: ${ctx.sessionId}`)
1334
+ lines.push(`- **Node**: ${process.version}`)
1335
+ lines.push(`- **Platform**: ${process.platform} ${process.arch}`)
1336
+ lines.push(
1337
+ `- **OS**: ${process.platform === 'darwin' ? 'macOS' : process.platform === 'linux' ? 'Linux' : 'Windows'}`,
1338
+ )
1339
+ lines.push(`- **Provider**: ${ctx.providerId}`)
1340
+ lines.push(`- **Model**: ${ctx.modelId}`)
1341
+ lines.push('')
1342
+
1343
+ // ── SIS errors ──
1344
+ try {
1345
+ const db = engine.getErrorSignatureDB?.()
1346
+ if (db) {
1347
+ const active = db.getActive()
1348
+ if (active.length > 0) {
1349
+ lines.push('### Active Error Signatures', '')
1350
+ for (const sig of active.slice(0, 10)) {
1351
+ lines.push(
1352
+ `- \`${sig.id}\`: ${sig.pattern} (${sig.category}, ${sig.occurrences}x, ${(sig.successRate * 100).toFixed(0)}% success)`,
1353
+ )
1354
+ }
1355
+ lines.push('')
1356
+ }
1357
+ }
1358
+ } catch {
1359
+ // SIS unavailable
1360
+ }
1361
+
1362
+ // ── Hook health ──
1363
+ try {
1364
+ const hookEngine = engine.getHookEngine?.()
1365
+ if (hookEngine) {
1366
+ const health = hookEngine.getHookHealth()
1367
+ const disabled = health.filter((h) => h.health.disabled)
1368
+ if (disabled.length > 0) {
1369
+ lines.push('### Disabled Hooks', '')
1370
+ for (const entry of disabled) {
1371
+ lines.push(
1372
+ `- \`${entry.key}\`: ${entry.health.failures} failures, disabled at ${new Date(entry.health.disabledAt).toISOString()}`,
1373
+ )
1374
+ }
1375
+ lines.push('')
1376
+ }
1377
+ }
1378
+ } catch {
1379
+ // Hook health unavailable
1380
+ }
1381
+
1382
+ // ── Recent dream log ──
1383
+ try {
1384
+ const dreamEngine = engine.getDreamEngine?.()
1385
+ if (dreamEngine) {
1386
+ const history = dreamEngine.getDreamHistory()
1387
+ if (history.length > 0) {
1388
+ const last = history[0]!
1389
+ lines.push('### Last Auto-Dream', '')
1390
+ lines.push(`- **Ran at**: ${last.timestamp}`)
1391
+ lines.push(
1392
+ `- **Actions**: ${last.actions.length} (${last.actions.filter((a: { autoApplied: boolean }) => a.autoApplied).length} applied)`,
1393
+ )
1394
+ lines.push('')
1395
+ }
1396
+ }
1397
+ } catch {
1398
+ // Dream engine unavailable
1399
+ }
1400
+
1401
+ // ── Steps to reproduce (template) ──
1402
+ lines.push('### Steps to Reproduce', '')
1403
+ lines.push('1. ')
1404
+ lines.push('2. ')
1405
+ lines.push('3. ')
1406
+ lines.push('')
1407
+ lines.push('### Expected Behavior', '')
1408
+ lines.push('')
1409
+ lines.push('### Actual Behavior', '')
1410
+ lines.push('')
1411
+ lines.push('---')
1412
+ lines.push(`🤖 Generated with Mipham Code v${ctx.version}`)
1413
+
1414
+ return { content: lines.join('\n'), copyContent: lines.join('\n') }
1415
+ }
1416
+
1417
+ // ═══════════════════════════════════════════════════════════════
1418
+ // Feedback
1419
+ // ═══════════════════════════════════════════════════════════════
1420
+ // Changelog
1421
+ // ═══════════════════════════════════════════════════════════════
1422
+
1423
+ const changelogCmd: CommandHandler = async (ctx) => {
1424
+ const t = resolveT(ctx)
1425
+ const lines: string[] = ['## 📋 Changelog', '']
1426
+
1427
+ try {
1428
+ const { execSync } = await import('node:child_process')
1429
+ const tags = execSync('git tag --sort=-creatordate', { encoding: 'utf-8', timeout: 5000 })
1430
+ .trim()
1431
+ .split('\n')
1432
+ .filter(Boolean)
1433
+ .slice(0, 15)
1434
+
1435
+ if (tags.length === 0) {
1436
+ lines.push('No version tags found.')
1437
+ return { content: lines.join('\n') }
1438
+ }
1439
+
1440
+ lines.push(`Current: **v${ctx.version}**`, '')
1441
+
1442
+ for (let i = 0; i < tags.length; i++) {
1443
+ const tag = tags[i]!
1444
+ const nextTag = tags[i + 1]
1445
+ try {
1446
+ const range = nextTag ? `${nextTag}..${tag}` : tag
1447
+ const log = execSync(
1448
+ `git log --oneline --no-merges ${range} --format="%s" 2>/dev/null | head -8`,
1449
+ { encoding: 'utf-8', timeout: 5000 },
1450
+ )
1451
+ .trim()
1452
+ .split('\n')
1453
+ .filter(Boolean)
1454
+
1455
+ const isCurrent = tag === `v${ctx.version}`
1456
+ lines.push(`### ${tag}${isCurrent ? ' ← current' : ''}`, '')
1457
+ if (log.length > 0) {
1458
+ for (const entry of log) {
1459
+ lines.push(`- ${entry}`)
1460
+ }
1461
+ } else {
1462
+ lines.push(' _(release tag only)_')
1463
+ }
1464
+ lines.push('')
1465
+ } catch {
1466
+ lines.push(`### ${tag}`, '', ' _(details unavailable)_', '')
1467
+ }
1468
+ }
1469
+ } catch {
1470
+ lines.push('Unable to read git history. Make sure you are in the Mipham Code repository.')
1471
+ }
1472
+
1473
+ lines.push('---')
1474
+ lines.push(`Full history: \`git log --oneline\``)
1475
+
1476
+ return { content: lines.join('\n') }
1477
+ }
1478
+
932
1479
  // ═══════════════════════════════════════════════════════════════
933
1480
  // Workflow
934
1481
  // ═══════════════════════════════════════════════════════════════
@@ -2147,25 +2694,69 @@ const statsCmd: CommandHandler = (ctx) => {
2147
2694
  const assistantMsgs = msgs.filter((m) => m.role === 'assistant').length
2148
2695
  const systemMsgs = msgs.filter((m) => m.role === 'system').length
2149
2696
 
2150
- return {
2151
- content: [
2152
- t('commands.stats.title'),
2153
- '',
2154
- t('commands.stats.messages', {
2155
- total: String(msgs.length),
2156
- user: String(userMsgs),
2157
- assistant: String(assistantMsgs),
2158
- system: String(systemMsgs),
2159
- }),
2160
- t('commands.stats.tokens', { tokens: tokens.toLocaleString() }),
2161
- t('commands.stats.tools', { count: String(tools.size) }),
2162
- t('commands.stats.provider', { provider: ctx.providerId }),
2163
- t('commands.stats.model', { model: ctx.modelId }),
2164
- t('commands.stats.permission', { permission: ctx.config.permission }),
2165
- '',
2166
- t('commands.stats.usage', { pct: ((tokens / 200_000) * 100).toFixed(1) }),
2167
- ].join('\n'),
2697
+ const base = [
2698
+ t('commands.stats.title'),
2699
+ '',
2700
+ t('commands.stats.messages', {
2701
+ total: String(msgs.length),
2702
+ user: String(userMsgs),
2703
+ assistant: String(assistantMsgs),
2704
+ system: String(systemMsgs),
2705
+ }),
2706
+ t('commands.stats.tokens', { tokens: tokens.toLocaleString() }),
2707
+ t('commands.stats.tools', { count: String(tools.size) }),
2708
+ t('commands.stats.provider', { provider: ctx.providerId }),
2709
+ t('commands.stats.model', { model: ctx.modelId }),
2710
+ t('commands.stats.permission', { permission: ctx.config.permission }),
2711
+ '',
2712
+ t('commands.stats.usage', { pct: ((tokens / 200_000) * 100).toFixed(1) }),
2713
+ ]
2714
+
2715
+ // ── CRSI & SIS extensions ──
2716
+ const engine = ctx.engine
2717
+ const extras: string[] = []
2718
+
2719
+ try {
2720
+ const db = engine.getErrorSignatureDB?.()
2721
+ if (db) {
2722
+ const s = db.getStats()
2723
+ if (s.total > 0) {
2724
+ extras.push(
2725
+ '',
2726
+ '── SIS Self-Immune ──',
2727
+ `Signatures: ${s.total} total, ${s.active} active | Success rate: ${(s.avgSuccessRate * 100).toFixed(0)}%`,
2728
+ )
2729
+ }
2730
+ }
2731
+ } catch {
2732
+ /* SIS not initialized */
2168
2733
  }
2734
+
2735
+ try {
2736
+ const autoMemory = engine.getAutoMemory?.()
2737
+ if (autoMemory) {
2738
+ const count = autoMemory.sessionReflectionCount ?? 0
2739
+ if (count > 0) extras.push(`CRSI Reflections: ${count} turn(s) analyzed`)
2740
+ }
2741
+ } catch {
2742
+ /* CRSI not initialized */
2743
+ }
2744
+
2745
+ try {
2746
+ const meta = engine.getMetaRuleEngine?.()
2747
+ if (meta) {
2748
+ const analysis = meta.analyze()
2749
+ if (analysis.systemHealth) {
2750
+ extras.push(
2751
+ `System Health: ${analysis.systemHealth.score}/100 — ${analysis.systemHealth.assessment}`,
2752
+ )
2753
+ }
2754
+ }
2755
+ } catch {
2756
+ /* Meta not initialized */
2757
+ }
2758
+
2759
+ return { content: [...base, ...extras].join('\n') }
2169
2760
  }
2170
2761
 
2171
2762
  const summaryCmd: CommandHandler = (ctx) => {
@@ -3157,31 +3748,57 @@ To switch providers without clearing keys, use /switch <provider> <model>.`,
3157
3748
  // Phase 4 — Feedback
3158
3749
  // ═══════════════════════════════════════════════════════════════
3159
3750
 
3160
- const feedbackCmd: CommandHandler = (ctx, args) => {
3751
+ const feedbackCmd: CommandHandler = async (ctx, args) => {
3161
3752
  const message = args.join(' ').trim()
3162
3753
 
3163
3754
  const lines: string[] = ['── Feedback ──', '']
3164
3755
 
3756
+ // If a message was provided, save it to ~/.mipham/feedback/
3165
3757
  if (message) {
3166
- lines.push('Your feedback:')
3167
- lines.push('')
3168
- lines.push(' """')
3169
- for (const line of message.split('\n')) {
3170
- lines.push(' ' + line)
3758
+ try {
3759
+ const { writeFileSync, mkdirSync, existsSync } = await import('node:fs')
3760
+ const { join } = await import('node:path')
3761
+ const { homedir } = await import('node:os')
3762
+
3763
+ const dir = join(homedir(), '.mipham', 'feedback')
3764
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
3765
+
3766
+ const ts = new Date().toISOString().replace(/[:.]/g, '-')
3767
+ const file = join(dir, `feedback-${ts}.md`)
3768
+ const content = [
3769
+ '---',
3770
+ `timestamp: ${new Date().toISOString()}`,
3771
+ `version: ${ctx.version}`,
3772
+ `session: ${ctx.sessionId}`,
3773
+ `provider: ${ctx.providerId}`,
3774
+ `model: ${ctx.modelId}`,
3775
+ '---',
3776
+ '',
3777
+ message,
3778
+ ].join('\n')
3779
+ writeFileSync(file, content, 'utf-8')
3780
+
3781
+ lines.push('Your feedback:')
3782
+ lines.push('')
3783
+ lines.push(' """')
3784
+ for (const line of message.split('\n')) {
3785
+ lines.push(' ' + line)
3786
+ }
3787
+ lines.push(' """')
3788
+ lines.push('')
3789
+ lines.push(`✅ Saved to \`${file}\``)
3790
+ lines.push('')
3791
+ } catch (err) {
3792
+ lines.push(`⚠️ Save failed: ${String(err)}`)
3793
+ lines.push('')
3171
3794
  }
3172
- lines.push(' """')
3173
- lines.push('')
3174
- lines.push('── Preview Complete ──')
3175
- lines.push('')
3176
- lines.push('Copy the above and submit via one of the channels below.')
3177
- lines.push('')
3178
3795
  }
3179
3796
 
3180
3797
  lines.push('── Feedback Channels ──')
3181
3798
  lines.push('')
3182
3799
  lines.push(' 🐛 Bug Reports')
3183
3800
  lines.push(' GitHub Issues: https://github.com/One-Mipham/mipham-code/issues')
3184
- lines.push(' Template: Bug Report (include version + reproduction steps)')
3801
+ lines.push(' Or run `/bug-report` to auto-generate a diagnostic report')
3185
3802
  lines.push('')
3186
3803
  lines.push(' 💡 Feature Requests')
3187
3804
  lines.push(' GitHub Issues: https://github.com/One-Mipham/mipham-code/issues')
@@ -3562,6 +4179,10 @@ const commandsListCmd: CommandHandler = () => {
3562
4179
  '/recap': 'Session & Identity',
3563
4180
  '/export': 'Session & Identity',
3564
4181
  '/doctor': 'Session & Identity',
4182
+ '/dream': 'Session & Identity',
4183
+ '/constitution': 'Session & Identity',
4184
+ '/bug-report': 'Session & Identity',
4185
+ '/changelog': 'Session & Identity',
3565
4186
  '/resume': 'Session & Identity',
3566
4187
  '/resume last': 'Session & Identity',
3567
4188
  '/resume delete': 'Session & Identity',
@@ -3604,6 +4225,9 @@ const commandsListCmd: CommandHandler = () => {
3604
4225
  '/crsi stats': 'Tools & Skills',
3605
4226
  '/crsi health': 'Tools & Skills',
3606
4227
  '/crsi meta': 'Tools & Skills',
4228
+ '/crsi interpret': 'Tools & Skills',
4229
+ '/crsi critique': 'Tools & Skills',
4230
+ '/crsi red-team': 'Tools & Skills',
3607
4231
  '/sis errors': 'Tools & Skills',
3608
4232
  '/sis stats': 'Tools & Skills',
3609
4233
  '/sis clear': 'Tools & Skills',
@@ -3753,10 +4377,17 @@ registry.set('/crsi restore', crsiRestoreCmd)
3753
4377
  registry.set('/crsi stats', crsiStatsCmd)
3754
4378
  registry.set('/crsi health', crsiHealthCmd)
3755
4379
  registry.set('/crsi meta', crsiMetaCmd)
4380
+ registry.set('/crsi interpret', crsiInterpretCmd)
4381
+ registry.set('/crsi critique', crsiCritiqueCmd)
4382
+ registry.set('/crsi red-team', crsiRedTeamCmd)
3756
4383
  registry.set('/sis errors', sisErrorsCmd)
3757
4384
  registry.set('/sis stats', sisStatsCmd)
3758
4385
  registry.set('/sis clear', sisClearCmd)
3759
4386
  registry.set('/sis cleanup', sisCleanupCmd)
4387
+ registry.set('/dream', dreamCmd)
4388
+ registry.set('/constitution', constitutionCmd)
4389
+ registry.set('/bug-report', bugReportCmd)
4390
+ registry.set('/changelog', changelogCmd)
3760
4391
 
3761
4392
  // Workflow
3762
4393
  registry.set('/plan', planCmd)
@@ -3877,6 +4508,10 @@ const COMMAND_DESCRIPTIONS: Record<string, string> = {
3877
4508
  '/recap': 'Summarize session so far',
3878
4509
  '/export': 'Export conversation to file',
3879
4510
  '/doctor': 'System diagnostics',
4511
+ '/dream': 'Background memory consolidation',
4512
+ '/constitution': 'View or reload constitutional principles',
4513
+ '/bug-report': 'Generate diagnostic report for GitHub Issues',
4514
+ '/changelog': 'Recent version history',
3880
4515
  '/resume': 'List saved sessions',
3881
4516
  '/resume last': 'Restore the most recent saved session',
3882
4517
  '/resume delete': 'Delete a saved session',
@@ -3917,6 +4552,9 @@ const COMMAND_DESCRIPTIONS: Record<string, string> = {
3917
4552
  '/crsi stats': 'Show CRSI overall effectiveness statistics',
3918
4553
  '/crsi health': 'CRSI + SIS unified health dashboard with scoring',
3919
4554
  '/crsi meta': 'RSI Level 3 meta-rule analysis — rules that improve the rules',
4555
+ '/crsi interpret': 'Tool-call behavior dashboard — error patterns, usage, health',
4556
+ '/crsi critique': 'Enable/disable RLAIF self-critique on tool calls',
4557
+ '/crsi red-team': 'Run adversarial self-test — verify SIS blocks known attacks',
3920
4558
  '/sis errors': 'List all active SIS immune memory signatures',
3921
4559
  '/sis stats': 'Show SIS self-immune system aggregate statistics',
3922
4560
  '/sis clear': 'Retire an immune memory signature by ID',