auroq-os 1.0.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 (90) hide show
  1. package/.auroq-core/constitution.md +153 -0
  2. package/.auroq-core/core/synapse/context/context-builder.js +34 -0
  3. package/.auroq-core/core/synapse/context/context-tracker.js +198 -0
  4. package/.auroq-core/core/synapse/diagnostics/collectors/consistency-collector.js +168 -0
  5. package/.auroq-core/core/synapse/diagnostics/collectors/hook-collector.js +129 -0
  6. package/.auroq-core/core/synapse/diagnostics/collectors/manifest-collector.js +82 -0
  7. package/.auroq-core/core/synapse/diagnostics/collectors/output-analyzer.js +134 -0
  8. package/.auroq-core/core/synapse/diagnostics/collectors/pipeline-collector.js +75 -0
  9. package/.auroq-core/core/synapse/diagnostics/collectors/quality-collector.js +252 -0
  10. package/.auroq-core/core/synapse/diagnostics/collectors/relevance-matrix.js +174 -0
  11. package/.auroq-core/core/synapse/diagnostics/collectors/safe-read-json.js +31 -0
  12. package/.auroq-core/core/synapse/diagnostics/collectors/session-collector.js +102 -0
  13. package/.auroq-core/core/synapse/diagnostics/collectors/timing-collector.js +126 -0
  14. package/.auroq-core/core/synapse/diagnostics/collectors/uap-collector.js +83 -0
  15. package/.auroq-core/core/synapse/diagnostics/report-formatter.js +484 -0
  16. package/.auroq-core/core/synapse/diagnostics/synapse-diagnostics.js +95 -0
  17. package/.auroq-core/core/synapse/domain/domain-loader.js +322 -0
  18. package/.auroq-core/core/synapse/engine.js +400 -0
  19. package/.auroq-core/core/synapse/layers/l0-constitution.js +80 -0
  20. package/.auroq-core/core/synapse/layers/l1-global.js +102 -0
  21. package/.auroq-core/core/synapse/layers/l2-agent.js +94 -0
  22. package/.auroq-core/core/synapse/layers/l3-workflow.js +94 -0
  23. package/.auroq-core/core/synapse/layers/l4-task.js +83 -0
  24. package/.auroq-core/core/synapse/layers/l5-squad.js +244 -0
  25. package/.auroq-core/core/synapse/layers/l6-keyword.js +154 -0
  26. package/.auroq-core/core/synapse/layers/l7-star-command.js +169 -0
  27. package/.auroq-core/core/synapse/layers/layer-processor.js +82 -0
  28. package/.auroq-core/core/synapse/memory/memory-bridge.js +220 -0
  29. package/.auroq-core/core/synapse/memory/synapse-memory-provider.js +201 -0
  30. package/.auroq-core/core/synapse/output/formatter.js +561 -0
  31. package/.auroq-core/core/synapse/runtime/hook-runtime.js +98 -0
  32. package/.auroq-core/core/synapse/scripts/generate-constitution.js +204 -0
  33. package/.auroq-core/core/synapse/session/session-manager.js +404 -0
  34. package/.auroq-core/core/synapse/utils/atomic-write.js +79 -0
  35. package/.auroq-core/core/synapse/utils/paths.js +57 -0
  36. package/.auroq-core/core/synapse/utils/tokens.js +25 -0
  37. package/.auroq-core/core-config.yaml +80 -0
  38. package/.auroq-core/development/sistema-gestao-projetos.md +193 -0
  39. package/.auroq-core/development/sistema-memoria.md +157 -0
  40. package/.auroq-core/dna-operacional.md +134 -0
  41. package/.claude/CLAUDE.md +399 -0
  42. package/.claude/commands/AuroqOS/agents/forge.md +374 -0
  43. package/.claude/commands/AuroqOS/agents/ops.md +277 -0
  44. package/.claude/commands/companion.md +7 -0
  45. package/.claude/hooks/precompact-session-digest.cjs +46 -0
  46. package/.claude/hooks/synapse-engine.cjs +99 -0
  47. package/.claude/rules/agent-authority.md +79 -0
  48. package/.claude/rules/agent-handoff.md +97 -0
  49. package/.claude/rules/commit-inteligente.md +86 -0
  50. package/.claude/rules/dna-operacional.md +53 -0
  51. package/.claude/rules/evolucao-incremental.md +43 -0
  52. package/.claude/rules/mcp-usage.md +38 -0
  53. package/.claude/rules/memoria-inteligente.md +65 -0
  54. package/.claude/rules/project-tracker.md +49 -0
  55. package/.claude/rules/tool-response-filtering.md +57 -0
  56. package/.claude/settings.json +1 -0
  57. package/.claude/settings.local.json +33 -0
  58. package/.env.example +22 -0
  59. package/.gitignore +23 -0
  60. package/.synapse/constitution +21 -0
  61. package/.synapse/context +8 -0
  62. package/.synapse/global +10 -0
  63. package/.synapse/manifest +35 -0
  64. package/README.md +67 -0
  65. package/agents/companion/agents/companion.md +306 -0
  66. package/agents/companion/data/contexto-dinamico.md +23 -0
  67. package/agents/companion/data/demandas-backlog.md +19 -0
  68. package/agents/companion/data/log-decisoes.md +11 -0
  69. package/agents/companion/data/padroes-observados.md +10 -0
  70. package/agents/companion/knowledge/companion-foundation.md +49 -0
  71. package/agents/companion/knowledge/expert-essencial.md +30 -0
  72. package/agents/companion/knowledge/modus-operandi.md +161 -0
  73. package/agents/companion/tasks/new-project.md +111 -0
  74. package/agents/companion/tasks/save-memory.md +73 -0
  75. package/agents/companion/tasks/start.md +136 -0
  76. package/agents/companion/tasks/weekly-review.md +82 -0
  77. package/bin/auroq-os.js +346 -0
  78. package/business/campanhas/_template/BRIEFING.md +45 -0
  79. package/business/campanhas/_template/CHECKLIST.md +29 -0
  80. package/business/campanhas/_template/DIARIO.md +15 -0
  81. package/business/campanhas/_template/RETROVISOR.md +34 -0
  82. package/business/cockpit.md +72 -0
  83. package/business/templates/tracker-template.md +71 -0
  84. package/docs/knowledge/expert-business/posicionamento.md +27 -0
  85. package/docs/knowledge/expert-business/publico-alvo.md +39 -0
  86. package/docs/knowledge/expert-mind/historia.md +27 -0
  87. package/docs/knowledge/expert-mind/identidade.md +23 -0
  88. package/docs/knowledge/expert-mind/tom-de-voz.md +30 -0
  89. package/docs/knowledge/expert-mind/valores.md +32 -0
  90. package/package.json +26 -0
@@ -0,0 +1,169 @@
1
+ /**
2
+ * L7 Star-Command Layer Processor
3
+ *
4
+ * Detects *command patterns in the user prompt and loads
5
+ * corresponding rules from the .synapse/commands domain file.
6
+ *
7
+ * Command blocks in the domain file are delimited by [*command]
8
+ * headers. Multiple star-commands in a single prompt are supported.
9
+ *
10
+ * @module core/synapse/layers/l7-star-command
11
+ * @version 1.0.0
12
+ * @created Story SYN-5 - Layer Processors L4-L7
13
+ */
14
+
15
+ const path = require('path');
16
+ const { loadDomainFile } = require('../domain/domain-loader');
17
+ const LayerProcessor = require('./layer-processor');
18
+
19
+ /** Regex to detect star-commands in prompt */
20
+ const STAR_COMMAND_REGEX = /\*([a-z][\w-]*)/gi;
21
+
22
+ /**
23
+ * L7 Star-Command Processor
24
+ *
25
+ * Detects *command patterns in the prompt, loads the commands
26
+ * domain file, and extracts rules for matching command blocks.
27
+ * Returns null if no star-commands detected.
28
+ *
29
+ * @extends LayerProcessor
30
+ */
31
+ class L7StarCommandProcessor extends LayerProcessor {
32
+ constructor() {
33
+ super({ name: 'star-command', layer: 7, timeout: 5 });
34
+ }
35
+
36
+ /**
37
+ * Detect star-commands and load matching rules.
38
+ *
39
+ * Detection flow:
40
+ * 1. Scan prompt for *command patterns via regex
41
+ * 2. Deduplicate detected commands
42
+ * 3. Load .synapse/commands domain file
43
+ * 4. Parse command blocks delimited by [*command]
44
+ * 5. Collect rules for detected commands
45
+ *
46
+ * @param {object} context
47
+ * @param {string} context.prompt - Current prompt text
48
+ * @param {object} context.session - Session state (SYN-2 schema)
49
+ * @param {object} context.config - Config with synapsePath and manifest
50
+ * @param {object[]} context.previousLayers - Results from previous layers
51
+ * @returns {{ rules: string[], metadata: object } | null}
52
+ */
53
+ process(context) {
54
+ const { prompt, config } = context;
55
+ const { synapsePath } = config;
56
+
57
+ if (!prompt) {
58
+ return null;
59
+ }
60
+
61
+ // 1. Detect star-commands in prompt
62
+ const commands = this._detectCommands(prompt);
63
+ if (commands.length === 0) {
64
+ return null;
65
+ }
66
+
67
+ // 2. Load commands domain file
68
+ const commandsFilePath = path.join(synapsePath, 'commands');
69
+ const rawRules = loadDomainFile(commandsFilePath);
70
+
71
+ if (!rawRules || rawRules.length === 0) {
72
+ return null;
73
+ }
74
+
75
+ // 3. Parse command blocks from raw rules
76
+ const commandBlocks = this._parseCommandBlocks(rawRules);
77
+
78
+ // 4. Collect rules for detected commands
79
+ const allRules = [];
80
+ const matchedCommands = [];
81
+
82
+ for (const cmd of commands) {
83
+ const block = commandBlocks[cmd];
84
+ if (block && block.length > 0) {
85
+ allRules.push(...block);
86
+ matchedCommands.push(cmd);
87
+ }
88
+ }
89
+
90
+ if (allRules.length === 0) {
91
+ return null;
92
+ }
93
+
94
+ return {
95
+ rules: allRules,
96
+ metadata: {
97
+ layer: 7,
98
+ commands: matchedCommands,
99
+ },
100
+ };
101
+ }
102
+
103
+ /**
104
+ * Detect star-command patterns in prompt text.
105
+ *
106
+ * @param {string} prompt - User prompt text
107
+ * @returns {string[]} Deduplicated list of command names (lowercase)
108
+ * @private
109
+ */
110
+ _detectCommands(prompt) {
111
+ const matches = [];
112
+ let match;
113
+
114
+ // Reset regex state
115
+ STAR_COMMAND_REGEX.lastIndex = 0;
116
+
117
+ while ((match = STAR_COMMAND_REGEX.exec(prompt)) !== null) {
118
+ matches.push(match[1].toLowerCase());
119
+ }
120
+
121
+ return [...new Set(matches)];
122
+ }
123
+
124
+ /**
125
+ * Parse command blocks from domain file rules.
126
+ *
127
+ * Format:
128
+ * [*command] COMMAND:
129
+ * 0. Rule text here
130
+ * 1. Another rule
131
+ *
132
+ * Each [*command] header starts a new block.
133
+ * Rules within a block are the lines following the header.
134
+ *
135
+ * @param {string[]} rules - Raw rules from loadDomainFile
136
+ * @returns {object} Map of command name -> rule strings
137
+ * @private
138
+ */
139
+ _parseCommandBlocks(rules) {
140
+ const blocks = {};
141
+ let currentCommand = null;
142
+
143
+ for (const rule of rules) {
144
+ // Check if this line is a command header: [*command]
145
+ const headerMatch = rule.match(/^\[\*([a-z][\w-]*)\]/i);
146
+ if (headerMatch) {
147
+ currentCommand = headerMatch[1].toLowerCase();
148
+ if (!blocks[currentCommand]) {
149
+ blocks[currentCommand] = [];
150
+ }
151
+ // If there's content after the header on the same line, include it
152
+ const afterHeader = rule.substring(headerMatch[0].length).trim();
153
+ if (afterHeader && !afterHeader.endsWith(':')) {
154
+ blocks[currentCommand].push(afterHeader);
155
+ }
156
+ continue;
157
+ }
158
+
159
+ // Add rule to current command block
160
+ if (currentCommand && rule.trim()) {
161
+ blocks[currentCommand].push(rule.trim());
162
+ }
163
+ }
164
+
165
+ return blocks;
166
+ }
167
+ }
168
+
169
+ module.exports = L7StarCommandProcessor;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * LayerProcessor — Abstract Base Class
3
+ *
4
+ * Defines the contract for all 8 SYNAPSE layer processors.
5
+ * Each layer implements process() to inject contextual rules
6
+ * into the prompt pipeline. The _safeProcess() wrapper provides
7
+ * timeout monitoring and error recovery (graceful degradation).
8
+ *
9
+ * @module core/synapse/layers/layer-processor
10
+ * @version 1.0.0
11
+ * @created Story SYN-4 - Layer Processors L0-L3
12
+ */
13
+
14
+ /**
15
+ * Abstract base class for SYNAPSE layer processors.
16
+ *
17
+ * Subclasses MUST override process() with their layer-specific logic.
18
+ * Use _safeProcess() as the public entry point — it wraps process()
19
+ * with timeout monitoring and error handling.
20
+ *
21
+ * @abstract
22
+ */
23
+ class LayerProcessor {
24
+ /**
25
+ * @param {object} options
26
+ * @param {string} options.name - Layer name (e.g., 'constitution', 'global')
27
+ * @param {number} options.layer - Layer number (0-7)
28
+ * @param {number} [options.timeout=15] - Timeout budget in milliseconds
29
+ */
30
+ constructor({ name, layer, timeout = 15 }) {
31
+ if (new.target === LayerProcessor) {
32
+ throw new Error('LayerProcessor is abstract and cannot be instantiated directly');
33
+ }
34
+ this.name = name;
35
+ this.layer = layer;
36
+ this.timeout = timeout;
37
+ }
38
+
39
+ /**
40
+ * Process the layer and return contextual rules.
41
+ *
42
+ * Subclasses MUST override this method.
43
+ *
44
+ * @param {object} context
45
+ * @param {string} context.prompt - Current prompt text
46
+ * @param {object} context.session - Session state (SYN-2 schema)
47
+ * @param {object} context.config - Config with synapsePath and manifest
48
+ * @param {string} context.config.synapsePath - Base path to .synapse/ directory
49
+ * @param {object} context.config.manifest - Parsed manifest from parseManifest()
50
+ * @param {object[]} context.previousLayers - Results from previous layers
51
+ * @returns {{ rules: string[], metadata: object } | null} Rules and metadata, or null to skip
52
+ */
53
+ process(context) {
54
+ throw new Error(`${this.name}: process() must be implemented by subclass`);
55
+ }
56
+
57
+ /**
58
+ * Safe wrapper with timeout guard and error recovery.
59
+ *
60
+ * Calls process() and monitors execution time against the timeout budget.
61
+ * On error, logs a warning and returns null (graceful degradation).
62
+ *
63
+ * @param {object} context - Same as process()
64
+ * @returns {{ rules: string[], metadata: object } | null} Result or null on error/timeout
65
+ */
66
+ _safeProcess(context) {
67
+ const start = Date.now();
68
+ try {
69
+ const result = this.process(context);
70
+ const elapsed = Date.now() - start;
71
+ if (elapsed > this.timeout) {
72
+ console.warn(`[synapse:${this.name}] Warning: Layer exceeded timeout (${elapsed}ms > ${this.timeout}ms)`);
73
+ }
74
+ return result;
75
+ } catch (error) {
76
+ console.warn(`[synapse:${this.name}] Error: ${error.message}`);
77
+ return null;
78
+ }
79
+ }
80
+ }
81
+
82
+ module.exports = LayerProcessor;
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Memory Bridge — MIS consumer for SYNAPSE engine.
3
+ *
4
+ * Connects SynapseEngine to the Memory Intelligence System (MIS)
5
+ * via SynapseMemoryProvider. Implements bracket-aware retrieval with
6
+ * agent-scoped sector filtering and token budget enforcement.
7
+ *
8
+ * Consumer-only: reads from MIS APIs, never modifies memory stores.
9
+ * Graceful no-op when MIS module is not installed.
10
+ *
11
+ * @module core/synapse/memory/memory-bridge
12
+ * @version 2.0.0
13
+ * @created Story SYN-10 - Pro Memory Bridge (Feature-Gated MIS Consumer)
14
+ * @migrated Story INS-4.11 - Removed pro feature gate (AC9)
15
+ */
16
+
17
+ 'use strict';
18
+
19
+ const { estimateTokens } = require('../utils/tokens');
20
+
21
+ /** Memory bridge timeout in milliseconds. */
22
+ const BRIDGE_TIMEOUT_MS = 15;
23
+
24
+ /**
25
+ * Bracket-to-memory-layer mapping.
26
+ *
27
+ * FRESH → skip (no memory needed)
28
+ * MODERATE → Layer 1 metadata (~50 tokens)
29
+ * DEPLETED → Layer 2 chunks (~200 tokens)
30
+ * CRITICAL → Layer 3 full content (~1000 tokens)
31
+ */
32
+ const BRACKET_LAYER_MAP = {
33
+ FRESH: { layer: 0, maxTokens: 0 },
34
+ MODERATE: { layer: 1, maxTokens: 50 },
35
+ DEPLETED: { layer: 2, maxTokens: 200 },
36
+ CRITICAL: { layer: 3, maxTokens: 1000 },
37
+ };
38
+
39
+ /** Default sector for unknown agents. */
40
+ const DEFAULT_SECTORS = ['semantic'];
41
+
42
+ /**
43
+ * MemoryBridge — MIS consumer for SYNAPSE engine.
44
+ *
45
+ * Provides bracket-aware memory retrieval with:
46
+ * - Agent-scoped sector filtering
47
+ * - Token budget enforcement
48
+ * - Session-level caching
49
+ * - Timeout protection (<15ms)
50
+ * - Error catch-all with warn-and-proceed
51
+ * - Graceful no-op when MIS module is not installed
52
+ */
53
+ class MemoryBridge {
54
+ /**
55
+ * @param {object} [options={}]
56
+ * @param {number} [options.timeout=15] - Max execution time in ms
57
+ */
58
+ constructor(options = {}) {
59
+ this._timeout = options.timeout || BRIDGE_TIMEOUT_MS;
60
+ this._provider = null;
61
+ this._initialized = false;
62
+ }
63
+
64
+ /**
65
+ * Lazy-load the SynapseMemoryProvider (open-source).
66
+ * Gracefully returns null if MIS dependencies are not available.
67
+ *
68
+ * @private
69
+ * @returns {object|null} Provider instance or null
70
+ */
71
+ _getProvider() {
72
+ if (this._provider) return this._provider;
73
+
74
+ try {
75
+ const { SynapseMemoryProvider } = require('./synapse-memory-provider');
76
+ this._provider = new SynapseMemoryProvider();
77
+ return this._provider;
78
+ } catch {
79
+ // Provider or MIS not available — graceful degradation
80
+ return null;
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Get memory hints for the current prompt context.
86
+ *
87
+ * Returns an array of memory hint objects suitable for injection
88
+ * into the SYNAPSE pipeline. Gracefully returns [] when:
89
+ * - MIS module is not installed
90
+ * - Bracket is FRESH (no memory needed)
91
+ * - Provider fails or times out
92
+ * - Any error occurs
93
+ *
94
+ * @param {string} agentId - Active agent ID (e.g., 'dev', 'qa')
95
+ * @param {string} bracket - Context bracket (FRESH, MODERATE, DEPLETED, CRITICAL)
96
+ * @param {number} tokenBudget - Max tokens available for memory hints
97
+ * @returns {Promise<Array<{content: string, source: string, relevance: number, tokens: number}>>}
98
+ */
99
+ async getMemoryHints(agentId, bracket, tokenBudget) {
100
+ try {
101
+ // 1. Bracket check — FRESH needs no memory
102
+ const bracketConfig = BRACKET_LAYER_MAP[bracket];
103
+ if (!bracketConfig || bracketConfig.layer === 0) {
104
+ return [];
105
+ }
106
+
107
+ // 2. Calculate effective token budget
108
+ const effectiveBudget = Math.min(
109
+ bracketConfig.maxTokens,
110
+ tokenBudget > 0 ? tokenBudget : bracketConfig.maxTokens,
111
+ );
112
+
113
+ if (effectiveBudget <= 0) {
114
+ return [];
115
+ }
116
+
117
+ // 3. Load provider
118
+ const provider = this._getProvider();
119
+ if (!provider) {
120
+ return [];
121
+ }
122
+
123
+ // 4. Execute with timeout protection
124
+ const hints = await this._executeWithTimeout(
125
+ () => provider.getMemories(agentId, bracket, effectiveBudget),
126
+ this._timeout,
127
+ );
128
+
129
+ // 5. Enforce token budget on results
130
+ return this._enforceTokenBudget(hints || [], effectiveBudget);
131
+ } catch (error) {
132
+ // Catch-all: warn and proceed with empty results
133
+ console.warn(`[synapse:memory-bridge] Error getting memory hints: ${error.message}`);
134
+ return [];
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Execute a function with timeout protection.
140
+ *
141
+ * @private
142
+ * @param {Function} fn - Async function to execute
143
+ * @param {number} timeoutMs - Timeout in milliseconds
144
+ * @returns {Promise<*>} Result or empty array on timeout
145
+ */
146
+ async _executeWithTimeout(fn, timeoutMs) {
147
+ return new Promise((resolve) => {
148
+ const timer = setTimeout(() => {
149
+ console.warn(`[synapse:memory-bridge] Timeout after ${timeoutMs}ms`);
150
+ resolve([]);
151
+ }, timeoutMs);
152
+
153
+ Promise.resolve(fn())
154
+ .then((result) => {
155
+ clearTimeout(timer);
156
+ resolve(result);
157
+ })
158
+ .catch((error) => {
159
+ clearTimeout(timer);
160
+ console.warn(`[synapse:memory-bridge] Provider error: ${error.message}`);
161
+ resolve([]);
162
+ });
163
+ });
164
+ }
165
+
166
+ /**
167
+ * Enforce token budget on hint array.
168
+ * Removes hints from end until within budget.
169
+ *
170
+ * @private
171
+ * @param {Array<{content: string, tokens: number}>} hints
172
+ * @param {number} budget
173
+ * @returns {Array}
174
+ */
175
+ _enforceTokenBudget(hints, budget) {
176
+ if (!Array.isArray(hints) || hints.length === 0) {
177
+ return [];
178
+ }
179
+
180
+ const result = [];
181
+ let tokensUsed = 0;
182
+
183
+ for (const hint of hints) {
184
+ const hintTokens = hint.tokens || estimateTokens(hint.content || '');
185
+ if (tokensUsed + hintTokens > budget) {
186
+ break;
187
+ }
188
+ result.push({ ...hint, tokens: hintTokens });
189
+ tokensUsed += hintTokens;
190
+ }
191
+
192
+ return result;
193
+ }
194
+
195
+ /**
196
+ * Clear provider cache. Used for testing and session reset.
197
+ */
198
+ clearCache() {
199
+ if (this._provider && typeof this._provider.clearCache === 'function') {
200
+ this._provider.clearCache();
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Reset internal state. Used for testing.
206
+ *
207
+ * @private
208
+ */
209
+ _reset() {
210
+ this._provider = null;
211
+ this._initialized = false;
212
+ }
213
+ }
214
+
215
+ module.exports = {
216
+ MemoryBridge,
217
+ BRACKET_LAYER_MAP,
218
+ BRIDGE_TIMEOUT_MS,
219
+ DEFAULT_SECTORS,
220
+ };
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Synapse Memory Provider — MIS retrieval for SYNAPSE engine.
3
+ *
4
+ * Implements the provider interface consumed by MemoryBridge.
5
+ * Open-source: no feature gate required.
6
+ *
7
+ * Responsibilities:
8
+ * - Agent-scoped memory retrieval using AGENT_SECTOR_PREFERENCES
9
+ * - Progressive disclosure layer selection based on bracket
10
+ * - Session-level caching (keyed by agentId-bracket)
11
+ * - Token budget respect
12
+ *
13
+ * @module core/synapse/memory/synapse-memory-provider
14
+ * @version 2.0.0
15
+ * @created Story SYN-10 - Pro Memory Bridge (Feature-Gated MIS Consumer)
16
+ * @migrated Story INS-4.11 - Moved from pro/ to open-source (AC9)
17
+ */
18
+
19
+ 'use strict';
20
+
21
+ const { estimateTokens } = require('../utils/tokens');
22
+
23
+ /** Default sectors for unknown agents. */
24
+ const DEFAULT_SECTORS = ['semantic'];
25
+
26
+ /**
27
+ * Agent sector preferences for memory retrieval.
28
+ * Defines which cognitive sectors each agent prefers.
29
+ *
30
+ * Moved from pro/memory/memory-loader.js to open-source.
31
+ */
32
+ const AGENT_SECTOR_PREFERENCES = {
33
+ dev: ['procedural', 'semantic'],
34
+ qa: ['reflective', 'episodic'],
35
+ architect: ['semantic', 'reflective'],
36
+ pm: ['episodic', 'semantic'],
37
+ po: ['episodic', 'semantic'],
38
+ sm: ['procedural', 'episodic'],
39
+ devops: ['procedural', 'episodic'],
40
+ analyst: ['semantic', 'reflective'],
41
+ 'data-engineer': ['procedural', 'semantic'],
42
+ 'ux-design-expert': ['reflective', 'procedural'],
43
+ };
44
+
45
+ /**
46
+ * Bracket → retrieval configuration.
47
+ */
48
+ const BRACKET_CONFIG = {
49
+ MODERATE: { layer: 1, limit: 3, minRelevance: 0.7 },
50
+ DEPLETED: { layer: 2, limit: 5, minRelevance: 0.5 },
51
+ CRITICAL: { layer: 3, limit: 10, minRelevance: 0.3 },
52
+ };
53
+
54
+ /**
55
+ * SynapseMemoryProvider — Open-source memory retrieval.
56
+ *
57
+ * Provides memories from MIS for SYNAPSE engine injection.
58
+ * Session-level caching avoids repeated MIS queries for
59
+ * the same agent + bracket combination.
60
+ *
61
+ * Uses lazy-loading for MemoryLoader to gracefully degrade
62
+ * when the MIS module is not installed.
63
+ */
64
+ class SynapseMemoryProvider {
65
+ /**
66
+ * @param {object} [options={}]
67
+ * @param {string} [options.projectDir] - Project directory for MemoryLoader
68
+ */
69
+ constructor(options = {}) {
70
+ this._projectDir = options.projectDir || process.cwd();
71
+ this._loader = null;
72
+ /** @type {Map<string, Array>} Session-level cache keyed by `${agentId}-${bracket}` */
73
+ this._cache = new Map();
74
+ }
75
+
76
+ /**
77
+ * Lazy-load MemoryLoader.
78
+ * Gracefully returns null if pro/memory module is not available.
79
+ *
80
+ * @private
81
+ * @returns {object|null}
82
+ */
83
+ _getLoader() {
84
+ if (this._loader) return this._loader;
85
+
86
+ try {
87
+ const { MemoryLoader } = require('../../../../pro/memory/memory-loader');
88
+ this._loader = new MemoryLoader(this._projectDir);
89
+ return this._loader;
90
+ } catch {
91
+ // MIS module not available — graceful degradation
92
+ return null;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Get memories for SYNAPSE engine injection.
98
+ *
99
+ * Uses bracket to determine:
100
+ * - Which MIS layer to query (1=metadata, 2=chunks, 3=full)
101
+ * - How many results to return
102
+ * - Minimum relevance threshold
103
+ *
104
+ * Results are cached per session (agentId + bracket).
105
+ *
106
+ * @param {string} agentId - Active agent ID
107
+ * @param {string} bracket - Context bracket (MODERATE, DEPLETED, CRITICAL)
108
+ * @param {number} tokenBudget - Max tokens for memory hints
109
+ * @returns {Promise<Array<{content: string, source: string, relevance: number, tokens: number}>>}
110
+ */
111
+ async getMemories(agentId, bracket, tokenBudget) {
112
+ // Cache lookup
113
+ const cacheKey = `${agentId}-${bracket}`;
114
+ if (this._cache.has(cacheKey)) {
115
+ return this._cache.get(cacheKey);
116
+ }
117
+
118
+ // Get bracket config
119
+ const config = BRACKET_CONFIG[bracket];
120
+ if (!config) {
121
+ return [];
122
+ }
123
+
124
+ // Get loader (lazy-load, graceful if unavailable)
125
+ const loader = this._getLoader();
126
+ if (!loader) {
127
+ return [];
128
+ }
129
+
130
+ // Get agent sectors
131
+ const sectors = AGENT_SECTOR_PREFERENCES[agentId] || DEFAULT_SECTORS;
132
+
133
+ // Query MIS via MemoryLoader
134
+ const memories = await loader.queryMemories(agentId, {
135
+ sectors,
136
+ layer: config.layer,
137
+ limit: config.limit,
138
+ minRelevance: config.minRelevance,
139
+ tokenBudget,
140
+ });
141
+
142
+ // Transform to hint format
143
+ const hints = this._transformToHints(memories, tokenBudget);
144
+
145
+ // Cache results
146
+ this._cache.set(cacheKey, hints);
147
+
148
+ return hints;
149
+ }
150
+
151
+ /**
152
+ * Transform MIS memory results into hint format.
153
+ *
154
+ * @private
155
+ * @param {Array} memories - Raw memories from MemoryLoader
156
+ * @param {number} tokenBudget - Max tokens
157
+ * @returns {Array<{content: string, source: string, relevance: number, tokens: number}>}
158
+ */
159
+ _transformToHints(memories, tokenBudget) {
160
+ if (!Array.isArray(memories) || memories.length === 0) {
161
+ return [];
162
+ }
163
+
164
+ const hints = [];
165
+ let tokensUsed = 0;
166
+
167
+ for (const memory of memories) {
168
+ const content = memory.content || memory.summary || memory.title || '';
169
+ const tokens = estimateTokens(content);
170
+
171
+ if (tokensUsed + tokens > tokenBudget) {
172
+ break;
173
+ }
174
+
175
+ hints.push({
176
+ content,
177
+ source: memory.source || memory.sector || 'memory',
178
+ relevance: memory.relevance || memory.attention || 0,
179
+ tokens,
180
+ });
181
+
182
+ tokensUsed += tokens;
183
+ }
184
+
185
+ return hints;
186
+ }
187
+
188
+ /**
189
+ * Clear the session cache.
190
+ */
191
+ clearCache() {
192
+ this._cache.clear();
193
+ }
194
+ }
195
+
196
+ module.exports = {
197
+ SynapseMemoryProvider,
198
+ AGENT_SECTOR_PREFERENCES,
199
+ BRACKET_CONFIG,
200
+ DEFAULT_SECTORS,
201
+ };