@miphamai/cli 0.32.6 → 0.33.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.
@@ -0,0 +1,218 @@
1
+ /**
2
+ * SIS (Self-Immune System) Phase 0: Pre-Flight Checker
3
+ *
4
+ * Pre-execution interception layer that checks tool calls against:
5
+ * 1. ErrorSignatureDB — known error patterns with proven fixes
6
+ * 2. ExperienceRuleEngine — CRSI Phase 1 dynamic rules
7
+ *
8
+ * Returns one of four actions:
9
+ * - 'allow' → no issue, proceed normally
10
+ * - 'warn' → known risky pattern, show warning but allow
11
+ * - 'fix' → known error with proven fix, auto-correct params
12
+ * - 'block' → known dangerous pattern, refuse execution
13
+ *
14
+ * Priority: block > fix > warn > allow
15
+ * (most restrictive action wins when multiple sources match)
16
+ */
17
+
18
+ import type { ErrorSignatureDB, ErrorSignature } from './error-signature-db.js'
19
+ import type { ExperienceRuleEngine } from './rule-engine.js'
20
+
21
+ // ── Types ──
22
+
23
+ export interface PreFlightResult {
24
+ /** The action to take */
25
+ action: 'allow' | 'warn' | 'fix' | 'block'
26
+ /** Warning message (for 'warn' and 'block' actions) */
27
+ warning?: string
28
+ /** Modified parameters (for 'fix' action) */
29
+ modifiedParams?: Record<string, unknown>
30
+ /** Matched error signature ID (for tracking) */
31
+ matchedSignature?: string
32
+ /** Human-readable explanation of the fix */
33
+ explanation?: string
34
+ }
35
+
36
+ // ── Action Priority ──
37
+
38
+ const ACTION_PRIORITY: Record<PreFlightResult['action'], number> = {
39
+ allow: 0,
40
+ warn: 1,
41
+ fix: 2,
42
+ block: 3,
43
+ }
44
+
45
+ // ── Checker ──
46
+
47
+ export class PreFlightChecker {
48
+ private errorDB: ErrorSignatureDB
49
+ private ruleEngine?: ExperienceRuleEngine
50
+
51
+ constructor(errorDB: ErrorSignatureDB, ruleEngine?: ExperienceRuleEngine) {
52
+ this.errorDB = errorDB
53
+ this.ruleEngine = ruleEngine
54
+ }
55
+
56
+ /**
57
+ * Check a tool call before execution.
58
+ *
59
+ * @param toolName — e.g. 'Bash', 'Write', 'Grep'
60
+ * @param params — tool input parameters
61
+ * @returns PreFlightResult with the strictest applicable action
62
+ */
63
+ check(toolName: string, params: Record<string, unknown>): PreFlightResult {
64
+ const results: PreFlightResult[] = []
65
+
66
+ // ── Layer 1: ErrorSignatureDB ──
67
+ const sig = this.errorDB.match(toolName, params)
68
+ if (sig) {
69
+ results.push(this.signatureToResult(sig, params))
70
+ }
71
+
72
+ // ── Layer 2: ExperienceRuleEngine ──
73
+ if (this.ruleEngine) {
74
+ const ruleResult = this.checkRuleEngine(toolName, params)
75
+ if (ruleResult) {
76
+ results.push(ruleResult)
77
+ }
78
+ }
79
+
80
+ // ── Merge: pick the most restrictive result ──
81
+ if (results.length === 0) {
82
+ return { action: 'allow' }
83
+ }
84
+
85
+ return results.reduce((best, curr) =>
86
+ ACTION_PRIORITY[curr.action] > ACTION_PRIORITY[best.action] ? curr : best,
87
+ )
88
+ }
89
+
90
+ /**
91
+ * Set/update the rule engine reference.
92
+ * Useful when the rule engine is wired after construction.
93
+ */
94
+ setRuleEngine(ruleEngine: ExperienceRuleEngine): void {
95
+ this.ruleEngine = ruleEngine
96
+ }
97
+
98
+ // ── Private: Signature Conversion ──
99
+
100
+ /**
101
+ * Convert an ErrorSignature to a PreFlightResult based on its fixStrategy.
102
+ */
103
+ private signatureToResult(sig: ErrorSignature, params: Record<string, unknown>): PreFlightResult {
104
+ const base = {
105
+ matchedSignature: sig.id,
106
+ explanation: sig.explanation,
107
+ }
108
+
109
+ switch (sig.fixStrategy) {
110
+ case 'block':
111
+ return {
112
+ ...base,
113
+ action: 'block',
114
+ warning: `⛔ SIS 免疫拦截: ${sig.explanation} (${sig.occurrences} 次历史发生,成功率 ${Math.round(sig.successRate * 100)}%)`,
115
+ }
116
+
117
+ case 'warn':
118
+ return {
119
+ ...base,
120
+ action: 'warn',
121
+ warning: `⚠️ SIS 预警: ${sig.explanation} (${sig.occurrences} 次历史发生)`,
122
+ }
123
+
124
+ case 'replace':
125
+ return {
126
+ ...base,
127
+ action: 'fix',
128
+ warning: `🔧 SIS 自动修复: ${sig.explanation}`,
129
+ modifiedParams: this.applyReplace(sig),
130
+ }
131
+
132
+ case 'prepend':
133
+ return {
134
+ ...base,
135
+ action: 'fix',
136
+ warning: `🔧 SIS 自动修复: ${sig.explanation}`,
137
+ modifiedParams: this.applyPrepend(params, sig),
138
+ }
139
+
140
+ case 'append':
141
+ return {
142
+ ...base,
143
+ action: 'fix',
144
+ warning: `🔧 SIS 自动修复: ${sig.explanation}`,
145
+ modifiedParams: this.applyAppend(params, sig),
146
+ }
147
+
148
+ default:
149
+ return { ...base, action: 'warn', warning: sig.explanation }
150
+ }
151
+ }
152
+
153
+ // ── Private: Rule Engine Check ──
154
+
155
+ /**
156
+ * Check against the ExperienceRuleEngine.
157
+ * Converts the rule engine's {modified, warnings} output to a PreFlightResult.
158
+ */
159
+ private checkRuleEngine(
160
+ toolName: string,
161
+ params: Record<string, unknown>,
162
+ ): PreFlightResult | null {
163
+ if (!this.ruleEngine) return null
164
+
165
+ try {
166
+ const { modified, warnings } = this.ruleEngine.intercept(toolName, params)
167
+ const hasWarnings = warnings.length > 0
168
+ const hasModifications = JSON.stringify(modified) !== JSON.stringify(params)
169
+
170
+ if (!hasWarnings && !hasModifications) return null
171
+
172
+ if (hasModifications) {
173
+ return {
174
+ action: 'fix',
175
+ warning: warnings.join('; '),
176
+ modifiedParams: modified,
177
+ explanation: 'CRSI 规则引擎自动修正',
178
+ }
179
+ }
180
+
181
+ if (hasWarnings) {
182
+ return {
183
+ action: 'warn',
184
+ warning: warnings.join('; '),
185
+ }
186
+ }
187
+ } catch {
188
+ // Rule engine errors are non-fatal
189
+ }
190
+
191
+ return null
192
+ }
193
+
194
+ // ── Private: Fix Application Helpers ──
195
+
196
+ /** 'replace' strategy: replace the entire command string. */
197
+ private applyReplace(sig: ErrorSignature): Record<string, unknown> {
198
+ return { command: sig.fixAction }
199
+ }
200
+
201
+ /** 'prepend' strategy: prepend text to the command. */
202
+ private applyPrepend(
203
+ params: Record<string, unknown>,
204
+ sig: ErrorSignature,
205
+ ): Record<string, unknown> {
206
+ const cmd = String(params.command ?? '')
207
+ return { ...params, command: `${sig.fixAction} ${cmd}` }
208
+ }
209
+
210
+ /** 'append' strategy: append text to the command. */
211
+ private applyAppend(
212
+ params: Record<string, unknown>,
213
+ sig: ErrorSignature,
214
+ ): Record<string, unknown> {
215
+ const cmd = String(params.command ?? '')
216
+ return { ...params, command: `${cmd} ${sig.fixAction}` }
217
+ }
218
+ }
@@ -4,7 +4,15 @@ import { resolveSafe } from '../../security/path'
4
4
 
5
5
  export const grepTool: ToolDefinition = {
6
6
  name: 'Grep',
7
- description: 'Search file contents using ripgrep. Fast regex search across files.',
7
+ description:
8
+ 'Search file contents using ripgrep (rg) — the recommended code search tool. ' +
9
+ '~10× faster than grep, with automatic fallback to grep if rg is unavailable. ' +
10
+ 'Use this for single-shot regex searches across files. ' +
11
+ 'Prefer Grep over Bash grep/rg for code search; use Bash only for complex ' +
12
+ 'multi-step pipelines (e.g., pipe to sort/uniq/wc, or chained find+xargs). ' +
13
+ 'Best practice: narrow scope with `path` (directory/file) and `include` ' +
14
+ '(glob pattern, e.g. "*.ts") before searching. ' +
15
+ 'The `pattern` parameter accepts full regex syntax (e.g., "log.*Error", "\\bclass\\s+\\w+").',
8
16
  category: 'file',
9
17
  permission: 'auto',
10
18
  parameters: {
@@ -17,6 +17,31 @@ interface CommandPickerProps {
17
17
 
18
18
  const PAGE_SIZE = 12
19
19
 
20
+ /**
21
+ * Split a string into segments, marking which substrings match the query.
22
+ * Case-insensitive matching. Used to bold matching characters in the picker.
23
+ */
24
+ function highlightMatches(text: string, query: string): { text: string; match: boolean }[] {
25
+ if (!query) return [{ text, match: false }]
26
+ const lowerText = text.toLowerCase()
27
+ const lowerQuery = query.toLowerCase()
28
+ const segments: { text: string; match: boolean }[] = []
29
+ let pos = 0
30
+ while (pos < text.length) {
31
+ const idx = lowerText.indexOf(lowerQuery, pos)
32
+ if (idx === -1) {
33
+ segments.push({ text: text.slice(pos), match: false })
34
+ break
35
+ }
36
+ if (idx > pos) {
37
+ segments.push({ text: text.slice(pos, idx), match: false })
38
+ }
39
+ segments.push({ text: text.slice(idx, idx + query.length), match: true })
40
+ pos = idx + query.length
41
+ }
42
+ return segments
43
+ }
44
+
20
45
  /**
21
46
  * CommandPicker — interactive slash-command selector.
22
47
  *
@@ -107,12 +132,20 @@ export function CommandPicker({
107
132
  {visible.map((cmd, i) => {
108
133
  const globalIdx = i + scrollStart
109
134
  const isCursor = globalIdx === cursorIdx
135
+ const query = filter.startsWith('/') ? filter.slice(1) : filter
136
+ const segments = highlightMatches(cmd.name, query)
137
+ const padLen = Math.max(0, 20 - cmd.name.length)
110
138
  return (
111
139
  <Box key={cmd.name}>
112
140
  <Text color={itemColor(isCursor)} bold={itemBold(isCursor)}>
113
141
  {isCursor ? '▶ ' : ' '}
114
- {cmd.name.padEnd(20)}
115
142
  </Text>
143
+ {segments.map((seg, j) => (
144
+ <Text key={j} color={itemColor(isCursor)} bold={itemBold(isCursor) || seg.match}>
145
+ {seg.text}
146
+ </Text>
147
+ ))}
148
+ {padLen > 0 && <Text color={itemColor(isCursor)}>{' '.repeat(padLen)}</Text>}
116
149
  <Text dimColor>{cmd.description}</Text>
117
150
  </Box>
118
151
  )
@@ -656,6 +656,257 @@ const crsiStatsCmd: CommandHandler = async (ctx) => {
656
656
  return { content: lines.join('\n') }
657
657
  }
658
658
 
659
+ const crsiHealthCmd: CommandHandler = async (ctx) => {
660
+ const engine = ctx.engine.getRuleEngine()
661
+ const tracker = ctx.engine.getEffectivenessTracker()
662
+ const db = ctx.engine.getErrorSignatureDB?.()
663
+ const patternAnalyzer = ctx.engine.getPatternAnalyzer?.()
664
+
665
+ const lines: string[] = ['## 🏥 CRSI 系统健康仪表盘', '']
666
+
667
+ // ── CRSI Section ──
668
+ lines.push('### 🧠 CRSI 学习子系统', '')
669
+ if (engine) {
670
+ const rules = engine.getActiveRules()
671
+ const builtin = rules.filter((r) => r.source === 'builtin').length
672
+ const auto = rules.filter((r) => r.source === 'pattern-analyzer').length
673
+ const manual = rules.filter((r) => r.source === 'manual').length
674
+
675
+ lines.push(`| 指标 | 值 |`)
676
+ lines.push(`|------|----|`)
677
+ lines.push(`| 活跃规则 | ${rules.length} (内置 ${builtin} · 自动 ${auto} · 手动 ${manual}) |`)
678
+
679
+ if (tracker) {
680
+ let interceptions = 0
681
+ let successes = 0
682
+ for (const r of rules) {
683
+ const eff = tracker.getEffectiveness(r.id)
684
+ if (eff) {
685
+ interceptions += eff.appliedCount
686
+ successes += eff.successAfterCount
687
+ }
688
+ }
689
+ const crsiRate = interceptions > 0 ? Math.round((successes / interceptions) * 100) : 100
690
+ lines.push(`| 总拦截次数 | ${interceptions} |`)
691
+ lines.push(`| 拦截成功率 | ${crsiRate}% |`)
692
+ }
693
+
694
+ // Pattern analysis depth
695
+ if (patternAnalyzer) {
696
+ const patterns = patternAnalyzer.analyzeAllAgents()
697
+ lines.push(`| 已检测模式 | ${patterns.length} |`)
698
+ }
699
+
700
+ lines.push('')
701
+ lines.push('CRSI 命令: `/crsi rules` `/crsi stats` `/crsi analyze`')
702
+ } else {
703
+ lines.push('CRSI 规则引擎未初始化')
704
+ }
705
+
706
+ // ── SIS Section ──
707
+ lines.push('', '### 🛡️ SIS 自免疫子系统', '')
708
+ if (db) {
709
+ const stats = db.getStats()
710
+ const healthEmoji =
711
+ stats.avgSuccessRate >= 0.8 ? '🟢' : stats.avgSuccessRate >= 0.5 ? '🟡' : '🔴'
712
+
713
+ lines.push(`| 指标 | 值 |`)
714
+ lines.push(`|------|----|`)
715
+ lines.push(
716
+ `| 免疫记忆 | ${stats.total} 条 (🟢${stats.active} · 🟡${stats.degraded} · ⚫${stats.retired}) |`,
717
+ )
718
+ lines.push(`| 平均成功率 | ${Math.round(stats.avgSuccessRate * 100)}% |`)
719
+ lines.push(`| 总拦截 | ${stats.totalInterceptions} 次 |`)
720
+
721
+ lines.push('')
722
+ lines.push('SIS 命令: `/sis errors` `/sis stats` `/sis clear <id>`')
723
+ } else {
724
+ lines.push('SIS 自免疫系统未初始化')
725
+ }
726
+
727
+ // ── Overall Health Score ──
728
+ lines.push('', '### 📊 综合健康评分', '')
729
+ const crsiScore = engine ? 50 : 0
730
+ const sisScore = db ? (db.getStats().avgSuccessRate >= 0.8 ? 50 : 25) : 0
731
+ const totalScore = crsiScore + sisScore
732
+
733
+ const grade =
734
+ totalScore >= 80
735
+ ? '🟢 A — 优秀'
736
+ : totalScore >= 50
737
+ ? '🟡 B — 良好'
738
+ : totalScore >= 25
739
+ ? '🟠 C — 需关注'
740
+ : '🔴 D — 待初始化'
741
+
742
+ lines.push(`| 子系统 | 状态 | 得分 |`)
743
+ lines.push(`|--------|------|------|`)
744
+ lines.push(`| CRSI 学习 | ${engine ? '✅ 在线' : '❌ 离线'} | ${crsiScore}/50 |`)
745
+ lines.push(`| SIS 免疫 | ${db ? '✅ 在线' : '❌ 离线'} | ${sisScore}/50 |`)
746
+ lines.push(`| **综合** | **${grade}** | **${totalScore}/100** |`)
747
+
748
+ return { content: lines.join('\n') }
749
+ }
750
+
751
+ const crsiMetaCmd: CommandHandler = async (ctx) => {
752
+ const metaEngine = ctx.engine.getMetaRuleEngine?.()
753
+ if (!metaEngine) {
754
+ return { content: 'MetaRuleEngine 未初始化。请先运行 `/crsi health` 初始化 CRSI 系统。' }
755
+ }
756
+
757
+ const result = metaEngine.analyze()
758
+ const lines: string[] = ['## 🔮 CRSI 元规则分析 (RSI Level 3)', '']
759
+
760
+ // ── System Health ──
761
+ lines.push('### 📊 系统健康评分', '')
762
+ const h = result.systemHealth
763
+ lines.push(`| 组件 | 得分 |`)
764
+ lines.push(`|------|------|`)
765
+ lines.push(`| 错误签名 | ${h.components.errorSignatures}/100 |`)
766
+ lines.push(`| 预防拦截 | ${h.components.preflightPrevention}/100 |`)
767
+ lines.push(`| 自动修复 | ${h.components.autoCorrection}/100 |`)
768
+ lines.push(`| 免疫记忆 | ${h.components.immuneMemory}/100 |`)
769
+ lines.push(`| 规则有效性 | ${h.components.ruleEffectiveness}/100 |`)
770
+ lines.push(`| **综合** | **${h.score}/100** |`)
771
+ lines.push('')
772
+ lines.push(h.assessment)
773
+ lines.push('')
774
+
775
+ // ── Recommendations ──
776
+ lines.push('### 💡 优化建议', '')
777
+ for (const rec of h.recommendations) {
778
+ lines.push(`- ${rec}`)
779
+ }
780
+ lines.push('')
781
+
782
+ // ── Meta-Rules ──
783
+ if (result.metaRules.length > 0) {
784
+ lines.push(`### 🧬 发现 ${result.metaRules.length} 条元规则`, '')
785
+
786
+ for (const mr of result.metaRules) {
787
+ const confIcon = mr.confidence === 'high' ? '🔴' : mr.confidence === 'medium' ? '🟡' : '🟢'
788
+ const autoLabel = mr.autoApplicable ? ' [可自动应用]' : ''
789
+ lines.push(`#### ${confIcon} ${mr.title}${autoLabel}`)
790
+ lines.push('')
791
+ lines.push(mr.description)
792
+ lines.push('')
793
+ lines.push(`> **建议**: ${mr.recommendation}`)
794
+ lines.push('')
795
+ lines.push(
796
+ `置信度: ${mr.confidence} | 样本量: ${mr.evidence.sampleSize} | 生成时间: ${mr.generatedAt}`,
797
+ )
798
+ lines.push('')
799
+ }
800
+ } else {
801
+ lines.push('### 🧬 元规则', '')
802
+ lines.push(
803
+ '暂无元规则生成。当系统积累足够的错误签名和规则数据后,元规则引擎将自动发现跨规则模式。',
804
+ )
805
+ lines.push('')
806
+ }
807
+
808
+ // ── Auto-applicable summary ──
809
+ const autoApplicable = metaEngine.getAutoApplicable(result.metaRules)
810
+ if (autoApplicable.length > 0) {
811
+ lines.push('### ⚡ 可自动应用', '')
812
+ lines.push(`${autoApplicable.length} 条元规则可安全自动应用:`)
813
+ for (const mr of autoApplicable) {
814
+ lines.push(`- \`${mr.id}\`: ${mr.recommendation}`)
815
+ }
816
+ lines.push('')
817
+ lines.push('使用 `/crsi meta --apply` 自动应用高置信度元规则。')
818
+ }
819
+
820
+ return { content: lines.join('\n') }
821
+ }
822
+
823
+ // ═══════════════════════════════════════════════════════════════
824
+ // SIS (Self-Immune System)
825
+ // ═══════════════════════════════════════════════════════════════
826
+
827
+ const sisErrorsCmd: CommandHandler = (ctx) => {
828
+ const db = ctx.engine.getErrorSignatureDB?.()
829
+ if (!db) {
830
+ return { content: 'SIS 自免疫系统未初始化。' }
831
+ }
832
+ const sigs = db.getActive()
833
+ if (sigs.length === 0) {
834
+ return { content: '🛡️ SIS 免疫记忆为空 — 尚未记录任何错误签名。' }
835
+ }
836
+ const lines: string[] = ['## 🛡️ SIS 免疫记忆', '']
837
+ for (const sig of sigs) {
838
+ const statusIcon = sig.status === 'active' ? '🟢' : '🟡'
839
+ lines.push(`- ${statusIcon} \`${sig.id}\` [${sig.category}] ${sig.toolName}`)
840
+ lines.push(` 模式: \`${sig.pattern.slice(0, 80)}${sig.pattern.length > 80 ? '...' : ''}\``)
841
+ lines.push(
842
+ ` 修复: ${sig.fixStrategy} → ${sig.fixAction.slice(0, 60)} | 发生 ${sig.occurrences} 次 | 成功率 ${Math.round(sig.successRate * 100)}%`,
843
+ )
844
+ lines.push('')
845
+ }
846
+ lines.push(`共 ${sigs.length} 条活跃免疫记忆`)
847
+ lines.push('', '使用 `/sis stats` 查看汇总统计,`/sis clear <id>` 清除指定签名')
848
+ return { content: lines.join('\n') }
849
+ }
850
+
851
+ const sisStatsCmd: CommandHandler = (ctx) => {
852
+ const db = ctx.engine.getErrorSignatureDB?.()
853
+ if (!db) {
854
+ return { content: 'SIS 自免疫系统未初始化。' }
855
+ }
856
+ const stats = db.getStats()
857
+ const lines: string[] = ['## 🛡️ SIS 自免疫统计', '']
858
+ lines.push(`总签名数: ${stats.total}`)
859
+ lines.push(
860
+ `🟢 活跃: ${stats.active} | 🟡 降级: ${stats.degraded} | ⚫ 已退役: ${stats.retired}`,
861
+ )
862
+ lines.push(`平均成功率: ${Math.round(stats.avgSuccessRate * 100)}%`)
863
+ lines.push(`总拦截次数: ${stats.totalInterceptions}`)
864
+ return { content: lines.join('\n') }
865
+ }
866
+
867
+ const sisClearCmd: CommandHandler = (ctx, args) => {
868
+ const db = ctx.engine.getErrorSignatureDB?.()
869
+ if (!db) {
870
+ return { content: 'SIS 自免疫系统未初始化。' }
871
+ }
872
+ const sigId = args[0]?.trim()
873
+ if (!sigId) {
874
+ return { content: 'Usage: /sis clear <signature-id>\n\n使用 `/sis errors` 查看所有签名 ID。' }
875
+ }
876
+ const sig = db.get(sigId)
877
+ if (!sig) {
878
+ return { content: `签名 \`${sigId}\` 未找到。` }
879
+ }
880
+ db.retire(sigId)
881
+ return { content: `已退役签名 \`${sigId}\` (${sig.pattern.slice(0, 50)}...)` }
882
+ }
883
+
884
+ const sisCleanupCmd: CommandHandler = async (ctx) => {
885
+ const db = ctx.engine.getErrorSignatureDB?.()
886
+ if (!db) {
887
+ return { content: 'SIS 自免疫系统未初始化。' }
888
+ }
889
+ // Use dynamic import for ESM compatibility
890
+ const { ImmuneMemoryGC } = await import('../../src/core/immune-memory-gc.js')
891
+ const gc = new ImmuneMemoryGC(db)
892
+ const report = gc.collect()
893
+ const lines: string[] = ['## 🧹 SIS 免疫记忆清理完成', '']
894
+ lines.push(`清理前: ${report.before} 条签名`)
895
+ lines.push(`清理后: ${report.after} 条签名`)
896
+ lines.push('')
897
+ if (report.retiredRemoved > 0) lines.push(`🗑️ 移除过期退役: ${report.retiredRemoved} 条`)
898
+ if (report.zeroSuccessRetired > 0) lines.push(`⚠️ 退役零成功率: ${report.zeroSuccessRetired} 条`)
899
+ if (report.duplicatesMerged > 0) lines.push(`🔗 合并重复签名: ${report.duplicatesMerged} 条`)
900
+ if (
901
+ report.retiredRemoved === 0 &&
902
+ report.zeroSuccessRetired === 0 &&
903
+ report.duplicatesMerged === 0
904
+ ) {
905
+ lines.push('✅ 免疫记忆干净,无需清理')
906
+ }
907
+ return { content: lines.join('\n') }
908
+ }
909
+
659
910
  // ═══════════════════════════════════════════════════════════════
660
911
  // Workflow
661
912
  // ═══════════════════════════════════════════════════════════════
@@ -3288,6 +3539,11 @@ const commandsListCmd: CommandHandler = () => {
3288
3539
  '/crsi analyze': 'Tools & Skills',
3289
3540
  '/crsi restore': 'Tools & Skills',
3290
3541
  '/crsi stats': 'Tools & Skills',
3542
+ '/crsi health': 'Tools & Skills',
3543
+ '/crsi meta': 'Tools & Skills',
3544
+ '/sis errors': 'Tools & Skills',
3545
+ '/sis stats': 'Tools & Skills',
3546
+ '/sis clear': 'Tools & Skills',
3291
3547
  '/plan': 'Workflow',
3292
3548
  '/no-plan': 'Workflow',
3293
3549
  '/tdd': 'Workflow',
@@ -3432,6 +3688,12 @@ registry.set('/crsi disable', crsiDisableCmd)
3432
3688
  registry.set('/crsi analyze', crsiAnalyzeCmd)
3433
3689
  registry.set('/crsi restore', crsiRestoreCmd)
3434
3690
  registry.set('/crsi stats', crsiStatsCmd)
3691
+ registry.set('/crsi health', crsiHealthCmd)
3692
+ registry.set('/crsi meta', crsiMetaCmd)
3693
+ registry.set('/sis errors', sisErrorsCmd)
3694
+ registry.set('/sis stats', sisStatsCmd)
3695
+ registry.set('/sis clear', sisClearCmd)
3696
+ registry.set('/sis cleanup', sisCleanupCmd)
3435
3697
 
3436
3698
  // Workflow
3437
3699
  registry.set('/plan', planCmd)
@@ -3588,6 +3850,12 @@ const COMMAND_DESCRIPTIONS: Record<string, string> = {
3588
3850
  '/crsi analyze': 'Manually trigger CRSI pattern analysis across all agents',
3589
3851
  '/crsi restore': 'Restore a disabled or degraded CRSI rule',
3590
3852
  '/crsi stats': 'Show CRSI overall effectiveness statistics',
3853
+ '/crsi health': 'CRSI + SIS unified health dashboard with scoring',
3854
+ '/crsi meta': 'RSI Level 3 meta-rule analysis — rules that improve the rules',
3855
+ '/sis errors': 'List all active SIS immune memory signatures',
3856
+ '/sis stats': 'Show SIS self-immune system aggregate statistics',
3857
+ '/sis clear': 'Retire an immune memory signature by ID',
3858
+ '/sis cleanup': 'Run immune memory garbage collection (dedup + cleanup)',
3591
3859
  '/plan': 'Enter plan mode',
3592
3860
  '/no-plan': 'Exit plan mode',
3593
3861
  '/tdd': 'Test-Driven Development workflow (RED → GREEN → REFACTOR)',