Skip to content

Commit df63536

Browse files
authored
Merge pull request #130 from Steake/copilot/resolve-merge-conflicts-129
merge: resolve conflicts between main and PR #129 (activate-cognitive-systems)
2 parents 78c2ece + 9082578 commit df63536

File tree

10 files changed

+1605
-8
lines changed

10 files changed

+1605
-8
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ svelte-frontend/node_modules/.package-lock.json
154154
svelte-frontend/node_modules/.vite/deps/_metadata.json
155155
svelte-frontend/test-results/
156156
svelte-frontend/playwright-report/
157+
svelte-frontend/playwright-report-output/
157158
svelte-frontend/screenshots/
158159

159160
# Build artifacts

backend/api/consciousness_endpoints.py

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,84 @@ async def get_emergence_score():
257257
logger.error(f"Failed to get emergence score: {e}")
258258
raise HTTPException(status_code=500, detail=f"Failed to retrieve emergence score: {str(e)}")
259259

260+
261+
@router.get("/breakthroughs")
262+
async def get_breakthroughs(limit: int = Query(50, ge=1, le=500)):
263+
"""Return historical breakthrough log entries (newest first).
264+
265+
Reads the persistent ``logs/breakthroughs.jsonl`` file and returns up to
266+
*limit* entries. Returns an empty list when no breakthroughs have been
267+
recorded yet.
268+
"""
269+
try:
270+
if emergence_detector is not None:
271+
entries = emergence_detector.get_breakthroughs(limit=limit)
272+
return {
273+
"breakthroughs": entries,
274+
"total": len(entries),
275+
"limit": limit,
276+
"threshold": emergence_detector.threshold,
277+
}
278+
raise HTTPException(
279+
status_code=503,
280+
detail="Emergence detector is not initialised",
281+
)
282+
except HTTPException:
283+
raise
284+
except Exception as e:
285+
logger.error(f"Failed to get breakthroughs: {e}")
286+
raise HTTPException(status_code=500, detail=f"Failed to retrieve breakthroughs: {str(e)}")
287+
288+
289+
# Observatory reference — set by unified_server at startup
290+
_observatory = None
291+
292+
293+
def set_observatory(observatory) -> None:
294+
"""Register the UnifiedConsciousnessObservatory instance."""
295+
global _observatory
296+
_observatory = observatory
297+
298+
299+
def get_observatory():
300+
"""Return the active UnifiedConsciousnessObservatory instance (may be None)."""
301+
return _observatory
302+
303+
304+
@router.get("/observatory")
305+
async def get_observatory_report():
306+
"""Return the full UnifiedConsciousnessObservatory report.
307+
308+
Includes uptime, total observed states, total breakthrough events, peak
309+
score, current emergence snapshot, and the 10 most recent breakthroughs.
310+
"""
311+
try:
312+
if _observatory is not None:
313+
return _observatory.get_report()
314+
# Fallback: lightweight report using the detector only
315+
if emergence_detector is not None:
316+
status = emergence_detector.get_emergence_status()
317+
recent = emergence_detector.get_breakthroughs(limit=10)
318+
return {
319+
"running": False,
320+
"uptime_seconds": 0,
321+
"total_states_observed": 0,
322+
"total_breakthroughs": len(recent),
323+
"peak_score": status.get("emergence_score", 0.0),
324+
"current_emergence": status,
325+
"recent_breakthroughs": recent,
326+
}
327+
raise HTTPException(
328+
status_code=503,
329+
detail="Neither observatory nor emergence detector is available",
330+
)
331+
except HTTPException:
332+
raise
333+
except Exception as e:
334+
logger.error(f"Failed to get observatory report: {e}")
335+
raise HTTPException(status_code=500, detail=f"Failed to retrieve observatory report: {str(e)}")
336+
337+
260338
# WebSocket endpoints for real-time consciousness streaming
261339

262340
@router.websocket("/stream")
@@ -313,6 +391,104 @@ async def global_workspace_stream(websocket: WebSocket):
313391

314392
await enhanced_websocket_manager.handle_consciousness_connection(websocket, "workspace")
315393

394+
395+
# ---------------------------------------------------------------------------
396+
# Autonomous Goal Engine endpoints (Issue #81)
397+
# ---------------------------------------------------------------------------
398+
399+
# Module-level references populated at startup by unified_server
400+
_goal_generator = None
401+
_creative_engine = None
402+
403+
404+
def set_goal_engine(generator, creative_engine) -> None:
405+
"""Register the AutonomousGoalGenerator and CreativeSynthesisEngine."""
406+
global _goal_generator, _creative_engine
407+
_goal_generator = generator
408+
_creative_engine = creative_engine
409+
410+
411+
@router.get("/goals")
412+
async def get_autonomous_goals():
413+
"""Return the currently active autonomous goals generated by the system.
414+
415+
Goals are produced without external prompting by monitoring cognitive
416+
state gaps (low phi, coherence drift, knowledge gaps, etc.).
417+
"""
418+
try:
419+
if _goal_generator is not None:
420+
goals = _goal_generator.active_goals
421+
metrics = _goal_generator.get_metrics()
422+
return {
423+
"goals": goals,
424+
"total": len(goals),
425+
"metrics": metrics,
426+
}
427+
raise HTTPException(
428+
status_code=503,
429+
detail="Autonomous goal generator is not initialised",
430+
)
431+
except HTTPException:
432+
raise
433+
except Exception as e:
434+
logger.error(f"Failed to get autonomous goals: {e}")
435+
raise HTTPException(status_code=500, detail=f"Failed to retrieve goals: {str(e)}")
436+
437+
438+
@router.post("/goals/generate")
439+
async def trigger_goal_generation():
440+
"""Manually trigger a round of autonomous goal generation.
441+
442+
Useful for testing or seeding the goal list before any cognitive state
443+
has been observed. Returns the newly proposed goals.
444+
"""
445+
try:
446+
if _goal_generator is not None:
447+
# Use an empty cognitive state to trigger baseline exploration
448+
new_goals = await _goal_generator.generate({})
449+
return {
450+
"new_goals": new_goals,
451+
"total_new": len(new_goals),
452+
"active_total": len(_goal_generator.active_goals),
453+
}
454+
raise HTTPException(
455+
status_code=503,
456+
detail="Autonomous goal generator is not initialised",
457+
)
458+
except HTTPException:
459+
raise
460+
except Exception as e:
461+
logger.error(f"Failed to generate autonomous goals: {e}")
462+
raise HTTPException(status_code=500, detail=f"Failed to generate goals: {str(e)}")
463+
464+
465+
@router.get("/creative-synthesis")
466+
async def get_creative_synthesis(n: int = Query(5, ge=1, le=20)):
467+
"""Return the most recent creative concept-synthesis outputs.
468+
469+
The CreativeSynthesisEngine combines concepts from the active knowledge
470+
store and scores them on novelty and coherence.
471+
"""
472+
try:
473+
if _creative_engine is not None:
474+
outputs = _creative_engine.get_recent_outputs(limit=n)
475+
metrics = _creative_engine.get_metrics()
476+
return {
477+
"syntheses": outputs,
478+
"total": len(outputs),
479+
"metrics": metrics,
480+
}
481+
raise HTTPException(
482+
status_code=503,
483+
detail="Creative synthesis engine is not initialised",
484+
)
485+
except HTTPException:
486+
raise
487+
except Exception as e:
488+
logger.error(f"Failed to get creative syntheses: {e}")
489+
raise HTTPException(status_code=500, detail=f"Failed to retrieve syntheses: {str(e)}")
490+
491+
316492
# Health and statistics endpoints
317493

318494
@router.get("/health")
@@ -410,4 +586,11 @@ async def assess_consciousness_level(query: str = "", context: Optional[Dict] =
410586
raise HTTPException(status_code=500, detail=f"Assessment failed: {str(e)}")
411587

412588
# Export router
413-
__all__ = ['router', 'set_consciousness_engine', 'set_emergence_detector']
589+
__all__ = [
590+
'router',
591+
'set_consciousness_engine',
592+
'set_emergence_detector',
593+
'set_observatory',
594+
'get_observatory',
595+
'set_goal_engine',
596+
]

0 commit comments

Comments
 (0)