hivemind-context-governance 1.3.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 (139) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/LICENSE +21 -0
  3. package/README.md +218 -0
  4. package/dist/cli/init.d.ts +23 -0
  5. package/dist/cli/init.d.ts.map +1 -0
  6. package/dist/cli/init.js +175 -0
  7. package/dist/cli/init.js.map +1 -0
  8. package/dist/cli.d.ts +14 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +162 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/dashboard/i18n/en.d.ts +43 -0
  13. package/dist/dashboard/i18n/en.d.ts.map +1 -0
  14. package/dist/dashboard/i18n/en.js +43 -0
  15. package/dist/dashboard/i18n/en.js.map +1 -0
  16. package/dist/dashboard/i18n/index.d.ts +10 -0
  17. package/dist/dashboard/i18n/index.d.ts.map +1 -0
  18. package/dist/dashboard/i18n/index.js +14 -0
  19. package/dist/dashboard/i18n/index.js.map +1 -0
  20. package/dist/dashboard/i18n/vi.d.ts +43 -0
  21. package/dist/dashboard/i18n/vi.d.ts.map +1 -0
  22. package/dist/dashboard/i18n/vi.js +43 -0
  23. package/dist/dashboard/i18n/vi.js.map +1 -0
  24. package/dist/dashboard/server.d.ts +23 -0
  25. package/dist/dashboard/server.d.ts.map +1 -0
  26. package/dist/dashboard/server.js +282 -0
  27. package/dist/dashboard/server.js.map +1 -0
  28. package/dist/hooks/compaction.d.ts +21 -0
  29. package/dist/hooks/compaction.d.ts.map +1 -0
  30. package/dist/hooks/compaction.js +79 -0
  31. package/dist/hooks/compaction.js.map +1 -0
  32. package/dist/hooks/index.d.ts +8 -0
  33. package/dist/hooks/index.d.ts.map +1 -0
  34. package/dist/hooks/index.js +7 -0
  35. package/dist/hooks/index.js.map +1 -0
  36. package/dist/hooks/session-lifecycle.d.ts +28 -0
  37. package/dist/hooks/session-lifecycle.d.ts.map +1 -0
  38. package/dist/hooks/session-lifecycle.js +94 -0
  39. package/dist/hooks/session-lifecycle.js.map +1 -0
  40. package/dist/hooks/tool-gate.d.ts +28 -0
  41. package/dist/hooks/tool-gate.d.ts.map +1 -0
  42. package/dist/hooks/tool-gate.js +152 -0
  43. package/dist/hooks/tool-gate.js.map +1 -0
  44. package/dist/index.d.ts +19 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +159 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/lib/complexity.d.ts +41 -0
  49. package/dist/lib/complexity.d.ts.map +1 -0
  50. package/dist/lib/complexity.js +67 -0
  51. package/dist/lib/complexity.js.map +1 -0
  52. package/dist/lib/context-refresh.d.ts +46 -0
  53. package/dist/lib/context-refresh.d.ts.map +1 -0
  54. package/dist/lib/context-refresh.js +77 -0
  55. package/dist/lib/context-refresh.js.map +1 -0
  56. package/dist/lib/index.d.ts +10 -0
  57. package/dist/lib/index.d.ts.map +1 -0
  58. package/dist/lib/index.js +10 -0
  59. package/dist/lib/index.js.map +1 -0
  60. package/dist/lib/logging.d.ts +13 -0
  61. package/dist/lib/logging.d.ts.map +1 -0
  62. package/dist/lib/logging.js +40 -0
  63. package/dist/lib/logging.js.map +1 -0
  64. package/dist/lib/persistence.d.ts +15 -0
  65. package/dist/lib/persistence.d.ts.map +1 -0
  66. package/dist/lib/persistence.js +62 -0
  67. package/dist/lib/persistence.js.map +1 -0
  68. package/dist/lib/planning-fs.d.ts +34 -0
  69. package/dist/lib/planning-fs.d.ts.map +1 -0
  70. package/dist/lib/planning-fs.js +134 -0
  71. package/dist/lib/planning-fs.js.map +1 -0
  72. package/dist/lib/sentiment.d.ts +31 -0
  73. package/dist/lib/sentiment.d.ts.map +1 -0
  74. package/dist/lib/sentiment.js +158 -0
  75. package/dist/lib/sentiment.js.map +1 -0
  76. package/dist/schemas/brain-state.d.ts +60 -0
  77. package/dist/schemas/brain-state.d.ts.map +1 -0
  78. package/dist/schemas/brain-state.js +176 -0
  79. package/dist/schemas/brain-state.js.map +1 -0
  80. package/dist/schemas/config.d.ts +51 -0
  81. package/dist/schemas/config.d.ts.map +1 -0
  82. package/dist/schemas/config.js +128 -0
  83. package/dist/schemas/config.js.map +1 -0
  84. package/dist/schemas/hierarchy.d.ts +22 -0
  85. package/dist/schemas/hierarchy.d.ts.map +1 -0
  86. package/dist/schemas/hierarchy.js +27 -0
  87. package/dist/schemas/hierarchy.js.map +1 -0
  88. package/dist/schemas/index.d.ts +7 -0
  89. package/dist/schemas/index.d.ts.map +1 -0
  90. package/dist/schemas/index.js +7 -0
  91. package/dist/schemas/index.js.map +1 -0
  92. package/dist/tools/compact-session.d.ts +15 -0
  93. package/dist/tools/compact-session.d.ts.map +1 -0
  94. package/dist/tools/compact-session.js +76 -0
  95. package/dist/tools/compact-session.js.map +1 -0
  96. package/dist/tools/declare-intent.d.ts +15 -0
  97. package/dist/tools/declare-intent.d.ts.map +1 -0
  98. package/dist/tools/declare-intent.js +83 -0
  99. package/dist/tools/declare-intent.js.map +1 -0
  100. package/dist/tools/index.d.ts +14 -0
  101. package/dist/tools/index.d.ts.map +1 -0
  102. package/dist/tools/index.js +14 -0
  103. package/dist/tools/index.js.map +1 -0
  104. package/dist/tools/map-context.d.ts +15 -0
  105. package/dist/tools/map-context.d.ts.map +1 -0
  106. package/dist/tools/map-context.js +85 -0
  107. package/dist/tools/map-context.js.map +1 -0
  108. package/dist/tools/self-rate.d.ts +15 -0
  109. package/dist/tools/self-rate.d.ts.map +1 -0
  110. package/dist/tools/self-rate.js +76 -0
  111. package/dist/tools/self-rate.js.map +1 -0
  112. package/package.json +71 -0
  113. package/src/cli/init.ts +214 -0
  114. package/src/cli.ts +178 -0
  115. package/src/dashboard/i18n/en.ts +43 -0
  116. package/src/dashboard/i18n/index.ts +20 -0
  117. package/src/dashboard/i18n/vi.ts +43 -0
  118. package/src/dashboard/server.ts +372 -0
  119. package/src/hooks/compaction.ts +104 -0
  120. package/src/hooks/index.ts +8 -0
  121. package/src/hooks/session-lifecycle.ts +133 -0
  122. package/src/hooks/tool-gate.ts +205 -0
  123. package/src/index.ts +206 -0
  124. package/src/lib/complexity.ts +96 -0
  125. package/src/lib/context-refresh.ts +107 -0
  126. package/src/lib/index.ts +10 -0
  127. package/src/lib/logging.ts +53 -0
  128. package/src/lib/persistence.ts +83 -0
  129. package/src/lib/planning-fs.ts +187 -0
  130. package/src/lib/sentiment.ts +183 -0
  131. package/src/schemas/brain-state.ts +257 -0
  132. package/src/schemas/config.ts +184 -0
  133. package/src/schemas/hierarchy.ts +58 -0
  134. package/src/schemas/index.ts +7 -0
  135. package/src/tools/compact-session.ts +97 -0
  136. package/src/tools/declare-intent.ts +104 -0
  137. package/src/tools/index.ts +14 -0
  138. package/src/tools/map-context.ts +105 -0
  139. package/src/tools/self-rate.ts +86 -0
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Sentiment Detection Module
3
+ *
4
+ * Detects negative signals in agent/user communication to trigger
5
+ * context refresh when drift is detected.
6
+ *
7
+ * Signals:
8
+ * - Negative keywords: stop, wrong, no, bad, incorrect, confused
9
+ * - Agent failure phrases: "I apologize", "you are right", "I was wrong"
10
+ * - Cancellation patterns: "cancel", "abort", "start over"
11
+ */
12
+
13
+ export interface SentimentSignal {
14
+ type: "negative_keyword" | "failure_phrase" | "cancellation" | "confusion"
15
+ matched_text: string
16
+ timestamp: number
17
+ turn_number: number
18
+ source: "user" | "agent"
19
+ }
20
+
21
+ /**
22
+ * Negative keywords that indicate problems.
23
+ *
24
+ * Short keywords (≤5 chars) use word-boundary regex to prevent false positives
25
+ * like "no" matching "no issues" or "error" matching "error handling".
26
+ * Benign phrases are excluded via negative-lookahead.
27
+ */
28
+ const NEGATIVE_KEYWORD_PATTERNS: Array<{ pattern: RegExp; label: string }> = [
29
+ { pattern: /\bstop\b(?!\s+(worrying|there))/i, label: "stop" },
30
+ { pattern: /\bwrong\b/i, label: "wrong" },
31
+ { pattern: /\bno\b(?!\s+(issues?|errors?|problems?|worries|need|thanks|longer|more))/i, label: "no" },
32
+ { pattern: /\bbad\b(?!\s+(→|->|to))/i, label: "bad" },
33
+ { pattern: /\bincorrect\b/i, label: "incorrect" },
34
+ { pattern: /\bconfused\b/i, label: "confused" },
35
+ { pattern: /\bconfusion\b/i, label: "confusion" },
36
+ { pattern: /\bmistake\b/i, label: "mistake" },
37
+ { pattern: /\berror\b(?!\s+(handling|boundary|boundaries|message|code|type|class|object|page|recovery|log))/i, label: "error" },
38
+ { pattern: /\bbroken\b/i, label: "broken" },
39
+ { pattern: /not working/i, label: "not working" },
40
+ { pattern: /doesn't work/i, label: "doesn't work" },
41
+ { pattern: /isn't working/i, label: "isn't working" },
42
+ ]
43
+
44
+ /** Agent failure admission phrases */
45
+ const FAILURE_PHRASES = [
46
+ "i apologize",
47
+ "you are right",
48
+ "i was wrong",
49
+ "my mistake",
50
+ "i misunderstood",
51
+ "i made an error",
52
+ "that was incorrect",
53
+ "i see the issue now",
54
+ "you're correct",
55
+ "i should have",
56
+ ]
57
+
58
+ /** Cancellation/restart patterns */
59
+ const CANCELLATION_PATTERNS = [
60
+ "cancel",
61
+ "abort",
62
+ "start over",
63
+ "begin again",
64
+ "scratch that",
65
+ "forget that",
66
+ "never mind",
67
+ "nevermind",
68
+ "let's restart",
69
+ "do over",
70
+ ]
71
+
72
+ /** Confusion indicators */
73
+ const CONFUSION_PATTERNS = [
74
+ "i'm confused",
75
+ "i am confused",
76
+ "this is confusing",
77
+ "doesn't make sense",
78
+ "not making sense",
79
+ "unclear",
80
+ "i don't understand",
81
+ "i do not understand",
82
+ "what do you mean",
83
+ "can you explain",
84
+ ]
85
+
86
+ /**
87
+ * Detect sentiment signals in text
88
+ */
89
+ export function detectSentiment(
90
+ text: string,
91
+ turnNumber: number,
92
+ source: "user" | "agent" = "user"
93
+ ): SentimentSignal[] {
94
+ const signals: SentimentSignal[] = []
95
+ const lowerText = text.toLowerCase()
96
+ const timestamp = Date.now()
97
+
98
+ // Check negative keywords (regex-based with word boundaries)
99
+ for (const { pattern, label } of NEGATIVE_KEYWORD_PATTERNS) {
100
+ if (pattern.test(lowerText)) {
101
+ signals.push({
102
+ type: "negative_keyword",
103
+ matched_text: label,
104
+ timestamp,
105
+ turn_number: turnNumber,
106
+ source,
107
+ })
108
+ }
109
+ }
110
+
111
+ // Check failure phrases
112
+ for (const phrase of FAILURE_PHRASES) {
113
+ if (lowerText.includes(phrase)) {
114
+ signals.push({
115
+ type: "failure_phrase",
116
+ matched_text: phrase,
117
+ timestamp,
118
+ turn_number: turnNumber,
119
+ source,
120
+ })
121
+ }
122
+ }
123
+
124
+ // Check cancellation patterns
125
+ for (const pattern of CANCELLATION_PATTERNS) {
126
+ if (lowerText.includes(pattern)) {
127
+ signals.push({
128
+ type: "cancellation",
129
+ matched_text: pattern,
130
+ timestamp,
131
+ turn_number: turnNumber,
132
+ source,
133
+ })
134
+ }
135
+ }
136
+
137
+ // Check confusion patterns
138
+ for (const pattern of CONFUSION_PATTERNS) {
139
+ if (lowerText.includes(pattern)) {
140
+ signals.push({
141
+ type: "confusion",
142
+ matched_text: pattern,
143
+ timestamp,
144
+ turn_number: turnNumber,
145
+ source,
146
+ })
147
+ }
148
+ }
149
+
150
+ return signals
151
+ }
152
+
153
+ /**
154
+ * Check if text contains any negative sentiment
155
+ */
156
+ export function hasNegativeSentiment(text: string): boolean {
157
+ return detectSentiment(text, 0).length > 0
158
+ }
159
+
160
+ /**
161
+ * Get sentiment summary for display
162
+ */
163
+ export function getSentimentSummary(signals: SentimentSignal[]): string {
164
+ if (signals.length === 0) {
165
+ return "No negative signals detected"
166
+ }
167
+
168
+ const byType = signals.reduce(
169
+ (acc, signal) => {
170
+ acc[signal.type] = (acc[signal.type] || 0) + 1
171
+ return acc
172
+ },
173
+ {} as Record<string, number>
174
+ )
175
+
176
+ const parts: string[] = []
177
+ if (byType["negative_keyword"]) parts.push(`${byType["negative_keyword"]} negative keywords`)
178
+ if (byType["failure_phrase"]) parts.push(`${byType["failure_phrase"]} failure admissions`)
179
+ if (byType["cancellation"]) parts.push(`${byType["cancellation"]} cancellations`)
180
+ if (byType["confusion"]) parts.push(`${byType["confusion"]} confusion indicators`)
181
+
182
+ return parts.join(", ")
183
+ }
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Brain State Schema
3
+ * Core state machine for session governance
4
+ */
5
+
6
+ import type { HiveMindConfig, GovernanceMode } from "./config.js";
7
+ import type { HierarchyState } from "./hierarchy.js";
8
+ import type { SentimentSignal } from "../lib/sentiment.js";
9
+
10
+ export type SessionMode = "plan_driven" | "quick_fix" | "exploration";
11
+ export type GovernanceStatus = "LOCKED" | "OPEN";
12
+
13
+ export interface SessionState {
14
+ id: string;
15
+ mode: SessionMode;
16
+ governance_mode: GovernanceMode;
17
+ governance_status: GovernanceStatus;
18
+ start_time: number;
19
+ last_activity: number;
20
+ }
21
+
22
+ export interface SelfRating {
23
+ score: number; // 1-10
24
+ reason?: string;
25
+ turn_context?: string;
26
+ timestamp: number;
27
+ turn_number: number;
28
+ }
29
+
30
+ export interface MetricsState {
31
+ turn_count: number;
32
+ drift_score: number;
33
+ files_touched: string[];
34
+ context_updates: number;
35
+ ratings: SelfRating[];
36
+ auto_health_score: number; // 0-100, calculated from success rate
37
+ total_tool_calls: number;
38
+ successful_tool_calls: number;
39
+ }
40
+
41
+ export interface BrainState {
42
+ session: SessionState;
43
+ hierarchy: HierarchyState;
44
+ metrics: MetricsState;
45
+ sentiment_signals: SentimentSignal[];
46
+ complexity_nudge_shown: boolean;
47
+ version: string;
48
+ }
49
+
50
+ export const BRAIN_STATE_VERSION = "1.0.0";
51
+
52
+ export function generateSessionId(): string {
53
+ const timestamp = Date.now();
54
+ const random = Math.random().toString(36).substring(2, 8);
55
+ return `session-${timestamp}-${random}`;
56
+ }
57
+
58
+ export function createBrainState(
59
+ sessionId: string,
60
+ config: HiveMindConfig,
61
+ mode: SessionMode = "plan_driven"
62
+ ): BrainState {
63
+ const now = Date.now();
64
+
65
+ return {
66
+ session: {
67
+ id: sessionId,
68
+ mode,
69
+ governance_mode: config.governance_mode,
70
+ governance_status: config.governance_mode === "strict" ? "LOCKED" : "OPEN",
71
+ start_time: now,
72
+ last_activity: now,
73
+ },
74
+ hierarchy: {
75
+ trajectory: "",
76
+ tactic: "",
77
+ action: "",
78
+ },
79
+ metrics: {
80
+ turn_count: 0,
81
+ drift_score: 100,
82
+ files_touched: [],
83
+ context_updates: 0,
84
+ ratings: [],
85
+ auto_health_score: 100,
86
+ total_tool_calls: 0,
87
+ successful_tool_calls: 0,
88
+ },
89
+ sentiment_signals: [],
90
+ complexity_nudge_shown: false,
91
+ version: BRAIN_STATE_VERSION,
92
+ };
93
+ }
94
+
95
+ export function isSessionLocked(state: BrainState): boolean {
96
+ return state.session.governance_status === "LOCKED";
97
+ }
98
+
99
+ export function unlockSession(state: BrainState): BrainState {
100
+ return {
101
+ ...state,
102
+ session: {
103
+ ...state.session,
104
+ governance_status: "OPEN",
105
+ last_activity: Date.now(),
106
+ },
107
+ };
108
+ }
109
+
110
+ export function lockSession(state: BrainState): BrainState {
111
+ return {
112
+ ...state,
113
+ session: {
114
+ ...state.session,
115
+ governance_status: "LOCKED",
116
+ last_activity: Date.now(),
117
+ },
118
+ };
119
+ }
120
+
121
+ export function incrementTurnCount(state: BrainState): BrainState {
122
+ return {
123
+ ...state,
124
+ metrics: {
125
+ ...state.metrics,
126
+ turn_count: state.metrics.turn_count + 1,
127
+ },
128
+ session: {
129
+ ...state.session,
130
+ last_activity: Date.now(),
131
+ },
132
+ };
133
+ }
134
+
135
+ export function resetTurnCount(state: BrainState): BrainState {
136
+ return {
137
+ ...state,
138
+ metrics: {
139
+ ...state.metrics,
140
+ turn_count: 0,
141
+ drift_score: Math.min(100, state.metrics.drift_score + 10),
142
+ },
143
+ session: {
144
+ ...state.session,
145
+ last_activity: Date.now(),
146
+ },
147
+ };
148
+ }
149
+
150
+ export function updateHierarchy(
151
+ state: BrainState,
152
+ hierarchy: Partial<HierarchyState>
153
+ ): BrainState {
154
+ return {
155
+ ...state,
156
+ hierarchy: { ...state.hierarchy, ...hierarchy },
157
+ metrics: {
158
+ ...state.metrics,
159
+ context_updates: state.metrics.context_updates + 1,
160
+ },
161
+ session: {
162
+ ...state.session,
163
+ last_activity: Date.now(),
164
+ },
165
+ };
166
+ }
167
+
168
+ export function addFileTouched(state: BrainState, filePath: string): BrainState {
169
+ if (state.metrics.files_touched.includes(filePath)) {
170
+ return state;
171
+ }
172
+ return {
173
+ ...state,
174
+ metrics: {
175
+ ...state.metrics,
176
+ files_touched: [...state.metrics.files_touched, filePath],
177
+ },
178
+ };
179
+ }
180
+
181
+ export function calculateDriftScore(state: BrainState): number {
182
+ const turnsPenalty = Math.min(50, state.metrics.turn_count * 5);
183
+ const updatesBonus = Math.min(20, state.metrics.context_updates * 2);
184
+ return Math.max(0, Math.min(100, 100 - turnsPenalty + updatesBonus));
185
+ }
186
+
187
+ export function shouldTriggerDriftWarning(
188
+ state: BrainState,
189
+ maxTurns: number
190
+ ): boolean {
191
+ return state.metrics.turn_count >= maxTurns && state.metrics.drift_score < 50;
192
+ }
193
+
194
+ export function addSelfRating(
195
+ state: BrainState,
196
+ rating: Omit<SelfRating, "timestamp" | "turn_number">
197
+ ): BrainState {
198
+ const newRating: SelfRating = {
199
+ ...rating,
200
+ timestamp: Date.now(),
201
+ turn_number: state.metrics.turn_count,
202
+ };
203
+ return {
204
+ ...state,
205
+ metrics: {
206
+ ...state.metrics,
207
+ ratings: [...state.metrics.ratings, newRating],
208
+ },
209
+ };
210
+ }
211
+
212
+ export function trackToolCall(
213
+ state: BrainState,
214
+ success: boolean
215
+ ): BrainState {
216
+ const total = state.metrics.total_tool_calls + 1;
217
+ const successful = success
218
+ ? state.metrics.successful_tool_calls + 1
219
+ : state.metrics.successful_tool_calls;
220
+ const healthScore = total > 0 ? Math.round((successful / total) * 100) : 100;
221
+
222
+ return {
223
+ ...state,
224
+ metrics: {
225
+ ...state.metrics,
226
+ total_tool_calls: total,
227
+ successful_tool_calls: successful,
228
+ auto_health_score: healthScore,
229
+ },
230
+ };
231
+ }
232
+
233
+ export function addSentimentSignals(
234
+ state: BrainState,
235
+ signals: SentimentSignal[]
236
+ ): BrainState {
237
+ if (signals.length === 0) return state;
238
+
239
+ return {
240
+ ...state,
241
+ sentiment_signals: [...state.sentiment_signals, ...signals],
242
+ };
243
+ }
244
+
245
+ export function setComplexityNudgeShown(state: BrainState): BrainState {
246
+ return {
247
+ ...state,
248
+ complexity_nudge_shown: true,
249
+ };
250
+ }
251
+
252
+ export function resetComplexityNudge(state: BrainState): BrainState {
253
+ return {
254
+ ...state,
255
+ complexity_nudge_shown: false,
256
+ };
257
+ }
@@ -0,0 +1,184 @@
1
+ /**
2
+ * HiveMind Configuration Schema
3
+ * Defines governance modes, project settings, and agent behavior constraints
4
+ */
5
+
6
+ export type GovernanceMode = "permissive" | "assisted" | "strict";
7
+ export type Language = "en" | "vi";
8
+ export type ExpertLevel = "beginner" | "intermediate" | "advanced" | "expert";
9
+ export type OutputStyle =
10
+ | "explanatory" // Detailed explanations, teaching mode
11
+ | "outline" // Bullet points, structured summaries
12
+ | "skeptical" // Critical review, challenge assumptions
13
+ | "architecture" // Focus on design patterns, structure first
14
+ | "minimal"; // Brief, code-only responses
15
+
16
+ export interface AgentBehaviorConfig {
17
+ /** Language for all responses */
18
+ language: Language;
19
+ /** Expertise level - affects depth and assumptions */
20
+ expert_level: ExpertLevel;
21
+ /** Output style - affects response format */
22
+ output_style: OutputStyle;
23
+ /** Additional behavioral constraints */
24
+ constraints: {
25
+ /** Require code review before accepting */
26
+ require_code_review: boolean;
27
+ /** Enforce test-driven development */
28
+ enforce_tdd: boolean;
29
+ /** Maximum response length in tokens (approximate) */
30
+ max_response_tokens: number;
31
+ /** Always explain 'why' not just 'what' */
32
+ explain_reasoning: boolean;
33
+ /** Challenge user assumptions */
34
+ be_skeptical: boolean;
35
+ };
36
+ }
37
+
38
+ export interface HiveMindConfig {
39
+ governance_mode: GovernanceMode;
40
+ language: Language;
41
+ max_turns_before_warning: number;
42
+ max_active_md_lines: number;
43
+ auto_compact_on_turns: number;
44
+ /** Agent behavior configuration - injected into every session */
45
+ agent_behavior: AgentBehaviorConfig;
46
+ }
47
+
48
+ export const DEFAULT_AGENT_BEHAVIOR: AgentBehaviorConfig = {
49
+ language: "en",
50
+ expert_level: "intermediate",
51
+ output_style: "explanatory",
52
+ constraints: {
53
+ require_code_review: false,
54
+ enforce_tdd: false,
55
+ max_response_tokens: 2000,
56
+ explain_reasoning: true,
57
+ be_skeptical: false,
58
+ },
59
+ };
60
+
61
+ export const DEFAULT_CONFIG: HiveMindConfig = {
62
+ governance_mode: "assisted",
63
+ language: "en",
64
+ max_turns_before_warning: 5,
65
+ max_active_md_lines: 50,
66
+ auto_compact_on_turns: 20,
67
+ agent_behavior: DEFAULT_AGENT_BEHAVIOR,
68
+ };
69
+
70
+ export function createConfig(overrides: Partial<HiveMindConfig> = {}): HiveMindConfig {
71
+ return {
72
+ ...DEFAULT_CONFIG,
73
+ ...overrides,
74
+ agent_behavior: {
75
+ ...DEFAULT_AGENT_BEHAVIOR,
76
+ ...overrides.agent_behavior,
77
+ },
78
+ };
79
+ }
80
+
81
+ export function isValidGovernanceMode(mode: string): mode is GovernanceMode {
82
+ return ["permissive", "assisted", "strict"].includes(mode);
83
+ }
84
+
85
+ export function isValidLanguage(lang: string): lang is Language {
86
+ return ["en", "vi"].includes(lang);
87
+ }
88
+
89
+ export function isValidExpertLevel(level: string): level is ExpertLevel {
90
+ return ["beginner", "intermediate", "advanced", "expert"].includes(level);
91
+ }
92
+
93
+ export function isValidOutputStyle(style: string): style is OutputStyle {
94
+ return ["explanatory", "outline", "skeptical", "architecture", "minimal"].includes(style);
95
+ }
96
+
97
+ /**
98
+ * Generates the mandatory agent configuration prompt that is injected
99
+ * at every session opening and persists throughout the conversation.
100
+ */
101
+ export function generateAgentBehaviorPrompt(config: AgentBehaviorConfig): string {
102
+ const lines: string[] = [];
103
+
104
+ lines.push("<agent-configuration>");
105
+ lines.push("MANDATORY: You MUST obey these constraints for this entire session:");
106
+ lines.push("");
107
+
108
+ // Language enforcement
109
+ const langNames: Record<Language, string> = {
110
+ en: "English",
111
+ vi: "Vietnamese (Tiếng Việt)",
112
+ };
113
+ lines.push(`[LANGUAGE] Respond ONLY in ${langNames[config.language]}. No exceptions.`);
114
+ lines.push("");
115
+
116
+ // Expert level
117
+ const expertDescriptions: Record<ExpertLevel, string> = {
118
+ beginner: "Explain everything simply. Define terms. No assumptions of prior knowledge.",
119
+ intermediate: "Standard technical depth. Some domain knowledge assumed.",
120
+ advanced: "Concise, sophisticated. Assume strong domain expertise.",
121
+ expert: "Terse, reference advanced concepts. Minimal hand-holding.",
122
+ };
123
+ lines.push(`[EXPERT LEVEL] ${config.expert_level.toUpperCase()}: ${expertDescriptions[config.expert_level]}`);
124
+ lines.push("");
125
+
126
+ // Output style
127
+ const styleInstructions: Record<OutputStyle, string[]> = {
128
+ explanatory: [
129
+ "- Explain WHY, not just WHAT",
130
+ "- Provide context and rationale",
131
+ "- Use analogies where helpful",
132
+ "- Answer follow-up questions proactively",
133
+ ],
134
+ outline: [
135
+ "- Use bullet points and structured lists",
136
+ "- Headings for organization",
137
+ "- Summary at the top",
138
+ "- Details collapsed or abbreviated",
139
+ ],
140
+ skeptical: [
141
+ "- Challenge assumptions in the request",
142
+ "- Point out risks and edge cases",
143
+ "- Ask clarifying questions",
144
+ "- Suggest alternatives",
145
+ "- Verify requirements are complete",
146
+ ],
147
+ architecture: [
148
+ "- Start with high-level design",
149
+ "- Discuss patterns and trade-offs",
150
+ "- Component diagrams before code",
151
+ "- Implementation follows design",
152
+ ],
153
+ minimal: [
154
+ "- Code only, minimal prose",
155
+ "- No explanations unless asked",
156
+ "- Direct answers",
157
+ ],
158
+ };
159
+ lines.push(`[OUTPUT STYLE] ${config.output_style.toUpperCase()}:`);
160
+ styleInstructions[config.output_style].forEach(instruction => lines.push(instruction));
161
+ lines.push("");
162
+
163
+ // Constraints
164
+ lines.push("[CONSTRAINTS]");
165
+ if (config.constraints.require_code_review) {
166
+ lines.push("- MUST review code before accepting: check for bugs, smells, tests");
167
+ }
168
+ if (config.constraints.enforce_tdd) {
169
+ lines.push("- TDD REQUIRED: Write failing test first, then implementation");
170
+ }
171
+ if (config.constraints.explain_reasoning) {
172
+ lines.push("- ALWAYS explain your reasoning");
173
+ }
174
+ if (config.constraints.be_skeptical) {
175
+ lines.push("- BE SKEPTICAL: Question requirements, point out gaps");
176
+ }
177
+ lines.push(`- Maximum response: ~${config.constraints.max_response_tokens} tokens`);
178
+ lines.push("");
179
+
180
+ lines.push("VIOLATION: If you cannot obey these constraints, state why explicitly.");
181
+ lines.push("</agent-configuration>");
182
+
183
+ return lines.join("\n");
184
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Hierarchy Schema
3
+ * 3-level context hierarchy: trajectory → tactic → action
4
+ */
5
+
6
+ export type HierarchyLevel = "trajectory" | "tactic" | "action";
7
+ export type ContextStatus = "pending" | "active" | "complete" | "blocked";
8
+
9
+ export interface ContextMap {
10
+ level: HierarchyLevel;
11
+ content: string;
12
+ status: ContextStatus;
13
+ timestamp: number;
14
+ }
15
+
16
+ export interface HierarchyState {
17
+ trajectory: string;
18
+ tactic: string;
19
+ action: string;
20
+ }
21
+
22
+ export function createHierarchyState(
23
+ trajectory = "",
24
+ tactic = "",
25
+ action = ""
26
+ ): HierarchyState {
27
+ return { trajectory, tactic, action };
28
+ }
29
+
30
+ export function updateHierarchyLevel(
31
+ state: HierarchyState,
32
+ level: HierarchyLevel,
33
+ content: string
34
+ ): HierarchyState {
35
+ return { ...state, [level]: content };
36
+ }
37
+
38
+ export function validateHierarchyTransition(
39
+ current: HierarchyLevel | "complete",
40
+ next: HierarchyLevel
41
+ ): boolean {
42
+ const levels: HierarchyLevel[] = ["trajectory", "tactic", "action"];
43
+ const currentIndex = levels.indexOf(current as HierarchyLevel);
44
+ const nextIndex = levels.indexOf(next);
45
+
46
+ // Allow same level or moving down (more specific)
47
+ // Allow moving up only if current is complete
48
+ return nextIndex >= currentIndex || current === "complete";
49
+ }
50
+
51
+ export function getLevelDepth(level: HierarchyLevel): number {
52
+ const depths: Record<HierarchyLevel, number> = {
53
+ trajectory: 1,
54
+ tactic: 2,
55
+ action: 3,
56
+ };
57
+ return depths[level];
58
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Schema barrel exports
3
+ */
4
+
5
+ export * from "./config.js";
6
+ export * from "./hierarchy.js";
7
+ export * from "./brain-state.js";