Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
88ad120
test(ddd): forbid LineageWeave-owned provider boundary
seonghobae Sep 1, 2026
31e0b8c
refactor(ddd): remove LineageWeave-owned orchestrator bootstrap
seonghobae Sep 1, 2026
49da27d
refactor(ddd): remove LineageWeave-owned model agent config
seonghobae Sep 1, 2026
e3a954b
refactor(ddd): remove embedded orchestrator image
seonghobae Sep 1, 2026
78f0945
refactor(ddd): keep provider config outside LineageWeave
seonghobae Sep 1, 2026
5e17f36
refactor(ddd): consume external contextual-orchestrator
seonghobae Sep 1, 2026
5b99ba0
fix(llm): require contextual-orchestrator consumer contract
seonghobae Sep 1, 2026
4a0a2c4
fix(llm): remove provider gateway fallback from estimation
seonghobae Sep 1, 2026
3530fa1
test(ddd): retire embedded orchestrator bootstrap tests
seonghobae Sep 1, 2026
308e8e3
docs(adr): assign provider runtime to contextual-orchestrator
seonghobae Sep 1, 2026
8779632
docs(changelog): record orchestrator ownership repair
seonghobae Sep 1, 2026
7ff72bd
test(ddd): reject direct provider SDK imports
seonghobae Sep 1, 2026
736ff3e
refactor(ddd): stop loading provider env into Compose
seonghobae Sep 1, 2026
dc9128b
test(ddd): keep provider env out of Compose launcher
seonghobae Sep 1, 2026
b2b8812
docs(ddd): align ecosystem ownership with canonical services
seonghobae Sep 1, 2026
eac6674
docs(ddd): define LineageWeave bounded-context map
seonghobae Sep 1, 2026
9318c4a
docs(ddd): define measurement ubiquitous language
seonghobae Sep 1, 2026
ccd626f
test(ddd): lock measurement ownership vocabulary
seonghobae Sep 1, 2026
2368b90
fix(ddd): align repository guidance with owner boundary
Sep 1, 2026
379c44b
docs(ddd): correct historical vision boundary note
seonghobae Sep 1, 2026
3295d8f
chore(ddd): restack orchestrator boundary on live main
seonghobae Sep 1, 2026
668e053
chore(ddd): restack orchestrator boundary on protected main
seonghobae Sep 3, 2026
47ebcee
chore(ddd): converge orchestrator boundary with protected main
seonghobae Sep 3, 2026
1f70eb5
test(ci): require current draft admission contract
seonghobae Sep 4, 2026
b008a4f
fix(ci): adopt protected Tests draft admission
seonghobae Sep 4, 2026
3780bfa
fix(ci): adopt protected PROV-O draft admission
seonghobae Sep 4, 2026
6dbf089
fix(ci): adopt protected Ontology Pages draft admission
seonghobae Sep 4, 2026
e571128
chore(stack): converge contextual-orchestrator boundary onto protecte…
seonghobae Sep 4, 2026
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
32 changes: 10 additions & 22 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Copy to .env to override. Every value below already has a working
# default baked into docker-compose.yml (see ${VAR:-default} references) --
# `docker compose up` succeeds from a clean checkout with no .env file at
# all for the default profile. The optional MCP profile requires measured
# quota inputs below. Other defaults are throwaway local-dev-only credentials, not
# production secrets; see docs/adr/0001-demo-identity-and-data-boundary.md.
# Copy to .env to override. Every value below is either a working local-dev
# default or an explicitly optional integration setting. The optional MCP
# profile requires measured quota inputs below. Local defaults are throwaway
# development credentials, not production secrets; see
# docs/adr/0001-demo-identity-and-data-boundary.md.

# Host ports deliberately avoid each service's own default (5432, 6379,
# 8080) -- a dev machine commonly already runs its own Postgres/Redis/local
Expand Down Expand Up @@ -34,24 +33,14 @@ MCP_ALLOWED_ORIGINS=
MCP_RATE_LIMIT_REQUESTS=
MCP_RATE_LIMIT_WINDOW_SECONDS=

# Optional. Empty = every LLM/vision channel is unavailable (Null client,
# dropped and renormalized -- never a placeholder score). Point these at a
# running contextual-orchestrator to turn the channels on.
# Optional contextual-orchestrator consumer contract. Empty keeps every
# LLM/vision channel unavailable (Null client, dropped and renormalized -- never
# a placeholder score). Provider endpoints, provider credentials, model-agent
# configuration, discovery and fallback belong to the separately deployed
# contextual-orchestrator and are intentionally not LineageWeave settings.
ORCHESTRATOR_BASE_URL=
ORCHESTRATOR_API_KEY=

# GitHub workflows inject the canonical provider names from masked secrets.
# Non-GitHub Compose runs also accept the operator's ~/.env compatibility
# names below; docker-compose maps them to the canonical names without
# exposing them to the frontend or committing them.
# Canonical provider endpoint for contextual-orchestrator.
LLM_GATEWAY_API_URL=
# Compatibility alias; LLM_GATEWAY_API_URL wins when both are set.
LLM_GATEWAY_URL=
LLM_GATEWAY_API_KEY=
LLM_GATEWAY_EMBEDDING_MODEL=
LLM_API_GATEWAY=
LLM_API_KEY=
CALDAV_BASE_URL=
# Optional Naruon calendar projection consume (ADR 0203 step 2 / #336).
# Empty keeps observed events fail-closed. Never put an end-user bearer here.
Expand All @@ -64,4 +53,3 @@ RANKWEAVE_DISABLED=
# Empty keeps truncated-without-cursor. Do not reuse OIDC or orchestrator secrets.
# Must be at least 32 bytes when source paging is enabled.
ONTOLOGY_SOURCE_CURSOR_SECRET=
CONTEXTUAL_ORCHESTRATOR_ALLOWED_PROVIDER_HOSTS=
22 changes: 12 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ does it (`gh repo list ContextualWisdomLab`).
- All LLM, VISION, embedding, and structured-output traffic crosses
`contextual-orchestrator`. This repository never calls a provider API
directly and never uses a monkey patch to repair an upstream capability.
- Compose loads provider transport credentials from `~/.env` into the
orchestrator service. Never copy those values into this repository, an
image, a fixture, a log, or a committed agent configuration.
- LineageWeave accepts only the deployed orchestrator's
`ORCHESTRATOR_BASE_URL` and `ORCHESTRATOR_API_KEY`. Provider transport
credentials stay in the contextual-orchestrator deployment; never copy them
into this repository, an image, a fixture, a log, or agent configuration.
- `LLM_GATEWAY_MODEL`, `VISION_MODEL`, and provider-specific model selectors
are not LineageWeave configuration. Model discovery, capability selection,
reasoning effort, protocol negotiation, and VISION selection belong to
Expand All @@ -98,16 +99,16 @@ evidence for model quality, routing, reasoning effort, agent count, synthesis,
or VISION selection. If the papers do not support a policy, leave it
undecided or unavailable rather than inventing a heuristic.

The canonical provider credentials are runtime-only from `~/.env` through the
Compose `env_file` boundary. Never copy `~/.env` into the repository or image,
print its values, or persist them. Do not add `LLM_GATEWAY_MODEL`; the upstream
Provider credentials remain runtime-only in the contextual-orchestrator
deployment. Never copy them into this repository or image, print them, or
persist them. Do not add `LLM_GATEWAY_MODEL`; the upstream
contextual-orchestrator owns model discovery and selection.

## LLM and VISION boundary

- Use `LLM_GATEWAY_API_KEY` and `LLM_GATEWAY_API_URL` from the user's `~/.env`
at runtime. Keep compatibility aliases only at the process boundary; do not
introduce a second credential source or a repository-local secret.
- Use `ORCHESTRATOR_BASE_URL` and `ORCHESTRATOR_API_KEY` to consume the
deployed contextual-orchestrator. Do not introduce a provider credential
source, compatibility alias, or repository-local secret.
- Every LLM and VISION operation goes through contextual-orchestrator. This
includes adjudication, summaries, Keyman/entity extraction, post chat,
paragraph structure, image region recognition, OCR, image descriptions, and
Expand All @@ -128,7 +129,8 @@ contextual-orchestrator owns model discovery and selection.
instruction roles at the orchestrator boundary. The orchestrator owns the
translation and provider capability handling; do not fork prompts per
transport in this repository.
- Treat `LLM_GATEWAY_API_URL` as an opaque OpenAI-compatible gateway endpoint.
- Treat `ORCHESTRATOR_BASE_URL` as the deployed contextual-orchestrator
endpoint.
Do not add MLX/local-server URL schemes, port lists, local defaults,
chat-template injection, or vendor-specific bootstrap exceptions in
LineageWeave. Provider-specific capability translation belongs upstream.
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.d/2.29.0-contextual-orchestrator-owner-boundary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Changed

- LineageWeave now consumes contextual-orchestrator only through `ORCHESTRATOR_BASE_URL` and `ORCHESTRATOR_API_KEY`; provider endpoints, provider credentials, model-agent bootstrap, discovery and fallback remain owned by contextual-orchestrator.
- The default Compose stack no longer embeds or starts a LineageWeave-owned contextual-orchestrator runtime. Missing orchestration configuration leaves model-backed channels unavailable instead of falling back to a provider gateway.
- Added architectural fitness coverage that rejects provider-boundary configuration and an embedded orchestrator runtime in LineageWeave.
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.PHONY: up down logs smoke seed ps load-http load-mcp

# Keep provider credentials outside the repository. Compose interpolation must
# read the same home env file as the orchestrator container's env_file.
COMPOSE := docker compose --env-file "$$HOME/.env"
# Compose reads the repository-local .env convention when present. Provider
# credentials belong to the separately deployed contextual-orchestrator and
# are not an input to the LineageWeave stack.
COMPOSE := docker compose

up:
$(COMPOSE) up -d
Expand Down
65 changes: 38 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,29 @@ retain the supporting bibliography and aggregate evidence.

## How it fits with the rest of the ecosystem

LineageWeave is a thin orchestration/BI layer. It does not do its own
psychometric or statistical estimation -- that stays inside
[TEPP](https://github.com/ContextualWisdomLab/TEPP) (Rust), consumed here
purely through TEPP's own published wire contract
(`lineageweave/tepp_client.py`, `AnalysisRunRequest` v1), never by reading
TEPP's tables or reimplementing TEPP's model. See
[ARCHITECTURE.md](ARCHITECTURE.md) for why the "computation layer must be
Rust + GPU/CPU multithreaded" rule that applies to TEPP does not apply to
this repo.

The optional LLM-adjudication channel calls
LineageWeave owns lineage product policy, source-evidence binding, instrument
and rubric administration, pilot lifecycle, interpretation, and audit. It does
not own reusable model routing or reusable psychometric numerical kernels.

Every production LLM-backed capability calls
[contextual-orchestrator](https://github.com/ContextualWisdomLab/contextual-orchestrator)
(`lineageweave/adjudication_client.py`). Tree assembly reuses
through its published consumer contract. Provider/model discovery, routing,
fallback, structured-output compatibility, multi-agent orchestration,
reasoning-effort allocation, usage/cost provenance, and provider credentials
stay in contextual-orchestrator. LineageWeave receives versioned observations
and provenance; it never treats an LLM judgment as truth and never falls back
to a provider endpoint directly. See [ADR 0300](docs/adr/0300-contextual-orchestrator-owner-boundary.md).

Reusable psychometric numerical/statistical kernels and their recovery
evidence belong to
[fast-mlsirm](https://github.com/ContextualWisdomLab/fast-mlsirm). Temporal,
event, multilevel, cross-classified, and multiple-membership measurement
semantics belong to [TEPP](https://github.com/ContextualWisdomLab/TEPP),
consumed through TEPP's published wire contract
(`lineageweave/tepp_client.py`, `AnalysisRunRequest` v1). LineageWeave does
not read either owner's tables or copy their model implementations.

Tree assembly reuses
[ThreadWeave](https://github.com/ContextualWisdomLab/ThreadWeave) (JWZ
message threading) and channel fusion reuses
[RankWeave](https://github.com/ContextualWisdomLab/RankWeave) (weighted
Expand Down Expand Up @@ -80,14 +90,15 @@ Map your records into `lineageweave.Record` (see `lineageweave/models.py`
for the field docs) and call `reconstruct()` directly -- nothing in this
package assumes any particular source schema.

To turn on the embedding or LLM channels, pass a real client instead of the
`Null*` defaults:
To turn on the embedding or LLM channels, use clients backed by a running
contextual-orchestrator. A provider endpoint or provider credential is not a
LineageWeave integration contract:

```python
from lineageweave import reconstruct
from lineageweave.adjudication_client import ContextualOrchestratorAdjudicationClient

llm = ContextualOrchestratorAdjudicationClient(base_url="http://localhost:8000", api_key="...")
llm = ContextualOrchestratorAdjudicationClient(base_url="https://orchestrator.example", api_key="...")
trees = reconstruct(my_records, llm=llm)
```

Expand All @@ -107,21 +118,20 @@ infrastructure -- PostgreSQL, Valkey, and a real Keycloak OIDC realm seeded
with synthetic demo accounts -- runs via Docker Compose:

```bash
make up # docker compose up -d: postgres, valkey, keycloak
make up # docker compose up -d: postgres, valkey, keycloak, backend, frontend
make smoke # real login as the synthetic demo user + JWT signature
# verification against Keycloak's live JWKS -- proves the
# OIDC round-trip actually works, not just that containers
# started
make down
```

Outside GitHub, `make up` reads `~/.env` through Compose's `--env-file`.
Configure the contextual-orchestrator provider there with
`LLM_GATEWAY_API_URL` and `LLM_GATEWAY_API_KEY`; the key is never committed or
printed. `LLM_GATEWAY_URL`, `LLM_API_GATEWAY`, and `LLM_API_KEY` remain
compatibility aliases only. `ORCHESTRATOR_BASE_URL` and
`ORCHESTRATOR_API_KEY` are separate, internal
LineageWeave-to-orchestrator settings.
The local stack does not build or start contextual-orchestrator and does not
load provider credentials. If model-backed channels are required, deploy or
reach contextual-orchestrator through its canonical owner path and set only
`ORCHESTRATOR_BASE_URL` and `ORCHESTRATOR_API_KEY` in LineageWeave's local
`.env`. Leaving either empty keeps model-backed channels unavailable/fail-closed;
there is no direct-provider fallback.

Postgres and Keycloak are built (`docker/postgres-init/`, `docker/keycloak/`)
rather than bind-mounted, so the keycloak database's init script and the
Expand Down Expand Up @@ -182,7 +192,7 @@ path against a live Keycloak + throwaway Postgres database, including
that a private post scoped to a *different* corporate entity is excluded
from the list and 403s on direct fetch.

`frontend/` (React + Vite + TypeScript, `docker compose`'s fourth service)
`frontend/` (React + Vite + TypeScript, `docker compose`'s frontend service)
is a real client, not mocked or static: `react-oidc-context` drives an
actual Authorization Code redirect through Keycloak, the home page
draws the reconstructed lineage as a git-branch SVG (`GET /api/lineage`;
Expand Down Expand Up @@ -214,9 +224,10 @@ the *real* OIDC round-trip is what `scripts/smoke_test_oidc.py` and
## Modular / standalone

This repo runs standalone (own server, own tests, own CI) and is equally
usable as a library module (`import lineageweave`) inside a larger service
-- no global state, no required environment variables, every external
dependency (embeddings, LLM adjudication, TEPP) is injected, not hardcoded.
usable as a library module (`import lineageweave`) inside a larger service.
Deterministic reconstruction remains available without any model service;
model-backed channels are injected through contextual-orchestrator's consumer
contract and fail closed when that contract is unavailable.

## License

Expand Down
58 changes: 7 additions & 51 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,45 +97,6 @@ services:
postgres:
condition: service_healthy

orchestrator:
# Consume the paper-grounded orchestration service from main; inference
# remains behind its authenticated OpenAI-compatible boundary.
build:
context: ./docker/contextual-orchestrator
dockerfile: Dockerfile
env_file:
- ${HOME}/.env
environment:
AGENTS_FILE: /app/agents.json
PORT: 8000
CONTEXTUAL_ORCHESTRATOR_TOKEN: ${CONTEXTUAL_ORCHESTRATOR_TOKEN:-${ORCHESTRATOR_API_KEY:-lineageweave-orchestrator-dev-only}}
# Gateway credentials and URL are supplied only by env_file (${HOME}/.env).
# Do not repeat them under environment:, where Compose interpolation can
# overwrite env_file values with an empty host-shell value.
# The upstream default remains 64 KiB for ordinary text APIs. Buyer
# image blocks are base64 data URIs, so the multimodal boundary gets an
# explicit bounded 8 MiB limit rather than an unbounded request size.
CONTEXTUAL_ORCHESTRATOR_MAX_BODY_BYTES: ${CONTEXTUAL_ORCHESTRATOR_MAX_BODY_BYTES:-8388608}
CONTEXTUAL_ORCHESTRATOR_ALLOWED_PROVIDER_HOSTS: ${CONTEXTUAL_ORCHESTRATOR_ALLOWED_PROVIDER_HOSTS:-host.docker.internal}
OTEL_SERVICE_NAME: ${OTEL_ORCHESTRATOR_SERVICE_NAME:-contextual-orchestrator}
# Do not set OTEL_EXPORTER_OTLP_ENDPOINT here. An empty
# ${OTEL_EXPORTER_OTLP_ENDPOINT:-} interpolation would wipe a value from
# env_file (${HOME}/.env). Export stays opt-in from that file or the host.
command: ["python", "/app/start.py"]
ports:
- "${ORCHESTRATOR_PORT:-18000}:8000"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/healthz', timeout=2)"]
interval: 5s
timeout: 3s
retries: 10
# Warm-up window: failures inside start_period do not consume the retry
# budget, so a booting orchestrator that becomes healthy within 50s is
# never counted against retries. A dead service trips the gate at
# ~100s (start_period + 10 x 5s), matching the previous retries: 20
# budget exactly; the win is boot tolerance, not faster dead detection.
start_period: 50s

backend:
build:
context: .
Expand Down Expand Up @@ -167,12 +128,11 @@ services:
VALKEY_URL: redis://valkey:6379/0
OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-lineageweave}
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-}
# Empty by default: every LLM/vision channel stays the Null client
# (dropped, not faked). Set these to a running contextual-orchestrator
# to turn the channels on. Provider credentials use LLM_GATEWAY_API_URL /
# LLM_GATEWAY_API_KEY in the orchestrator's private env file.
ORCHESTRATOR_BASE_URL: ${ORCHESTRATOR_BASE_URL:-http://orchestrator:8000}
ORCHESTRATOR_API_KEY: ${ORCHESTRATOR_API_KEY:-${CONTEXTUAL_ORCHESTRATOR_TOKEN:-lineageweave-orchestrator-dev-only}}
# Empty by default: every LLM/vision channel stays unavailable. Set only
# the published contextual-orchestrator consumer endpoint and bearer to
# enable them. Provider configuration belongs to contextual-orchestrator.
ORCHESTRATOR_BASE_URL: ${ORCHESTRATOR_BASE_URL:-}
ORCHESTRATOR_API_KEY: ${ORCHESTRATOR_API_KEY:-}
SEARXNG_BASE_URL: http://searxng:8080
TEPP_TRANSPORT_URL: ${TEPP_TRANSPORT_URL:-}
TEPP_API_KEY: ${TEPP_API_KEY:-}
Expand All @@ -190,8 +150,6 @@ services:
condition: service_healthy
database_migration:
condition: service_completed_successfully
orchestrator:
condition: service_healthy
keycloak:
condition: service_started
valkey:
Expand Down Expand Up @@ -222,8 +180,8 @@ services:
OIDC_JWKS_URI: ${OIDC_JWKS_URI:-}
OIDC_CLOCK_SKEW_SECONDS: ${OIDC_CLOCK_SKEW_SECONDS:-5}
VALKEY_URL: redis://valkey:6379/0
ORCHESTRATOR_BASE_URL: ${ORCHESTRATOR_BASE_URL:-http://orchestrator:8000}
ORCHESTRATOR_API_KEY: ${ORCHESTRATOR_API_KEY:-${CONTEXTUAL_ORCHESTRATOR_TOKEN:-lineageweave-orchestrator-dev-only}}
ORCHESTRATOR_BASE_URL: ${ORCHESTRATOR_BASE_URL:-}
ORCHESTRATOR_API_KEY: ${ORCHESTRATOR_API_KEY:-}
# Local Keycloak mints this exact fixed audience. Production Keyverse
# deployments configure both values together outside this demo stack.
MCP_RESOURCE_URL: http://localhost:18001/mcp
Expand All @@ -242,8 +200,6 @@ services:
condition: service_healthy
database_migration:
condition: service_completed_successfully
orchestrator:
condition: service_healthy
keycloak:
condition: service_started
valkey:
Expand Down
30 changes: 0 additions & 30 deletions docker/contextual-orchestrator/Dockerfile

This file was deleted.

20 changes: 0 additions & 20 deletions docker/contextual-orchestrator/agents.json

This file was deleted.

Loading
Loading