Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/migration/import-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Empty placeholder directories (no tracked source): `packages/ts-*`, top-level `e

| Repository | Verified source SHA in this clone? | Destination claimed historically | Status | Notes |
|------------|-------------------------------------|----------------------------------|--------|-------|
| TS-Core | Not verified here | `packages/ts-core`, `packages/ts-kernel` | **INSPECTED** / **PLANNED** | Empty `packages/`; kernel is native monorepo `core/kernel` |
| TS-Core | `3ef48ad00efef8659ad0981d71de509a9827f584` | `src/thinking_system/core/typed_tension/` | **PARTIALLY_IMPORTED** | Domain-neutral typed tension kernel imported with its focused test and example; legacy Python application layers, Rust acceleration, CLI, Z3, Grok, UI, and Kernel Wave 12 surfaces remain unimported |
| cig-ts-engine | Not verified here | `packages/ts-graph` | **INSPECTED** / **PLANNED** | Graph lives in `core/graph` |
| TS-Benchmarks | Not verified here | `benchmarks/` | **PLANNED** | `benchmarks/suites` empty |
| ts-chat-language | Not verified here | `packages/ts-language` | **INSPECTED** / **PLANNED** | TSLC-like code in `core/language/tslc.py` is in-tree monorepo code; full satellite port not evidenced |
Expand Down
57 changes: 57 additions & 0 deletions docs/migration/sources/TS-Core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# TS-Core consolidation record

## Source

- Repository: `BoggersTheFish/TS-Core`
- Source branch: `master`
- Source commit: `3ef48ad00efef8659ad0981d71de509a9827f584`
- Licence: MIT

## Imported surface

The domain-neutral typed tension kernel from the satellite's `ts_core/`
package was imported into:

`src/thinking_system/core/typed_tension/`

The corresponding focused test and generic demonstration were imported into:

- `tests/test_ts_core_typed_tension.py`
- `examples/typed_tension_kernel_demo.py`

## Adaptation

Internal package source was copied without architectural rewriting.

Test and demonstration imports were changed from:

`ts_core`

to:

`thinking_system.core.typed_tension`

## Deliberately not imported

The following TS-Core surfaces remain outside the monorepo pending separate
classification:

- legacy `src/python/` application and narrative layers
- TUI and Streamlit interfaces
- Grok/xAI integration
- Z3 toy alignment tooling
- training-data utilities
- Docker and Ollama configuration
- Rust/PyO3 acceleration
- Kernel Wave 12 and Daily Spin application modes
- legacy `tscore` and `tscore-daily` commands

These are not represented as consolidated by this import.

## Current status

**PARTIALLY_IMPORTED**

TS-Core must not be archived solely because of this import. Remaining unique
surfaces must be classified as importable, obsolete, historical, or independent
before an archival decision.
86 changes: 86 additions & 0 deletions examples/typed_tension_kernel_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""Generic typed tension kernel demo.

This example intentionally avoids reasoning-specific relations. It shows a
channel that detects an unbalanced resource edge and resolves it by adding a
traceable balancing edge.
"""

from __future__ import annotations

import json
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))

from thinking_system.core.typed_tension import (
ChannelResult,
Edge,
GraphState,
Node,
ResolverEvent,
TensionChannel,
TypedTensionRuntime,
)


class BalanceChannel(TensionChannel):
name = "generic_balance"
version = "0.1.0"

def activate(self, graph: GraphState, context: dict) -> bool:
return any(edge.relation == "requires" for edge in graph.edges)

def measure(self, graph: GraphState, context: dict) -> ChannelResult:
missing = [
edge
for edge in graph.edges
if edge.relation == "requires"
and not graph.has_edge(edge.target, edge.source, "stabilizes")
]
tension = 1.0 if missing else 0.0
return ChannelResult(
channel=self.name,
activated=bool(missing),
initial_tension=tension,
final_tension=tension,
evidence=[f"{edge.source}->{edge.target}" for edge in missing],
details={"missing_stabilizers": len(missing)},
)

def resolve(self, graph: GraphState, context: dict) -> ResolverEvent:
for edge in list(graph.edges):
if edge.relation == "requires" and not graph.has_edge(
edge.target, edge.source, "stabilizes"
):
graph.add_edge(Edge(edge.target, edge.source, "stabilizes", weight=0.5))
return ResolverEvent(
channel=self.name,
action="added_stabilizing_edge",
status="resolved",
target=f"{edge.target}->{edge.source}",
tension_delta=-1.0,
evidence=[f"{edge.source}->{edge.target}"],
)
return ResolverEvent(channel=self.name, action="no_op", status="settled")


def main() -> None:
graph = GraphState()
graph.add_node(Node("process", activation=0.8, stability=0.6))
graph.add_node(Node("resource", activation=0.5, stability=0.9))
graph.add_edge(Edge("process", "resource", "requires"))
trace = TypedTensionRuntime([BalanceChannel()]).run(graph)
print(
json.dumps(
{"graph": graph.to_dict(), "trace": trace.to_dict()},
indent=2,
sort_keys=True,
)
)


if __name__ == "__main__":
main()
38 changes: 38 additions & 0 deletions src/thinking_system/core/typed_tension/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Typed tension kernel surface for TS-Core."""

from .channels import TensionChannel
from .evolve import EvolveHook, apply_evolve_hooks
from .graph import GraphState
from .receipts import write_receipt
from .runtime import TypedTensionRuntime
from .schema import validate_runtime_trace
from .types import (
ActivationState,
ChannelResult,
Edge,
Node,
Receipt,
ResolverEvent,
RuntimeTrace,
to_jsonable,
utc_now,
)

__all__ = [
"ActivationState",
"ChannelResult",
"Edge",
"EvolveHook",
"GraphState",
"Node",
"Receipt",
"ResolverEvent",
"RuntimeTrace",
"TensionChannel",
"TypedTensionRuntime",
"apply_evolve_hooks",
"to_jsonable",
"utc_now",
"validate_runtime_trace",
"write_receipt",
]
31 changes: 31 additions & 0 deletions src/thinking_system/core/typed_tension/channels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Typed tension channel interface."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any

from .graph import GraphState
from .types import ChannelResult, ResolverEvent


class TensionChannel(ABC):
"""A typed operational route for measuring and resolving one tension kind."""

name = "unnamed"
version = "0.1.0"

@abstractmethod
def activate(self, graph: GraphState, context: dict[str, Any]) -> bool:
"""Return true when this channel has work to measure or resolve."""

@abstractmethod
def measure(self, graph: GraphState, context: dict[str, Any]) -> ChannelResult:
"""Measure this channel's unresolved pressure."""

@abstractmethod
def resolve(self, graph: GraphState, context: dict[str, Any]) -> ResolverEvent:
"""Apply this channel's resolver operation to the graph or context."""

def serialize(self) -> dict[str, Any]:
return {"name": self.name, "version": self.version}
20 changes: 20 additions & 0 deletions src/thinking_system/core/typed_tension/evolve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Break/Evolve hook protocol for typed tension runtimes."""

from __future__ import annotations

from typing import Protocol

from .graph import GraphState
from .types import ResolverEvent


class EvolveHook(Protocol):
def __call__(self, graph: GraphState, event: ResolverEvent) -> None: ...


def apply_evolve_hooks(
graph: GraphState, events: list[ResolverEvent], hooks: list[EvolveHook]
) -> None:
for event in events:
for hook in hooks:
hook(graph, event)
96 changes: 96 additions & 0 deletions src/thinking_system/core/typed_tension/graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""Domain-neutral graph state for typed tension runtimes."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Iterable

from .types import Edge, Node, to_jsonable


@dataclass
class GraphState:
nodes: dict[str, Node] = field(default_factory=dict)
edges: list[Edge] = field(default_factory=list)
metadata: dict[str, Any] = field(default_factory=dict)

def add_node(self, node: Node) -> None:
self.nodes[node.node_id] = node

def add_edge(self, edge: Edge) -> None:
if edge.source not in self.nodes:
raise ValueError(f"unknown edge source: {edge.source}")
if edge.target not in self.nodes:
raise ValueError(f"unknown edge target: {edge.target}")
self.edges.append(edge)

def outgoing(self, node_id: str, relation: str | None = None) -> list[Edge]:
return [
edge
for edge in self.edges
if edge.source == node_id
and (relation is None or edge.relation == relation)
]

def incoming(self, node_id: str, relation: str | None = None) -> list[Edge]:
return [
edge
for edge in self.edges
if edge.target == node_id
and (relation is None or edge.relation == relation)
]

def has_edge(self, source: str, target: str, relation: str | None = None) -> bool:
return any(
edge.source == source
and edge.target == target
and (relation is None or edge.relation == relation)
for edge in self.edges
)

def edge_keys(self) -> set[tuple[str, str, str]]:
return {(edge.source, edge.target, edge.relation) for edge in self.edges}

def extend(self, nodes: Iterable[Node] = (), edges: Iterable[Edge] = ()) -> None:
for node in nodes:
self.add_node(node)
for edge in edges:
self.add_edge(edge)

def to_dict(self) -> dict[str, Any]:
return {
"nodes": {
node_id: node.to_dict() for node_id, node in sorted(self.nodes.items())
},
"edges": [edge.to_dict() for edge in self.edges],
"metadata": to_jsonable(self.metadata),
}

@classmethod
def from_dict(cls, payload: dict[str, Any]) -> "GraphState":
graph = cls(metadata=dict(payload.get("metadata") or {}))
raw_nodes = payload.get("nodes") or {}
if isinstance(raw_nodes, dict):
raw_nodes = raw_nodes.values()
for item in raw_nodes:
graph.add_node(
Node(
node_id=str(item.get("node_id") or item.get("id")),
kind=str(item.get("kind", "state")),
activation=float(item.get("activation", 0.0)),
stability=float(item.get("stability", 1.0)),
data=dict(item.get("data") or {}),
)
)
for item in payload.get("edges") or []:
graph.add_edge(
Edge(
source=str(item.get("source") or item.get("from")),
target=str(item.get("target") or item.get("to")),
relation=str(item.get("relation", "constraint")),
weight=float(item.get("weight", 1.0)),
directed=bool(item.get("directed", True)),
data=dict(item.get("data") or {}),
)
)
return graph
17 changes: 17 additions & 0 deletions src/thinking_system/core/typed_tension/receipts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Receipt helpers for TS artifacts."""

from __future__ import annotations

import json
from pathlib import Path

from .types import Receipt


def write_receipt(receipt: Receipt, path: str | Path) -> Path:
target = Path(path)
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(
json.dumps(receipt.to_dict(), indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
return target
Loading
Loading