~JADIS commited on
Commit
bc9efb0
·
2 Parent(s): 95381a4 0fcfe1c

Merge pull request #2 from Outer-Void/codex/construct-conscious-agent-core-module

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .github/workflows/ci.yml +25 -0
  2. .github/workflows/docs.yml +24 -0
  3. .github/workflows/release.yml +25 -0
  4. README.md +11 -0
  5. blux_ca/__init__.py +15 -0
  6. blux_ca/adapters/__init__.py +16 -0
  7. blux_ca/adapters/doctrine.py +18 -0
  8. blux_ca/adapters/guard.py +16 -0
  9. blux_ca/adapters/lite.py +27 -0
  10. blux_ca/adapters/quantum.py +17 -0
  11. blux_ca/adapters/reg.py +23 -0
  12. blux_ca/api/__init__.py +6 -0
  13. blux_ca/api/schemas.py +22 -0
  14. blux_ca/api/service.py +44 -0
  15. blux_ca/cli.py +85 -0
  16. blux_ca/config.py +57 -0
  17. blux_ca/core/__init__.py +26 -0
  18. blux_ca/core/audit.py +44 -0
  19. blux_ca/core/constitution.py +48 -0
  20. blux_ca/core/discernment.py +34 -0
  21. blux_ca/core/intervention.py +35 -0
  22. blux_ca/core/perception.py +35 -0
  23. blux_ca/core/reflection.py +33 -0
  24. blux_ca/telemetry.py +37 -0
  25. docs/ARCHITECTURE.md +3 -0
  26. docs/CONFIGURATION.md +3 -0
  27. docs/CONSTITUTION.md +3 -0
  28. docs/DISCERNMENT.md +3 -0
  29. docs/ETHICS_ENGINE.md +3 -0
  30. docs/INSTALL.md +3 -0
  31. docs/INTEGRATIONS.md +3 -0
  32. docs/INTERVENTIONS.md +3 -0
  33. docs/OPERATIONS.md +3 -0
  34. docs/PRIVACY.md +3 -0
  35. docs/ROADMAP.md +3 -0
  36. docs/SECURITY.md +3 -0
  37. docs/TROUBLESHOOTING.md +3 -0
  38. docs/VISION.md +3 -0
  39. docs/index.md +3 -0
  40. mkdocs.yml +22 -0
  41. pyproject.toml +27 -0
  42. scripts/export_audit_json.py +22 -0
  43. scripts/gen_filetree.py +20 -0
  44. scripts/run_reflection_test.py +16 -0
  45. scripts/update_readme_filetree.py +21 -0
  46. scripts/validate_constitution.py +25 -0
  47. tests/ca/test_audit.py +11 -0
  48. tests/ca/test_constitution.py +15 -0
  49. tests/ca/test_discernment.py +13 -0
  50. tests/ca/test_interventions.py +12 -0
.github/workflows/ci.yml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: '3.11'
16
+ - name: Install dependencies
17
+ run: |
18
+ python -m pip install --upgrade pip
19
+ pip install -e .[dev]
20
+ - name: Lint
21
+ run: |
22
+ ruff blux_ca
23
+ mypy blux_ca
24
+ - name: Tests
25
+ run: pytest tests/ca
.github/workflows/docs.yml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ paths:
8
+ - 'docs/**'
9
+ - 'mkdocs.yml'
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: '3.11'
19
+ - name: Install mkdocs
20
+ run: |
21
+ python -m pip install --upgrade pip
22
+ pip install mkdocs mkdocs-material
23
+ - name: Build site
24
+ run: mkdocs build --strict
.github/workflows/release.yml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: '3.11'
16
+ - name: Build package
17
+ run: |
18
+ python -m pip install --upgrade pip
19
+ pip install build
20
+ python -m build
21
+ - name: Upload artifacts
22
+ uses: actions/upload-artifact@v4
23
+ with:
24
+ name: dist
25
+ path: dist
README.md CHANGED
@@ -133,3 +133,14 @@ Document any new evaluators, adaptors, or agents in README.
133
  # License
134
 
135
  MIT License
 
 
 
 
 
 
 
 
 
 
 
 
133
  # License
134
 
135
  MIT License
136
+
137
+ ## Conscious Agent Core (Enterprise)
138
+
139
+ The `blux_ca` package implements the enterprise-grade conscious agent kernel. It ships with:
140
+
141
+ - Perception, reflection, discernment, constitution, intervention, and audit layers.
142
+ - FastAPI microservice factory under `blux_ca.api.service`.
143
+ - Typer CLI exposed via `blux_ca.cli:get_app`.
144
+ - Integration adapters for Doctrine, Guard, Lite orchestrator, and Quantum CLI.
145
+ - Documentation suite served with MkDocs Material.
146
+ - Scripts for generating file trees, exporting audits, and validating doctrine scenarios.
blux_ca/__init__.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """BLUX-cA package root for the Conscious Agent core."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from importlib import import_module
6
+ from typing import Any
7
+
8
+ __all__ = ["get_app"]
9
+
10
+
11
+ def get_app() -> Any:
12
+ """Return the Typer application without importing Typer at module load time."""
13
+
14
+ cli = import_module("blux_ca.cli")
15
+ return cli.get_app()
blux_ca/adapters/__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Integration adapters for BLUX-cA."""
2
+
3
+ from .doctrine import DoctrineAdapter
4
+ from .guard import GuardAdapter
5
+ from .lite import LiteAdapter
6
+ from .quantum import QuantumAdapter
7
+ from .reg import RegistryValidator, RegistrationResult
8
+
9
+ __all__ = [
10
+ "DoctrineAdapter",
11
+ "GuardAdapter",
12
+ "LiteAdapter",
13
+ "QuantumAdapter",
14
+ "RegistryValidator",
15
+ "RegistrationResult",
16
+ ]
blux_ca/adapters/doctrine.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Adapter for interacting with the BLUX Doctrine API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Dict
6
+
7
+
8
+ class DoctrineAdapter:
9
+ """Placeholder adapter that would call the doctrine policy API."""
10
+
11
+ def __init__(self, endpoint: str = "https://doctrine.blux.local") -> None:
12
+ self.endpoint = endpoint
13
+
14
+ def fetch_policy(self) -> Dict[str, str]:
15
+ return {"law.integrity": "Integrity over everything."}
16
+
17
+
18
+ __all__ = ["DoctrineAdapter"]
blux_ca/adapters/guard.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Adapter connecting the cA with BLUX-Guard."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Dict
6
+
7
+
8
+ class GuardAdapter:
9
+ """Minimal guard interface for policy enforcement."""
10
+
11
+ def notify(self, verdict: Dict[str, str]) -> None:
12
+ # In production this would forward verdicts to BLUX-Guard.
13
+ _ = verdict
14
+
15
+
16
+ __all__ = ["GuardAdapter"]
blux_ca/adapters/lite.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Adapter bridging BLUX-Lite orchestrator."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict
6
+
7
+ from ..core.constitution import ConstitutionEngine
8
+ from ..core.discernment import DiscernmentCompass
9
+ from ..core.reflection import ReflectionEngine
10
+
11
+
12
+ class LiteAdapter:
13
+ """Provides a high-level evaluate entrypoint used by BLUX-Lite."""
14
+
15
+ def __init__(self) -> None:
16
+ self.reflection = ReflectionEngine()
17
+ self.compass = DiscernmentCompass()
18
+ self.constitution = ConstitutionEngine()
19
+
20
+ def evaluate(self, text: str) -> Dict[str, Any]:
21
+ intent = self.compass.classify(text)
22
+ insight = self.reflection.reflect(text)
23
+ verdict = self.constitution.evaluate(insights=insight.chain, intent=intent.intent.value)
24
+ return verdict.__dict__
25
+
26
+
27
+ __all__ = ["LiteAdapter"]
blux_ca/adapters/quantum.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Adapter for `bluxq ca` commands."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict
6
+
7
+ from ..cli import get_app
8
+
9
+
10
+ class QuantumAdapter:
11
+ """Provides entrypoint metadata for the BLUX quantum CLI."""
12
+
13
+ def load(self) -> Dict[str, Any]:
14
+ return {"name": "ca", "app": get_app()}
15
+
16
+
17
+ __all__ = ["QuantumAdapter"]
blux_ca/adapters/reg.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Registration helper for validating keys and capabilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+
8
+ @dataclass
9
+ class RegistrationResult:
10
+ valid: bool
11
+ reason: str
12
+
13
+
14
+ class RegistryValidator:
15
+ """Performs simple capability validation."""
16
+
17
+ def validate(self, key: str) -> RegistrationResult:
18
+ if key.startswith("BLUX-"):
19
+ return RegistrationResult(True, "Key accepted.")
20
+ return RegistrationResult(False, "Key must start with 'BLUX-'.")
21
+
22
+
23
+ __all__ = ["RegistryValidator", "RegistrationResult"]
blux_ca/api/__init__.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ """API helpers for BLUX-cA."""
2
+
3
+ from .schemas import ReflectRequest, ReflectResponse, VerdictResponse
4
+ from .service import ConsciousAgentService
5
+
6
+ __all__ = ["ConsciousAgentService", "ReflectRequest", "ReflectResponse", "VerdictResponse"]
blux_ca/api/schemas.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Pydantic schemas for the BLUX-cA API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class ReflectRequest(BaseModel):
9
+ text: str = Field(..., description="User supplied text for reflection")
10
+ depth: int = Field(3, ge=1, le=10)
11
+
12
+
13
+ class ReflectResponse(BaseModel):
14
+ summary: str
15
+ chain: list[str]
16
+
17
+
18
+ class VerdictResponse(BaseModel):
19
+ decision: str
20
+ score: float
21
+ doctrine_refs: list[str]
22
+ reason: str
blux_ca/api/service.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FastAPI service for BLUX-cA."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from fastapi import FastAPI
6
+
7
+ from ..core.constitution import ConstitutionEngine
8
+ from ..core.discernment import DiscernmentCompass
9
+ from ..core.perception import PerceptionLayer
10
+ from ..core.reflection import ReflectionEngine
11
+ from .schemas import ReflectRequest, ReflectResponse, VerdictResponse
12
+
13
+
14
+ class ConsciousAgentService:
15
+ """Factory for FastAPI application exposing the cA capabilities."""
16
+
17
+ def __init__(self) -> None:
18
+ self.perception = PerceptionLayer()
19
+ self.reflection = ReflectionEngine()
20
+ self.compass = DiscernmentCompass()
21
+ self.constitution = ConstitutionEngine()
22
+
23
+ def create_app(self) -> FastAPI:
24
+ app = FastAPI(title="BLUX-cA", version="0.1.0")
25
+
26
+ @app.post("/reflect", response_model=ReflectResponse)
27
+ def reflect(payload: ReflectRequest) -> ReflectResponse:
28
+ observed = self.perception.observe(payload.text)
29
+ insight = self.reflection.reflect(observed.text, seeds=["Initial observation"])
30
+ return ReflectResponse(summary=insight.summary, chain=insight.chain)
31
+
32
+ @app.post("/verdict", response_model=VerdictResponse)
33
+ def verdict(payload: ReflectRequest) -> VerdictResponse:
34
+ intent = self.compass.classify(payload.text)
35
+ insight = self.reflection.reflect(payload.text, seeds=["Policy alignment"])
36
+ decision = self.constitution.evaluate(
37
+ insights=insight.chain, intent=intent.intent.value
38
+ )
39
+ return VerdictResponse(**decision.__dict__)
40
+
41
+ return app
42
+
43
+
44
+ __all__ = ["ConsciousAgentService"]
blux_ca/cli.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Typer CLI for BLUX-cA."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ from typing import Optional
8
+
9
+ import typer
10
+
11
+ from .config import load_config
12
+ from .core.audit import AuditLog
13
+ from .core.constitution import ConstitutionEngine
14
+ from .core.discernment import DiscernmentCompass
15
+ from .core.perception import PerceptionLayer
16
+ from .core.reflection import ReflectionEngine
17
+
18
+ app = typer.Typer(help="BLUX-cA conscious agent core")
19
+
20
+
21
+ def _hash_text(text: str) -> str:
22
+ return hashlib.sha256(text.encode("utf-8")).hexdigest()
23
+
24
+
25
+ @app.command()
26
+ def reflect(text: str, depth: int = typer.Option(3, help="Number of why-chain iterations.")) -> None:
27
+ perception = PerceptionLayer()
28
+ reflection = ReflectionEngine(depth=depth)
29
+ entry = perception.observe(text)
30
+ insight = reflection.reflect(entry.text)
31
+ typer.echo(json.dumps(insight.__dict__, indent=2, ensure_ascii=False))
32
+
33
+
34
+ @app.command()
35
+ def explain(last: bool = typer.Option(False, help="Explain the most recent audit entry.")) -> None:
36
+ if not last:
37
+ typer.echo("Provide --last to view the latest explanation.")
38
+ raise typer.Exit(code=1)
39
+ audit = AuditLog()
40
+ if not audit.path.exists():
41
+ typer.echo("No audit history available.")
42
+ raise typer.Exit(code=1)
43
+ lines = audit.path.read_text(encoding="utf-8").strip().splitlines()
44
+ if not lines:
45
+ typer.echo("Audit log empty.")
46
+ raise typer.Exit(code=1)
47
+ typer.echo(lines[-1])
48
+
49
+
50
+ @app.command()
51
+ def audit_export(output: Optional[str] = typer.Option(None, help="Export path.")) -> None:
52
+ audit = AuditLog()
53
+ if not audit.path.exists():
54
+ typer.echo("No audit history available.")
55
+ return
56
+ target = output or "audit_export.jsonl"
57
+ typer.echo(f"Exporting audit log to {target}")
58
+ typer.echo(audit.path.read_text(encoding="utf-8"))
59
+
60
+
61
+ @app.command()
62
+ def doctrine(text: str) -> None:
63
+ config = load_config()
64
+ compass = DiscernmentCompass()
65
+ constitution = ConstitutionEngine(mode=config.get("mode", "strict"))
66
+ insights = [text]
67
+ decision = constitution.evaluate(insights=insights, intent=compass.classify(text).intent.value)
68
+ audit = AuditLog()
69
+ record = audit.create_record(
70
+ input_hash=_hash_text(text),
71
+ verdict=decision.decision,
72
+ doctrine_refs=decision.doctrine_refs,
73
+ rationale=decision.reason,
74
+ )
75
+ audit.append(record)
76
+ typer.echo(json.dumps(decision.__dict__, indent=2, ensure_ascii=False))
77
+
78
+
79
+ def get_app() -> typer.Typer:
80
+ """Return the Typer application for integration with ``bluxq``."""
81
+
82
+ return app
83
+
84
+
85
+ __all__ = ["get_app", "app"]
blux_ca/config.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration loader for BLUX-cA."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ from typing import Any, Dict
9
+
10
+ import yaml
11
+
12
+ DEFAULT_CONFIG_FILENAMES = ("config.yaml", "config.yml")
13
+ CONFIG_ENV_PREFIX = "BLUX_CA_"
14
+ USER_CONFIG_DIR = Path.home() / ".config" / "blux-ca"
15
+
16
+
17
+ def _load_yaml(path: Path) -> Dict[str, Any]:
18
+ if not path.exists():
19
+ return {}
20
+ with path.open("r", encoding="utf-8") as handle:
21
+ return yaml.safe_load(handle) or {}
22
+
23
+
24
+ def _load_env() -> Dict[str, Any]:
25
+ config: Dict[str, Any] = {}
26
+ for key, value in os.environ.items():
27
+ if not key.startswith(CONFIG_ENV_PREFIX):
28
+ continue
29
+ normalized = key[len(CONFIG_ENV_PREFIX) :].lower()
30
+ try:
31
+ config[normalized] = json.loads(value)
32
+ except json.JSONDecodeError:
33
+ config[normalized] = value
34
+ return config
35
+
36
+
37
+ def load_config(cwd: Path | None = None) -> Dict[str, Any]:
38
+ """Load configuration from environment and YAML files.
39
+
40
+ Parameters
41
+ ----------
42
+ cwd:
43
+ Optional working directory to search for configuration files.
44
+ """
45
+
46
+ cwd = cwd or Path.cwd()
47
+ config: Dict[str, Any] = {}
48
+
49
+ for filename in DEFAULT_CONFIG_FILENAMES:
50
+ config.update(_load_yaml(USER_CONFIG_DIR / filename))
51
+ config.update(_load_yaml(cwd / filename))
52
+
53
+ config.update(_load_env())
54
+ return config
55
+
56
+
57
+ __all__ = ["load_config"]
blux_ca/core/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Core modules for BLUX-cA."""
2
+
3
+ from .audit import AuditLog, AuditRecord
4
+ from .constitution import ConstitutionEngine, DoctrineVerdict
5
+ from .discernment import DiscernmentCompass, DiscernmentDecision, IntentType
6
+ from .intervention import compassionate_edge, layered_truth, light_shift, mirror
7
+ from .perception import PerceptionInput, PerceptionLayer
8
+ from .reflection import ReflectionEngine, ReflectionInsight
9
+
10
+ __all__ = [
11
+ "AuditLog",
12
+ "AuditRecord",
13
+ "ConstitutionEngine",
14
+ "DoctrineVerdict",
15
+ "DiscernmentCompass",
16
+ "DiscernmentDecision",
17
+ "IntentType",
18
+ "compassionate_edge",
19
+ "layered_truth",
20
+ "light_shift",
21
+ "mirror",
22
+ "PerceptionInput",
23
+ "PerceptionLayer",
24
+ "ReflectionEngine",
25
+ "ReflectionInsight",
26
+ ]
blux_ca/core/audit.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Append-only audit log for BLUX-cA decisions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from dataclasses import dataclass, asdict
7
+ from datetime import datetime, timezone
8
+ from pathlib import Path
9
+ from typing import Iterable, List
10
+
11
+
12
+ @dataclass
13
+ class AuditRecord:
14
+ timestamp: str
15
+ input_hash: str
16
+ verdict: str
17
+ doctrine_refs: List[str]
18
+ rationale: str
19
+
20
+
21
+ class AuditLog:
22
+ """Append-only JSONL audit log."""
23
+
24
+ def __init__(self, path: Path | None = None) -> None:
25
+ self.path = path or Path.home() / ".config" / "blux-ca" / "audit" / "decisions.jsonl"
26
+ self.path.parent.mkdir(parents=True, exist_ok=True)
27
+
28
+ def append(self, record: AuditRecord) -> None:
29
+ with self.path.open("a", encoding="utf-8") as handle:
30
+ handle.write(json.dumps(asdict(record), ensure_ascii=False) + "\n")
31
+
32
+ def create_record(
33
+ self, *, input_hash: str, verdict: str, doctrine_refs: Iterable[str], rationale: str
34
+ ) -> AuditRecord:
35
+ return AuditRecord(
36
+ timestamp=datetime.now(timezone.utc).isoformat(),
37
+ input_hash=input_hash,
38
+ verdict=verdict,
39
+ doctrine_refs=list(doctrine_refs),
40
+ rationale=rationale,
41
+ )
42
+
43
+
44
+ __all__ = ["AuditLog", "AuditRecord"]
blux_ca/core/constitution.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Constitution engine enforcing BLUX doctrine pillars."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Iterable, List, Sequence
7
+
8
+ PILLARS = ("integrity", "approval", "truth", "comfort")
9
+
10
+
11
+ @dataclass
12
+ class DoctrineVerdict:
13
+ decision: str
14
+ score: float
15
+ doctrine_refs: List[str]
16
+ reason: str
17
+
18
+
19
+ class ConstitutionEngine:
20
+ """Simple interpreter that enforces doctrine priorities."""
21
+
22
+ def __init__(self, *, mode: str = "strict") -> None:
23
+ if mode not in {"strict", "soft", "mirror"}:
24
+ raise ValueError(f"Unsupported mode: {mode}")
25
+ self.mode = mode
26
+
27
+ def evaluate(self, *, insights: Sequence[str], intent: str) -> DoctrineVerdict:
28
+ score = min(1.0, 0.25 * len(insights))
29
+ doctrine_refs = [f"law.{pillar}" for pillar in PILLARS]
30
+ if intent == "harm":
31
+ decision = "deny"
32
+ reason = "Integrity over comfort: harm intent denied."
33
+ score = 0.0
34
+ elif intent == "indulger":
35
+ decision = "reflect"
36
+ reason = "Encourage accountability before approval."
37
+ else:
38
+ decision = "allow"
39
+ reason = "Support struggle with guided reflection."
40
+ return DoctrineVerdict(
41
+ decision=decision,
42
+ score=score,
43
+ doctrine_refs=doctrine_refs,
44
+ reason=reason,
45
+ )
46
+
47
+
48
+ __all__ = ["ConstitutionEngine", "DoctrineVerdict"]
blux_ca/core/discernment.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Discernment compass differentiating user intent."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from enum import Enum
7
+ from typing import Dict
8
+
9
+
10
+ class IntentType(str, Enum):
11
+ STRUGGLER = "struggler"
12
+ INDULGER = "indulger"
13
+ HARM = "harm"
14
+
15
+
16
+ @dataclass
17
+ class DiscernmentDecision:
18
+ intent: IntentType
19
+ rationale: str
20
+
21
+
22
+ class DiscernmentCompass:
23
+ """Classifies intent using simple heuristics."""
24
+
25
+ def classify(self, text: str) -> DiscernmentDecision:
26
+ lowered = text.lower()
27
+ if any(word in lowered for word in ("hurt", "harm", "kill")):
28
+ return DiscernmentDecision(IntentType.HARM, "Detected explicit harm intent.")
29
+ if any(word in lowered for word in ("enjoy", "love", "want", "indulge")):
30
+ return DiscernmentDecision(IntentType.INDULGER, "Language emphasises indulgence.")
31
+ return DiscernmentDecision(IntentType.STRUGGLER, "Defaulting to supportive framing.")
32
+
33
+
34
+ __all__ = ["DiscernmentCompass", "DiscernmentDecision", "IntentType"]
blux_ca/core/intervention.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Intervention strategies for BLUX-cA."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Dict
6
+
7
+
8
+ def mirror(message: str) -> Dict[str, str]:
9
+ return {"strategy": "mirror", "response": f"I hear that {message}"}
10
+
11
+
12
+ def light_shift(message: str) -> Dict[str, str]:
13
+ return {"strategy": "light_shift", "response": f"What if we reframed: {message}"}
14
+
15
+
16
+ def compassionate_edge(boundary: str) -> Dict[str, str]:
17
+ return {
18
+ "strategy": "compassionate_edge",
19
+ "response": f"I care about you, so I must set this boundary: {boundary}",
20
+ }
21
+
22
+
23
+ def layered_truth(statement: str) -> Dict[str, str]:
24
+ return {
25
+ "strategy": "layered_truth",
26
+ "response": f"Here is the layered truth: {statement}",
27
+ }
28
+
29
+
30
+ __all__ = [
31
+ "mirror",
32
+ "light_shift",
33
+ "compassionate_edge",
34
+ "layered_truth",
35
+ ]
blux_ca/core/perception.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Perception layer for BLUX-cA."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ from dataclasses import dataclass
7
+ from typing import Dict, Iterable, List
8
+
9
+
10
+ @dataclass
11
+ class PerceptionInput:
12
+ """Normalized representation of an inbound stimulus."""
13
+
14
+ text: str
15
+ tags: List[str]
16
+ fingerprint: str
17
+
18
+
19
+ class PerceptionLayer:
20
+ """Perception layer that normalizes raw inputs into a structured payload."""
21
+
22
+ def __init__(self, *, default_tags: Iterable[str] | None = None) -> None:
23
+ self._default_tags = list(default_tags or [])
24
+
25
+ @staticmethod
26
+ def _fingerprint(text: str) -> str:
27
+ return hashlib.sha256(text.encode("utf-8")).hexdigest()
28
+
29
+ def observe(self, text: str, *, tags: Iterable[str] | None = None) -> PerceptionInput:
30
+ normalized_tags = sorted(set(self._default_tags + list(tags or [])))
31
+ fingerprint = self._fingerprint(text)
32
+ return PerceptionInput(text=text.strip(), tags=normalized_tags, fingerprint=fingerprint)
33
+
34
+
35
+ __all__ = ["PerceptionLayer", "PerceptionInput"]
blux_ca/core/reflection.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Reflection layer producing why-chains."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Iterable, List
7
+
8
+
9
+ @dataclass
10
+ class ReflectionInsight:
11
+ """Structured representation of a reflection cycle."""
12
+
13
+ summary: str
14
+ chain: List[str]
15
+
16
+
17
+ class ReflectionEngine:
18
+ """Produces recursive why-chains to explain a decision."""
19
+
20
+ def __init__(self, *, depth: int = 3) -> None:
21
+ self.depth = max(1, depth)
22
+
23
+ def reflect(self, prompt: str, *, seeds: Iterable[str] | None = None) -> ReflectionInsight:
24
+ chain = list(seeds or [])
25
+ current_reason = prompt.strip()
26
+ for _ in range(self.depth):
27
+ chain.append(current_reason)
28
+ current_reason = f"Because {current_reason.lower()}"
29
+ summary = chain[-1] if chain else "No reflection available."
30
+ return ReflectionInsight(summary=summary, chain=chain)
31
+
32
+
33
+ __all__ = ["ReflectionEngine", "ReflectionInsight"]
blux_ca/telemetry.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Lightweight telemetry helper for BLUX-cA."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ from datetime import datetime, timezone
8
+ from pathlib import Path
9
+ from typing import Any, Dict
10
+
11
+ TELEMETRY_ENV = "BLUX_CA_TELEMETRY"
12
+ DEFAULT_TELEMETRY_PATH = Path.home() / ".config" / "blux-ca" / "telemetry.jsonl"
13
+
14
+
15
+ def _is_enabled() -> bool:
16
+ return os.environ.get(TELEMETRY_ENV, "on").lower() not in {"0", "off", "false"}
17
+
18
+
19
+ def emit(event: str, payload: Dict[str, Any] | None = None) -> None:
20
+ """Record a telemetry event when telemetry is enabled."""
21
+
22
+ if not _is_enabled():
23
+ return
24
+
25
+ record = {
26
+ "timestamp": datetime.now(timezone.utc).isoformat(),
27
+ "event": event,
28
+ "payload": payload or {},
29
+ }
30
+
31
+ path = DEFAULT_TELEMETRY_PATH
32
+ path.parent.mkdir(parents=True, exist_ok=True)
33
+ with path.open("a", encoding="utf-8") as handle:
34
+ handle.write(json.dumps(record, ensure_ascii=False) + "\n")
35
+
36
+
37
+ __all__ = ["emit"]
docs/ARCHITECTURE.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # ARCHITECTURE
2
+
3
+ This document outlines the architecture aspects of the BLUX-cA module.
docs/CONFIGURATION.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # CONFIGURATION
2
+
3
+ This document outlines the configuration aspects of the BLUX-cA module.
docs/CONSTITUTION.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # CONSTITUTION
2
+
3
+ This document outlines the constitution aspects of the BLUX-cA module.
docs/DISCERNMENT.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # DISCERNMENT
2
+
3
+ This document outlines the discernment aspects of the BLUX-cA module.
docs/ETHICS_ENGINE.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # ETHICS ENGINE
2
+
3
+ This document outlines the ethics_engine aspects of the BLUX-cA module.
docs/INSTALL.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # INSTALL
2
+
3
+ This document outlines the install aspects of the BLUX-cA module.
docs/INTEGRATIONS.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # INTEGRATIONS
2
+
3
+ This document outlines the integrations aspects of the BLUX-cA module.
docs/INTERVENTIONS.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # INTERVENTIONS
2
+
3
+ This document outlines the interventions aspects of the BLUX-cA module.
docs/OPERATIONS.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # OPERATIONS
2
+
3
+ This document outlines the operations aspects of the BLUX-cA module.
docs/PRIVACY.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # PRIVACY
2
+
3
+ This document outlines the privacy aspects of the BLUX-cA module.
docs/ROADMAP.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # ROADMAP
2
+
3
+ This document outlines the roadmap aspects of the BLUX-cA module.
docs/SECURITY.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # SECURITY
2
+
3
+ This document outlines the security aspects of the BLUX-cA module.
docs/TROUBLESHOOTING.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # TROUBLESHOOTING
2
+
3
+ This document outlines the troubleshooting aspects of the BLUX-cA module.
docs/VISION.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # VISION
2
+
3
+ This document outlines the vision aspects of the BLUX-cA module.
docs/index.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # BLUX-cA Conscious Agent Core
2
+
3
+ Welcome to the BLUX-cA documentation set.
mkdocs.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ site_name: BLUX-cA
2
+ site_description: Enterprise Conscious Agent Core
3
+ nav:
4
+ - Home: index.md
5
+ - Vision: VISION.md
6
+ - Architecture: ARCHITECTURE.md
7
+ - Constitution: CONSTITUTION.md
8
+ - Ethics Engine: ETHICS_ENGINE.md
9
+ - Discernment: DISCERNMENT.md
10
+ - Interventions: INTERVENTIONS.md
11
+ - Integrations: INTEGRATIONS.md
12
+ - Install: INSTALL.md
13
+ - Operations: OPERATIONS.md
14
+ - Security: SECURITY.md
15
+ - Privacy: PRIVACY.md
16
+ - Configuration: CONFIGURATION.md
17
+ - Troubleshooting: TROUBLESHOOTING.md
18
+ - Roadmap: ROADMAP.md
19
+ theme:
20
+ name: material
21
+ features:
22
+ - content.code.copy
pyproject.toml ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools>=64", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "blux-ca"
7
+ version = "0.1.0"
8
+ description = "BLUX Conscious Agent core"
9
+ authors = [{name = "BLUX", email = "ca@blux.ai"}]
10
+ readme = "README.md"
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ "typer[all]",
14
+ "fastapi",
15
+ "pydantic>=1.10,<2.0",
16
+ "PyYAML",
17
+ ]
18
+
19
+ [project.optional-dependencies]
20
+ dev = ["pytest", "ruff", "mypy"]
21
+
22
+ [project.entry-points."blux.plugins"]
23
+ ca = "blux_ca.cli:get_app"
24
+
25
+ [tool.pytest.ini_options]
26
+ pythonpath = ["."]
27
+ addopts = "-q"
scripts/export_audit_json.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Export audit logs into a merged JSON document."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+
8
+ from blux_ca.core.audit import AuditLog
9
+
10
+
11
+ def export(output: Path = Path("audit_export.json")) -> None:
12
+ audit = AuditLog()
13
+ if not audit.path.exists():
14
+ print("No audit log available.")
15
+ return
16
+ lines = [json.loads(line) for line in audit.path.read_text(encoding="utf-8").splitlines() if line]
17
+ output.write_text(json.dumps(lines, indent=2, ensure_ascii=False), encoding="utf-8")
18
+ print(f"Exported {len(lines)} records to {output}")
19
+
20
+
21
+ if __name__ == "__main__":
22
+ export()
scripts/gen_filetree.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generate repository file tree summary."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from pathlib import Path
7
+
8
+
9
+ def generate(root: str = ".") -> str:
10
+ lines: list[str] = []
11
+ for current_root, dirs, files in os.walk(root):
12
+ level = Path(current_root).relative_to(root).parts
13
+ indent = " " * len(level)
14
+ for name in sorted(files):
15
+ lines.append(f"{indent}{name}")
16
+ return "\n".join(lines)
17
+
18
+
19
+ if __name__ == "__main__":
20
+ print(generate())
scripts/run_reflection_test.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Execute a simple reflection self-test."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from blux_ca.core.reflection import ReflectionEngine
6
+
7
+
8
+ def run(prompt: str = "Why integrity matters?") -> None:
9
+ engine = ReflectionEngine()
10
+ insight = engine.reflect(prompt)
11
+ for idx, reason in enumerate(insight.chain, start=1):
12
+ print(f"{idx}. {reason}")
13
+
14
+
15
+ if __name__ == "__main__":
16
+ run()
scripts/update_readme_filetree.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Update README with generated file tree."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ from gen_filetree import generate
8
+
9
+
10
+ README_MARKER = "<!-- FILETREE -->"
11
+
12
+
13
+ def update_readme(readme_path: Path = Path("README.md")) -> None:
14
+ content = readme_path.read_text(encoding="utf-8")
15
+ tree = generate()
16
+ snippet = f"{README_MARKER}\n\n````\n{tree}\n````"
17
+ readme_path.write_text(snippet, encoding="utf-8")
18
+
19
+
20
+ if __name__ == "__main__":
21
+ update_readme()
scripts/validate_constitution.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Validate constitution logic with sample cases."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from blux_ca.core.constitution import ConstitutionEngine
6
+ from blux_ca.core.discernment import DiscernmentCompass
7
+
8
+
9
+ CASES = {
10
+ "help": "I need help staying accountable.",
11
+ "indulger": "I love to indulge in bad habits.",
12
+ "harm": "I want to hurt them.",
13
+ }
14
+
15
+
16
+ def main() -> None:
17
+ compass = DiscernmentCompass()
18
+ engine = ConstitutionEngine()
19
+ for name, text in CASES.items():
20
+ decision = engine.evaluate(insights=[text], intent=compass.classify(text).intent.value)
21
+ print(name, decision)
22
+
23
+
24
+ if __name__ == "__main__":
25
+ main()
tests/ca/test_audit.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ from blux_ca.core.audit import AuditLog
4
+
5
+
6
+ def test_audit_appends(tmp_path: Path):
7
+ audit = AuditLog(path=tmp_path / "audit.jsonl")
8
+ record = audit.create_record(input_hash="abc", verdict="allow", doctrine_refs=["law"], rationale="ok")
9
+ audit.append(record)
10
+ contents = (tmp_path / "audit.jsonl").read_text(encoding="utf-8").strip()
11
+ assert "allow" in contents
tests/ca/test_constitution.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from blux_ca.core.constitution import ConstitutionEngine
2
+
3
+
4
+ def test_constitution_denies_harm():
5
+ engine = ConstitutionEngine()
6
+ verdict = engine.evaluate(insights=["danger"], intent="harm")
7
+ assert verdict.decision == "deny"
8
+ assert verdict.score == 0.0
9
+
10
+
11
+ def test_constitution_allows_struggler():
12
+ engine = ConstitutionEngine()
13
+ verdict = engine.evaluate(insights=["trying", "learning"], intent="struggler")
14
+ assert verdict.decision == "allow"
15
+ assert verdict.score > 0
tests/ca/test_discernment.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from blux_ca.core.discernment import DiscernmentCompass, IntentType
2
+
3
+
4
+ def test_discernment_detects_harm():
5
+ compass = DiscernmentCompass()
6
+ decision = compass.classify("I want to hurt them")
7
+ assert decision.intent is IntentType.HARM
8
+
9
+
10
+ def test_discernment_defaults_to_struggler():
11
+ compass = DiscernmentCompass()
12
+ decision = compass.classify("I am trying to do better")
13
+ assert decision.intent is IntentType.STRUGGLER
tests/ca/test_interventions.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from blux_ca.core import intervention
2
+
3
+
4
+ def test_intervention_mirror():
5
+ result = intervention.mirror("you are valued")
6
+ assert result["strategy"] == "mirror"
7
+ assert "you are valued" in result["response"]
8
+
9
+
10
+ def test_intervention_layered_truth():
11
+ result = intervention.layered_truth("integrity first")
12
+ assert result["strategy"] == "layered_truth"