docs: establish canonical documentation architecture (#1210)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/publish Pipeline failed
This commit was merged in pull request #1210.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
# Tess Administration
|
||||
|
||||
Configure agent/provider identities outside client input. Verify `/health/ready` and provider health before enabling interaction clients. Every interaction request requires an authenticated actor and correlation header; tenant and owner scope are server-derived. Do not log or return service credentials.
|
||||
|
||||
For an incident, preserve correlation IDs, inspect provider status and durable checkpoint/inbox/outbox state, then use the recovery endpoint. Do not retry an ambiguous external effect automatically. Stop operations require an exact one-time approval reference; provisioning or granting a broad admin capability does not replace that check.
|
||||
@@ -0,0 +1,123 @@
|
||||
# Tess Architecture
|
||||
|
||||
## Purpose
|
||||
|
||||
Tess is the Mosaic operator interaction plane. Mos remains the coding/general fleet orchestration authority. Tess receives authorized operator intent, presents fleet/session state, delegates Mos-owned work to Mos, and exposes native Mosaic plus transitional external-agent capabilities through normalized providers.
|
||||
|
||||
## Component Boundaries
|
||||
|
||||
```text
|
||||
Discord plugin ─┐
|
||||
├─ authenticated ingress envelope ─> Mosaic Gateway
|
||||
mosaic tess CLI ┘ │
|
||||
├─ policy/approval/audit
|
||||
├─ Tess durable session service (Pi GPT-5.6 Sol high)
|
||||
├─ AgentRuntimeProvider registry
|
||||
│ ├─ native Pi provider
|
||||
│ ├─ fleet/tmux provider
|
||||
│ ├─ Hermes adapter
|
||||
│ └─ Matrix/native transport provider
|
||||
├─ memory/state/inbox plugins
|
||||
└─ Mos coordination adapter ─> Mos / fleet queue
|
||||
```
|
||||
|
||||
## Core Contract
|
||||
|
||||
`AgentRuntimeProvider` is separate from the existing model-completion `IProviderAdapter`. It normalizes external and native agent runtimes without leaking provider-specific schemas.
|
||||
|
||||
Required operations:
|
||||
|
||||
- `capabilities()` and `health()`
|
||||
- `listSessions(scope)`
|
||||
- `getSessionTree(scope)`
|
||||
- `streamSession(sessionRef, cursor, scope)`
|
||||
- `sendMessage(sessionRef, message, idempotencyKey, scope)`
|
||||
- `attach(sessionRef, mode, scope)` / `detach()`
|
||||
- `terminate(sessionRef, approvalRef, scope)`
|
||||
|
||||
Every call receives an immutable, server-derived actor/tenant/channel scope and correlation ID. Caller-supplied actor IDs are forbidden. Unsupported capabilities fail closed with typed errors.
|
||||
|
||||
### M1 Registry Boundary
|
||||
|
||||
`@mosaicstack/agent` owns the explicit `AgentRuntimeProviderRegistry`; duplicate provider IDs are rejected rather than replaced. Gateway owns `RuntimeProviderService`, which creates a frozen `RuntimeScope` from authenticated `ActorTenantScope` and trusted ingress channel/correlation metadata before every provider call. The service checks the declared provider capability before invoking a side effect and records metadata-only audit events (`providerId`, operation, outcome, actor/tenant/channel, correlation, and resource ID). It never records message bodies, idempotency keys, or approval references.
|
||||
|
||||
Termination is fail-closed: a runtime approval verifier consumes a one-time, exact action binding for the provider, session, actor, tenant, channel, and correlation ID before `terminate` reaches a provider. The verifier reuses the Redis-backed `interaction:command-approval:*` store and its expiry/delete-on-consume semantics; it has no parallel approval store. This internal service introduces no HTTP endpoint; later Discord, CLI, MCP, and provider adapters consume the same gateway boundary.
|
||||
|
||||
## Authority Model
|
||||
|
||||
| Intent | Owner | Tess behavior |
|
||||
| --------------------------------------------------------------------------- | ----------------------- | ---------------------------------------------------------------------- |
|
||||
| Conversation, status, retrieval, safe diagnostics | Tess | Execute within policy |
|
||||
| Code/project decomposition, worker assignment, reviews, merge orchestration | Mos | Create a correlated handoff and observe result |
|
||||
| Destructive, privileged, external/customer-visible action | Human approval + policy | Propose, wait for durable one-time approval, then execute idempotently |
|
||||
| Provider-specific unsupported action | None | Fail closed; never emulate silently |
|
||||
|
||||
### Mos Coordination Boundary
|
||||
|
||||
`@mosaicstack/coord` exposes only the transport-neutral `InteractionCoordinationPort`
|
||||
verbs `handoff`, `observe`, and `result`. Gateway derives the actor, tenant,
|
||||
correlation, and interaction-agent identity from authenticated context plus
|
||||
trusted configuration; callers never provide an orchestration target. It
|
||||
rejects unconfigured identities, self-delegation, target/correlation drift, and
|
||||
cross-tenant handoff reads before an adapter call. No dispatch, assignment,
|
||||
review, merge, or cancellation API exists at this boundary.
|
||||
|
||||
M4 uses a deterministic native in-process queue adapter to prove the handoff →
|
||||
observe → result flow without coupling the contract to tmux. A fleet/tmux
|
||||
adapter is deferred to the M5 live-deployment seam and must implement the same
|
||||
port.
|
||||
|
||||
## Session and State Model
|
||||
|
||||
A Tess session has stable `sessionId`, `tenantId`, `ownerId`, provider/runtime identity, ingress bindings, cursor, checkpoint, inbox/outbox, and idempotency records. Discord and CLI bind to the same authorized session. Ownership is verified server-side on every list/read/attach/send/terminate operation.
|
||||
|
||||
Valkey holds the existing short-lived, one-time command-approval records; PostgreSQL is canonical for durable session bindings, checkpoints, inbox/outbox, and idempotency. Pi session files are replay sources, not cross-agent truth.
|
||||
|
||||
### M2 Durable Recovery
|
||||
|
||||
`@mosaicstack/agent` owns a transport-neutral state machine and `apps/gateway` provides its
|
||||
PostgreSQL adapter. `interaction_sessions` holds immutable identity; inbox/outbox records use a
|
||||
per-session unique idempotency key and transition `pending → processing → processed|delivered`.
|
||||
Checkpoints are immutable history scoped by session and checkpoint ID: the latest checkpoint
|
||||
supports compaction recovery, while a handoff always resolves the exact checkpoint it references.
|
||||
Recovery requeues only interrupted inbox work; an ambiguous `processing` outbox record is preserved
|
||||
until separately authorized reconciliation can establish its external delivery state.
|
||||
|
||||
Provider sends travel through the existing `RuntimeProviderService` with the persisted outbox
|
||||
idempotency key. A normal dispatch claims exactly one outbox record and verifies its stored
|
||||
correlation and channel against the server-derived request scope; it never requeues or drains
|
||||
another live record. Inbox/outbox payloads and checkpoint cursor/summary pass through the existing
|
||||
secret/PII redactor and AES-256-GCM sealing before persistence; decryption occurs only in the
|
||||
scoped gateway repository path, and runtime audit remains metadata-only.
|
||||
|
||||
An external effect cannot share a database transaction. If a process dies after an effect begins
|
||||
but before its terminal outbox transition, automatic recovery does not replay that ambiguous claim.
|
||||
It remains `processing` until separately authorized reconciliation can establish delivery state;
|
||||
completed effects are never redispatched. Operators can therefore restart the gateway/Pi service,
|
||||
reconstruct the session, and resume pending inbox work without relying on process-local state.
|
||||
|
||||
## Transport Strategy
|
||||
|
||||
- **Initial:** fleet/tmux provider, including exact target, socket, identity, heartbeat, and safe attach semantics.
|
||||
- **Forward:** Matrix/native Mosaic provider using authenticated identity, idempotent transaction IDs, replay cursors, and the same contract suite.
|
||||
- Discord/CLI never call tmux or Matrix directly.
|
||||
|
||||
### Fleet/tmux Provider Boundary
|
||||
|
||||
`TmuxFleetRuntimeProvider` supports only rostered fleet peers. Its transport resolves the configured roster socket itself and verifies the exact `=<agent>:0.0` pane and declared runtime command before every attach, message, or termination operation. Prefixes, unrostered session IDs, unavailable sockets, dead panes, and runtime identity mismatches fail closed; callers cannot supply a socket or raw tmux target.
|
||||
|
||||
The provider advertises list, tree, read-only attach, send, and terminate. List/tree/health and read attach all default-deny until a scope-aware read authority permits the operation and exact peer. Attach produces a short-lived handle bound to the immutable actor, tenant, channel, and correlation scope; it never opens a server-side terminal and rejects `control` mode. Fleet stream support is intentionally absent. Tess has no direct write/control authority: send and terminate default-deny until a Mos authority adapter explicitly allows the exact session and immutable scope. The gateway registry remains the audit boundary for every requested, denied, and successful provider operation, and still consumes the exact-action termination approval before the provider is invoked.
|
||||
|
||||
## Plugin Families
|
||||
|
||||
1. Channel: Discord now; other channels later.
|
||||
2. Runtime: Pi, fleet/tmux, Hermes, Matrix/native.
|
||||
3. Operator tools: fleet health, Mos handoff, GitOps wrappers, incident-safe diagnostics.
|
||||
4. Memory/state: search/recent/capture, durable inbox, checkpoint, handoff, compaction recovery.
|
||||
5. Migration: capability inventory, adapters, cutover, rollback, telemetry.
|
||||
|
||||
## Deployment
|
||||
|
||||
Tess runs as a rostered, systemd-supervised Pi agent using GPT-5.6 Sol and high reasoning. Secrets are supplied through approved runtime secret mechanisms. Startup fails when required model, gateway identity, Discord binding, or durable-state dependencies are missing. Health reports effective model/reasoning/tool policy without credential material.
|
||||
|
||||
The interaction-service identity is provisioning data, not a source identifier: the roster and per-agent environment carry the chosen display/roster name into a generic systemd instance. The service rejects a name mismatch or any drift from its pinned Pi/GPT-5.6 Sol/high/operator-interaction effective policy before launch. Its policy printer exposes only those resolved safe fields.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Tess Developer Guide
|
||||
|
||||
Interaction adapters pass only server-derived actor/tenant scope, channel, and correlation to runtime providers. Durable session state owns inbox/outbox/checkpoint recovery. Use the OpenAPI contract rather than inventing routes; unsupported provider capabilities fail closed.
|
||||
@@ -0,0 +1,17 @@
|
||||
# TESS-M4-003 Operator Plugin Sketch
|
||||
|
||||
## Memory/retrieval slice — TESS-MEM-001
|
||||
|
||||
Introduce a transport-neutral `OperatorMemoryPlugin` in `packages/memory`. The plugin receives a server-derived `{tenantId, ownerId, sessionId}` scope and delegates to a registered `MemoryAdapter`; adapter and namespace are injected configuration, never caller input. Its operations are `capture`, `search`, `recent`, `stats`, and `startupContext`. Results carry configured instance, provenance, and namespace metadata. Capture/redaction occurs before adapter persistence; startup context uses a bounded candidate window ordered so project/flat-file truth takes precedence within returned material.
|
||||
|
||||
Registration remains replaceable-adapter based: the existing `registerMemoryAdapter(kind, factory)` / `createMemoryAdapter(config)` seam supplies the injected adapter to `createOperatorMemoryPlugin(config)`. Identity and namespace are configuration data; no interaction-agent name is embedded in keys or defaults.
|
||||
|
||||
## Remaining plugin foundations — TESS-PLG-001
|
||||
|
||||
- `packages/agent`: capability descriptors for runtime bootstrap, durable inbox/state hooks, and read-only fleet diagnostics. Each capability advertises supported operations and fails closed when absent.
|
||||
- `packages/mosaic`: a catalog/registration surface for GitOps, fleet diagnostics, runtime bootstrap, Discord, and MCP/skill discovery. Catalog entries describe authority, input schema, and safe/read-only status; they do not invoke provider transports directly.
|
||||
- Gateway/channel adapters consume these contracts through server-derived actor/tenant context and durable session state, preserving the replaceable-adapter boundary.
|
||||
|
||||
## First implementation boundary
|
||||
|
||||
The first PR slice should add the operator-memory plugin contract, configuration-injected adapter seam, scope isolation, provenance-bearing retrieval, and tests for namespace isolation plus a differently named configured instance. Durable inbox/outbox remains owned by the existing `DurableSessionCoordinator`; this plugin only supplies bounded context/capture at lifecycle boundaries.
|
||||
@@ -0,0 +1,8 @@
|
||||
# TESS-M5-003 Documentation Checklist
|
||||
|
||||
- [x] `openapi-tess.yaml`: authenticated interaction endpoints including SSE stream, Mos handoff/observe/result, and memory preferences, insights, and search.
|
||||
- [x] User guide: authorized session and handoff workflows.
|
||||
- [x] Admin guide: provisioning, policy, health, and approval boundary.
|
||||
- [x] Developer guide: scope, durable state, and provider adapter contract.
|
||||
- [x] Plugin guide: replaceable-adapter, redaction, and identity-as-data rules.
|
||||
- [x] Operations guide: readiness, recovery, ambiguous-effect safety, and tracing.
|
||||
@@ -0,0 +1,12 @@
|
||||
# TESS-MIG-001 — Cutover Procedure
|
||||
|
||||
This procedure is evidence-bound. It does not authorize a production cutover until the M5 qualification gate records the required validation.
|
||||
|
||||
1. Confirm the gateway has the explicitly registered `runtime.hermes` adapter (`apps/gateway/src/agent/agent.module.ts`) and provider reachability evidence (`apps/gateway/src/agent/hermes-runtime-reachability.e2e.test.ts`).
|
||||
2. Query the normalized runtime capability surface, not a Hermes API directly. Confirm the session capabilities required for the operation are advertised.
|
||||
3. Query the transitional matrix through `RuntimeProviderService.transitionalCapabilityMatrix` (`apps/gateway/src/agent/runtime-provider-registry.service.ts`). Kanban, skills, memory, tools, and cron must remain `unsupported`; stop rather than route those operations through Hermes.
|
||||
4. Route new memory activity through the Mosaic operator-memory plugin path; there is no landed Hermes memory import.
|
||||
5. Use `InteractionCoordinationService` (`apps/gateway/src/coord/interaction-coordination.service.ts`) for orchestration handoff. The interaction agent does not take configured orchestrator authority.
|
||||
6. Record the qualification evidence and only then update an external deployment/channel binding through its separately authorized operational process.
|
||||
|
||||
No claim here authorizes bulk transcript copying, data-schema migration, or enabling an unsupported transitional capability.
|
||||
@@ -0,0 +1,11 @@
|
||||
# TESS-MIG-001 — Hermes → Mosaic Evidence Inventory
|
||||
|
||||
Hermes is a reference adapter, not a Mosaic core dependency. `packages/agent/src/hermes-runtime-provider.ts` contains the adapter-local `HermesLegacySession` and converts it to core `RuntimeSession`; `packages/types/src/agent/agent-runtime-provider.ts` contains only normalized contracts. `apps/gateway/src/agent/agent.module.ts` explicitly registers the adapter, while `apps/gateway/src/agent/runtime-provider-registry.service.ts` exposes it only through the runtime registry.
|
||||
|
||||
| Reference concern | Landed Mosaic evidence | State |
|
||||
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
|
||||
| sessions, hierarchy, streaming, send/attach/terminate | `HermesRuntimeProvider` plus `hermes-runtime-provider.test.ts` | adapted |
|
||||
| Kanban, skills, memory, tools, cron | normalized matrix in `HermesRuntimeProvider.transitionalCapabilityMatrix`; each is `unsupported` and `assertTransitionalCapability` denies before a transport call | deferred / fail-closed |
|
||||
| operator memory | `packages/memory/src/operator-memory-plugin.ts`, constructed by `apps/gateway/src/memory/memory.module.ts` and session-scoped by `apps/gateway/src/agent/agent.service.ts` | native Mosaic path |
|
||||
| orchestration handoff | `InteractionCoordinationService` in `apps/gateway/src/coord/interaction-coordination.service.ts` retains authenticated handoff/observe/result ownership checks | native Mosaic path |
|
||||
| transcripts, profiles, preferences | no Hermes importer/schema mapping landed | no automatic migration |
|
||||
@@ -0,0 +1,14 @@
|
||||
# TESS-MIG-001 — Retention and Legacy Deprecation Policy
|
||||
|
||||
## Retention
|
||||
|
||||
- Hermes is not a Mosaic persistence authority. The adapter maps runtime behavior only; it does not import or persist Hermes legacy session shapes.
|
||||
- Mosaic operator memory is scoped by tenant, owner, and session in `packages/memory/src/operator-memory-plugin.ts`; gateway session ownership is derived before that plugin is made available in `apps/gateway/src/agent/agent.service.ts`.
|
||||
- Existing Hermes archives remain in their source system under its existing retention policy. This project has no landed automatic transcript, profile, or preference migration.
|
||||
- Any future import requires an explicit, scoped design and redaction/provenance evidence; it must not extend `packages/types` with Hermes schema.
|
||||
|
||||
## Deprecation
|
||||
|
||||
- Session adapter use remains transitional until M5 qualification demonstrates the normalized provider path.
|
||||
- Kanban, skills, memory, tools, and cron are not deprecated into a Hermes bridge: they remain explicitly unsupported until their Mosaic-owned contracts are implemented and qualified.
|
||||
- A future deprecation change must remove the external binding first, retain rollback evidence, and then remove the adapter in a separately reviewed code change. It must not silently replace or widen a registered provider.
|
||||
@@ -0,0 +1,10 @@
|
||||
# TESS-MIG-001 — Rollback Procedure
|
||||
|
||||
Rollback is configuration/binding reversal, not a database rollback: no Hermes schema migration or automatic data import is implemented by the landed adapter.
|
||||
|
||||
1. Stop sending new traffic to the Mosaic Hermes adapter by reverting the external runtime/channel binding through its authorized deployment process.
|
||||
2. Keep the gateway registration and core contracts unchanged unless a reviewed code rollback is required; `AgentRuntimeProviderRegistry` registration is explicit and non-replacing (`packages/agent/src/runtime-provider-registry.ts`).
|
||||
3. Do not replay an unsupported Kanban, skills, memory, tools, or cron operation. The transitional matrix is intentionally fail-closed.
|
||||
4. Preserve Mosaic audit, session, and operator-memory records under their normal scoped retention rules; do not copy them into Hermes as a rollback shortcut.
|
||||
5. For an in-flight coordination request, use the owned handoff observation/result flow in `InteractionCoordinationService` (`apps/gateway/src/coord/interaction-coordination.service.ts`); do not create a second orchestrator path.
|
||||
6. Capture the binding reversal, affected scope, correlation IDs, and reason in the approved operational record before retrying a cutover.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Tess Capability Migration Inventory
|
||||
|
||||
Status values: `native` · `adapt` · `defer` · `reject`. This is the initial inventory; M5 requires implementation and evidence fields to be completed before cutover.
|
||||
|
||||
| Capability | Current source | Target | Initial status | Cutover/rollback intent |
|
||||
| ---------------------------------------- | ---------------------------------------- | ------------------------------------------ | -------------- | ----------------------------------------------------------------------- |
|
||||
| Interactive agent chat/session streaming | Hermes/Pi/OpenClaw | Mosaic Tess session service | native | Dual-run per channel; revert binding to legacy gateway |
|
||||
| Discord dedicated-channel routing | Hermes/Claude/OpenClaw plugins | Mosaic Discord plugin + gateway | native | Per-channel binding switch; legacy bot disabled only after soak |
|
||||
| CLI/TUI session interaction and attach | Hermes/Pi/tmux | `mosaic tess` + AgentRuntimeProvider | native | Keep direct tmux attach as break-glass rollback |
|
||||
| Session list/tree/send/terminate | Hermes/fleet | AgentRuntimeProvider | native | Capability-negotiated adapter remains during migration |
|
||||
| Mos/fleet orchestration handoff | tmux messaging/Mosaic fleet | Mosaic coord/fleet provider | native | tmux handoff remains initial transport |
|
||||
| Kanban/projects/tasks | Hermes Kanban | Mosaic queue/coord/project providers | adapt | Read projection first; mutating cutover after parity/audit |
|
||||
| Skills catalog/load/manage | Hermes skills/Pi skills | Mosaic skill registry/provider | adapt | Import metadata/provenance; preserve source skill until validated |
|
||||
| Tools and MCP | Hermes/OpenClaw/MCP | Mosaic tool registry/MCP | adapt | Default deny; migrate allowlisted tools one capability at a time |
|
||||
| Cron/scheduled work | Hermes cron | Mosaic scheduler/queue | adapt | Shadow schedules; prevent duplicate execution; rollback owner field |
|
||||
| Memory search/recent/capture | jarvis-brain/OpenViking/OpenBrain/Hermes | Mosaic memory provider | adapt | Flat/project stores remain truth; semantic systems are mirrors |
|
||||
| User/profile preferences | Hermes memory/user profile | Mosaic user/memory domain | adapt | Provenance + explicit conflict rules; exportable rollback snapshot |
|
||||
| Agent state/inbox/handoff | OpenClaw extensions/session files | Mosaic durable state service | native | Read legacy handoff during coexistence; write Mosaic only after cutover |
|
||||
| Runtime contract/bootstrap | Mosaic framework/Hermes/OpenClaw | Mosaic compose/runtime provider | native | Legacy launchers remain until clean-host parity passes |
|
||||
| Repository/PR workflow | Mosaic wrappers/Hermes tools | Mosaic operator plugin | native | Wrapper-only; no raw-provider fallback |
|
||||
| Incident-safe diagnostics | Hermes skills/tools | Mosaic scoped operator plugin | adapt | Read-only first; privileged recovery requires approval |
|
||||
| Broad unrestricted shell from Discord | Hermes/OpenClaw configurations | None | reject | No cutover; replace with allowlisted typed operations |
|
||||
| Raw full transcript bulk migration | Hermes/Claude/OpenClaw histories | Indexed summaries/selective import | reject | Keep source archives subject to retention; no automatic copy |
|
||||
| Voice/video interaction | Hermes optional tools | Future Mosaic channel plugins | defer | Not required for Tess operational release |
|
||||
| Matrix transport | Mosaic connector | AgentRuntimeProvider Matrix implementation | native | Non-default until contract/reliability parity; tmux rollback |
|
||||
|
||||
## Cutover Gates
|
||||
|
||||
1. Capability contract and security tests pass.
|
||||
2. Data mapping/provenance and retention are documented.
|
||||
3. Shadow or dual-run shows no unauthorized access, loss, or duplicate effects.
|
||||
4. Operator runbook and rollback are exercised.
|
||||
5. Channel/provider binding changes are reversible without schema rollback.
|
||||
6. Legacy capability is disabled only after a defined soak period and evidence review.
|
||||
@@ -0,0 +1,87 @@
|
||||
# Tess–Mos Coordination Contract Sketch
|
||||
|
||||
**Task:** TESS-M4-001 · **PRD:** TESS-MOS-001 / AC-TESS-04
|
||||
|
||||
## Boundary
|
||||
|
||||
Agent identities are deployment data. A configured interaction agent may request
|
||||
Mos-owned work; the configured orchestration agent owns decomposition, worker
|
||||
assignment, reviews, and merge decisions. The interaction agent receives a
|
||||
correlated receipt, read-only activity projection, and terminal result. It has
|
||||
no dispatch, assignment, review, merge, or cancellation operation.
|
||||
|
||||
## `@mosaicstack/coord` interface
|
||||
|
||||
```ts
|
||||
interface CoordinationScope {
|
||||
readonly actorId: string;
|
||||
readonly tenantId: string;
|
||||
readonly correlationId: string;
|
||||
readonly requesterAgentId: string; // trusted gateway/configuration data
|
||||
}
|
||||
|
||||
interface HandoffRequest {
|
||||
readonly idempotencyKey: string;
|
||||
readonly summary: string;
|
||||
readonly context?: string;
|
||||
readonly missionId?: string;
|
||||
}
|
||||
|
||||
interface HandoffReceipt {
|
||||
readonly handoffId: string;
|
||||
readonly targetAgentId: string;
|
||||
readonly status: 'accepted' | 'queued';
|
||||
readonly correlationId: string;
|
||||
}
|
||||
|
||||
interface Handoff {
|
||||
readonly handoffId: string;
|
||||
readonly targetAgentId: string;
|
||||
readonly request: HandoffRequest;
|
||||
readonly scope: CoordinationScope;
|
||||
}
|
||||
|
||||
interface InteractionCoordinationPort {
|
||||
handoff(handoff: Handoff): Promise<HandoffReceipt>;
|
||||
observe(handoffId: string, scope: CoordinationScope): Promise<CoordinationObservation>;
|
||||
result(handoffId: string, scope: CoordinationScope): Promise<CoordinationResult>;
|
||||
}
|
||||
```
|
||||
|
||||
The port deliberately omits generic orchestrator verbs. It is tenant- and
|
||||
correlation-scoped; its gateway implementation obtains `actorId`, `tenantId`,
|
||||
and the requester agent from trusted authentication/configuration only.
|
||||
|
||||
## HTTP routes
|
||||
|
||||
`/api/coord/interaction` is the canonical HTTP coordination prefix for handoff, observe, and result. `/api/coord/mos` remains a backward-compatible alias with the same handlers and DTOs; new integrations use the neutral canonical prefix.
|
||||
|
||||
## Enforcement point
|
||||
|
||||
`apps/gateway` owns an `InteractionCoordinationService` (`apps/gateway/src/coord/interaction-coordination.service.ts`) boundary that compares the
|
||||
trusted configured requester/target identities and rejects all of the following
|
||||
before calling a transport: unconfigured requester, self-delegation, target
|
||||
identity drift, cross-tenant observe/result lookup, and attempts to observe or
|
||||
receive a result for a handoff outside the originating tenant. The service exposes handoff, observe,
|
||||
and result only, and delegates delivery to an injected adapter.
|
||||
|
||||
M4 ships a native in-process `InMemoryInteractionCoordinationPort` as the concrete,
|
||||
deterministic adapter. It preserves the immutable handoff ID, tenant, requester
|
||||
identity, and correlation ID while demonstrating the handoff → observe → result
|
||||
round trip. It is a queue/port adapter, not a Mos-side consumer.
|
||||
|
||||
A future fleet/tmux adapter is a documented M5 deployment seam and must
|
||||
implement the same `InteractionCoordinationPort`; no channel client or interaction
|
||||
runtime calls a transport directly.
|
||||
|
||||
## Required tests
|
||||
|
||||
1. A configured non-default interaction identity can hand off work to a
|
||||
configured non-default orchestration identity and receive its result.
|
||||
2. The gateway passes only server-derived scope/identity to the adapter.
|
||||
3. Self-targeting, target drift, and cross-tenant observe/result all fail closed
|
||||
without invoking the adapter.
|
||||
4. The exported public contract has no worker-dispatch, assignment, review,
|
||||
merge, or cancellation capability.
|
||||
5. The native adapter round-trips queued work, activity, and a host-recorded
|
||||
terminal result without a live fleet dependency.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Tess Operations and Recovery
|
||||
|
||||
Check `/health/ready`, provider health, and effective policy before recovery. Recover durable sessions through the interaction recovery operation; it requeues only interrupted work and does not replay ambiguous external effects. Preserve correlation IDs for incident tracing and use Mos handoff observation/result endpoints for orchestration visibility.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Tess Plugin Authoring
|
||||
|
||||
Plugins are replaceable adapters. Declare capabilities, derive scope from trusted context, preserve correlation IDs, redact before persistence/egress, and return unsupported operations as fail-closed results. Names and identities are configuration data, not literals in keys or defaults.
|
||||
|
||||
## Official channel adapter contract
|
||||
|
||||
Official Discord, Matrix, Slack, and future channel adapters share contracts exported from `@mosaicstack/types` under `channel/`:
|
||||
|
||||
- `OfficialChannelAdapter` provides `name`, `start()`, `stop()`, and non-throwing connection `health()`.
|
||||
- `ChannelMessageDto` and `ChannelAttachmentDto` normalize transport data with JSON-safe metadata.
|
||||
- `ChannelBindingDto` and `ChannelAuthorizedPrincipalDto` normalize configuration-owned logical-agent binding and the already-allowlisted/paired external actor.
|
||||
- `ChannelIngressDto` carries operation, correlation, native message ID, authorized principal, normalized message, and stable route into `ChannelIngressPort`.
|
||||
- `ChannelConversationRouteDto` binds a configured channel to `logicalAgentId`, stable `conversationId`, authorization parent, and response target.
|
||||
- `ChannelEgressDto` and `ChannelEgressPort` separate where a response is delivered from the gateway's runtime/provider selection.
|
||||
|
||||
`ChannelConversationRouteDto` deliberately has no harness, provider, model, process, or native runtime-session field. The gateway owns runtime selection, durable enrollment, authorization, audit, and lease/fencing. A channel adapter must not call Claude, Codex, Pi, OpenCode, tmux, or Matrix runtime providers directly. Discord currently preserves its signed Socket.IO compatibility ingress for established gateway authentication/replay/approval controls while normalizing the same ingress DTO; supplied direct ports are the future registration path.
|
||||
|
||||
## Adapter requirements
|
||||
|
||||
1. Resolve configuration-owned channel and logical-agent bindings before dispatch. A binding may carry a trusted gateway agent-config reference, but the stable route contains only the logical agent; gateway verifies the reference resolves to that agent before runtime selection.
|
||||
2. Apply channel-native allowlists and paired-user roles before any external side effect such as thread creation.
|
||||
3. Preserve native message ID, correlation ID, channel/thread address, attachments, and response target.
|
||||
4. Treat normal channel parents (for example Discord categories) separately from thread parents.
|
||||
5. Keep reconnect and conversation identity independent of the active runtime provider.
|
||||
6. Report sanitized connection/routing failures without message bodies or credentials.
|
||||
7. Pass the shared route/authorization contract suite plus adapter-specific translation tests.
|
||||
|
||||
Discord establishes the first policy: authorized untagged messages respond in the configured channel; a mention creates a thread or reuses the thread already attached to that message; existing thread messages stay there. Runtime control commands remain on the current durable session. Matrix and Slack should translate native rooms/threads into the same route and response-target semantics rather than adding transport branches to gateway core.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Tess Threat Model
|
||||
|
||||
## Assets and Trust Boundaries
|
||||
|
||||
Assets: operator identity, tenant/project data, agent sessions, fleet control, approvals, credentials, memories, tool outputs, audit evidence, and provider transports.
|
||||
|
||||
Trust boundaries: Discord→plugin, CLI→gateway, plugin→gateway service identity, gateway→Pi/provider, Tess→Mos/fleet, Tess→Hermes, MCP→gateway, persistence, and tmux/Matrix transports.
|
||||
|
||||
## Threat Matrix
|
||||
|
||||
| ID | Severity | Threat | Required control | Required verification |
|
||||
| ----- | -------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
|
||||
| TM-01 | critical | Client invokes admin/system command without role | Server-side scope/role enforcement in executor; durable approval for privileged/destructive commands | Authenticated non-admin and forged-scope tests deny and audit |
|
||||
| TM-02 | critical | Cross-user/tenant list, attach, send, or terminate by guessed session ID | Owner/tenant binding on every session operation; admin override is explicit and audited | Cross-tenant matrix for REST, WS, CLI, Discord and provider methods |
|
||||
| TM-03 | high | MCP caller supplies another `userId` | Remove actor IDs from schemas; derive actor/tenant from authenticated context; per-tool scopes | Forged actor/tool calls deny; no victim data returned |
|
||||
| TM-04 | high | Discord ingress impersonates user/channel or bypasses gateway auth | Service-to-service identity, guild/channel/user allowlists, signed/correlated envelope, replay protection | Invalid service identity, unlisted IDs, replayed message IDs all deny |
|
||||
| TM-05 | high | Secrets/PII leak in chat, auth links, tool args, logs, memory, or DB | Redact before persistence/egress; DM/out-of-band auth flow; short-lived hashed token state; output classification | Seeded secret/PII canary absent from durable stores/logs/public channel |
|
||||
| TM-06 | high | Prompt/tool injection escalates from content to privileged action | Treat messages/files/tool output as untrusted data; structured proposals only; allowlisted tools; approval binds exact action digest | Injection corpus cannot invoke unapproved tools or alter authority |
|
||||
| TM-07 | high | Approval forged, replayed, or applied to modified action | One-time approval with actor, tenant, action digest, expiry, correlation and consumption record | Forged/replayed/expired/mutated approvals deny and audit |
|
||||
| TM-08 | medium | Restart causes message loss or duplicate side effects | Durable inbox/outbox/checkpoint; idempotency keys; transactional state transitions; bounded replay | Kill/restart at each state transition; exactly-once effect or safe dedupe |
|
||||
| TM-09 | medium | Session GC/retention crosses tenant/session scope | Session/user-scoped GC or separately authorized global retention job | GC one session; unrelated logs/memory remain unchanged |
|
||||
| TM-10 | high | tmux/Matrix transport target or identity spoofing | Exact target/socket binding, peer identity verification, Matrix whoami, authenticated transport metadata | Wrong socket/peer/room/identity refuses delivery/attach |
|
||||
| TM-11 | medium | Hermes adapter exposes unsupported or broader legacy powers | Capability negotiation, default deny, normalized scopes, adapter sandbox/timeouts | Unsupported and over-scoped operations fail closed |
|
||||
| TM-12 | medium | Tess competes with Mos or bypasses orchestration gates | Authority policy and correlated Mos handoff; no Tess worker-claim capability by default | Coding/decomposition intent produces handoff, not direct claim |
|
||||
|
||||
## Security Invariants
|
||||
|
||||
1. Authentication is not authorization; every command/tool/provider operation is authorized server-side.
|
||||
2. Actor, tenant, roles, and channel bindings come only from authenticated gateway context.
|
||||
3. No client-provided session ID grants ownership or attachment.
|
||||
4. No privileged action executes without a matching, unexpired, one-time approval when policy requires it.
|
||||
5. Redaction occurs before persistence and before channel egress.
|
||||
6. Every externally caused operation is replay-safe and correlated.
|
||||
7. Provider capability absence is a denial, not an invitation to shell around it.
|
||||
|
||||
## Closed Prerequisite Findings
|
||||
|
||||
The original M1 findings below are closed by landed controls and retained for audit traceability.
|
||||
|
||||
| Former finding | Closed evidence |
|
||||
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Command scope/role enforcement | `apps/gateway/src/commands/command-authorization.service.ts` and its authorization tests enforce the server-side approval boundary. |
|
||||
| Cross-owner session access | Gateway session ownership tests cover server-derived owner and tenant scope. |
|
||||
| Caller-controlled MCP identity | MCP tools derive actor and tenant from authenticated gateway context. |
|
||||
| Missing Discord ingress allowlists | `apps/gateway/src/plugin/plugin.module.ts` requires the guild, channel, and user allowlist environment values; `apps/gateway/src/plugin/discord-ingress.security.spec.ts` exercises denial and configured ingress. |
|
||||
| Missing redaction before persistence/egress | Gateway and log redaction coverage verifies sensitive content is classified before durable storage or channel delivery. |
|
||||
| In-memory-only restart safety | `packages/agent/src/durable-session.test.ts` reconstructs durable identity, inbox/outbox, checkpoints, and handoffs after simulated restart. |
|
||||
| Globally scoped session GC | `apps/gateway/src/gc/session-gc.service.spec.ts` verifies session-only collection and the absence of automatic global collection entry points. |
|
||||
|
||||
These controls remain subject to the runtime's independent review and release qualification gates.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Tess User Guide
|
||||
|
||||
## Discord conversations
|
||||
|
||||
In a configured Tess/interaction channel, an authorized untagged message is sent to the bound logical agent and its response appears in the channel. Mention the bot when starting a separate topic: Mosaic reuses a thread already attached to that same Discord message, or creates a new thread for the message, and responds there. Continue in that thread without tagging the bot again. Messages from unconfigured channels or users without an authorized pairing are ignored without creating a thread.
|
||||
|
||||
`/approve` and `/stop <approval>` operate on the current channel/thread session and do not open a new thread. The Discord connection is bound to the logical agent conversation, not Claude, Codex, Pi, OpenCode, or another harness; a runtime handoff behind Mosaic does not change where you continue the conversation.
|
||||
|
||||
## CLI and HTTP interaction
|
||||
|
||||
All HTTP interaction calls require authenticated session credentials and `X-Correlation-Id`. Use `GET /api/interaction/{agentName}/sessions?provider=...` to list only visible runtime sessions, then enroll with `POST .../sessions/{sessionId}/enroll` body `{providerId,runtimeSessionId}`. Attach uses `{mode:"read"}`; send uses `{content,idempotencyKey}`. Stop requires `{approvalRef}` and fails with 403 without the exact durable approval. Recovery only requeues interrupted durable work.
|
||||
|
||||
Memory is user-scoped: preferences support list/get/upsert/delete; insights support list/get/create/delete; search body is `{query,limit?,maxDistance?}`. Mos work is handed off with `POST /api/coord/mos/handoff`; observe and result use the returned handoff ID.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Tess Verification Matrix
|
||||
|
||||
| Acceptance criterion | Requirements | Planned evidence | Gate |
|
||||
| -------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
|
||||
| AC-TESS-01 | TESS-PI-001, TESS-DSC-001, TESS-CLI-001 | Discord/CLI same-session integration and streaming E2E | M3-V |
|
||||
| AC-TESS-02 | TESS-ARP-001, TESS-CLI-001, TESS-FLT-001 | CLI contract tests for status/sessions/tree/attach/send/stop, typed denial/error snapshots | M3-V |
|
||||
| AC-TESS-03 | TESS-PI-001, TESS-OBS-001 | Clean service launch; status asserts GPT-5.6 Sol, high reasoning and effective tool policy with secret canaries absent | M2-V, M3-V |
|
||||
| AC-TESS-04 | TESS-MOS-001, TESS-FLT-001 | M4 contract/gateway native-port handoff → observe → result round trip; configurable identity, target-drift and tenant-denial tests; M4-V fleet authority qualification | M4-001, M4-V |
|
||||
| AC-TESS-05 | TESS-HRM-001, TESS-MEM-001 | Hermes capability contract suite: sessions/stream/send/tree plus Kanban/skills/memory/tools/cron supported-or-denied matrix; operator-memory plugin (TESS-MEM-001) reachable end-to-end — env-configured plugin registered + AgentService session-bound server-derived {tenantId,ownerId,sessionId} scoped search/capture, cross-tenant reuse denied before plugin call (M4-W-001 spine: #736 plugin + #739 consumer) | M4-V |
|
||||
| AC-TESS-06 | TESS-STA-001, TESS-SEC-008 | Kill/restart/compaction fault injection across inbox/outbox/checkpoint transitions; duplicate side-effect detector | M2-V, M5-V |
|
||||
| AC-TESS-07 | TESS-SEC-001..009 | Threat-model abuse suite: authz, tenant isolation, forged identity/approval, injection, redaction, transport identity, GC scope | M1-V, M3-V, M5-V |
|
||||
| AC-TESS-08 | TESS-TRN-001 | Common provider contract suite against tmux/fleet and Matrix/native; identity and replay tests | M5-V |
|
||||
| AC-TESS-09 | all | `pnpm typecheck`, lint, format, unit/integration/contract/E2E; independent code and security reviews; CI URLs | Every milestone |
|
||||
| AC-TESS-10 | TESS-MIG-001 | Completed capability inventory with native/adapted/deferred/rejected state, owner, cutover/rollback evidence | M5-V |
|
||||
| AC-TESS-11 | TESS-PLG-001, TESS-OBS-001 | OpenAPI and user/admin/developer/plugin/ops docs, sitemap links, documentation checklist | M5-V |
|
||||
|
||||
## Security Abuse Suite Minimum
|
||||
|
||||
- Role/scope matrix for every command and provider capability.
|
||||
- Cross-tenant and cross-user session ID matrix across REST, WS, Discord, CLI, MCP, and providers.
|
||||
- Discord service identity, guild/channel/user allowlist, replay, attachment, and mention/DM policy cases.
|
||||
- Prompt/tool injection corpus and structured-proposal enforcement.
|
||||
- Approval action-digest mutation, replay, expiry, tenant, and actor mismatch cases.
|
||||
- Secret/PII canaries through message, attachment, tool args/output, logs, memory, audit, and error paths.
|
||||
- Restart fault injection before/after enqueue, provider send, side effect, response persistence, and acknowledgement.
|
||||
- Wrong tmux socket/target and Matrix identity/room/replay cases.
|
||||
|
||||
## Evidence Rules
|
||||
|
||||
Evidence must include command/test name, terminal result, CI run URL, PR/merge reference, environment, and artifact/log location. A worker self-report is not evidence until independently verified.
|
||||
@@ -0,0 +1,19 @@
|
||||
# TESS-HRM-001 — Hermes runtime adapter boundary
|
||||
|
||||
## Normalized provider surface
|
||||
|
||||
`HermesRuntimeProvider` implements the existing Mosaic-owned `AgentRuntimeProvider` unchanged. Its public surface is therefore `capabilities`, `health`, session list/tree, stream, send, attach/detach, and terminate, accepting only `RuntimeScope`, `RuntimeMessage`, `RuntimeSession`, `RuntimeStreamEvent`, and other types from `@mosaicstack/types`. Provider id is `runtime.hermes`.
|
||||
|
||||
The provider receives a narrow injected `HermesRuntimeTransport`, whose method names and inputs may represent Hermes API operations but whose return values are explicitly private `HermesLegacy*` types defined only in `packages/agent/src/hermes-runtime-provider.ts`. Mapping functions convert those private values to Mosaic sessions, state, hierarchy, and stream events. Capability negotiation maps a supplied Hermes feature inventory onto the fixed Mosaic runtime capability vocabulary; no unknown/ambiguous legacy feature is advertised. Unsupported Mosaic operations throw the typed fail-closed `capability_unsupported` provider error before a transport call.
|
||||
|
||||
## Boundary line
|
||||
|
||||
**Hermes legacy schema ends at `HermesRuntimeTransport` and its private adapter-local `HermesLegacy*` definitions in `packages/agent`.** `packages/types` is never changed to contain a Hermes field, enum, identifier, session shape, status, or capability. `apps/gateway` registers/resolves the provider only through `AgentRuntimeProvider` and receives normalized values only. Identity remains server-derived `RuntimeScope` data and is passed to the injected transport as context, never reconstructed from a legacy response.
|
||||
|
||||
## Initial mapping and safety posture
|
||||
|
||||
- Hermes conversation/thread identifiers map to opaque Mosaic `RuntimeSession.id`; parent linkage maps only when a known parent exists.
|
||||
- Hermes status strings map through a closed lookup to `RuntimeSessionState`; unknown statuses become `failed`, never a permissive active state.
|
||||
- Legacy stream chunks map to `message.delta` / `message.complete`; malformed or unsupported events become a normalized `runtime.error` event.
|
||||
- Send, attach, and terminate require the normalized capability first. `terminate` continues to be approval-bound by the gateway service; the adapter does not weaken gateway authority.
|
||||
- Kanban, skills, memory, tools, and cron are capability-inventory entries for this transitional adapter, not additions to the core runtime contract. They are reported as explicitly unsupported until a Mosaic-owned capability contract exists.
|
||||
@@ -0,0 +1,238 @@
|
||||
# Tess / Option 2 runtime-portability qualification — 2026-07-14
|
||||
|
||||
**Issue context:** #706–#711 and runtime-neutral Mos follow-up #754
|
||||
|
||||
**Qualified revision:** `d0771835542d` (`origin/main` at review time)
|
||||
|
||||
**Reviewer/runtime:** Independent Pi lane requested as `openai-codex/gpt-5.6-sol:high`
|
||||
|
||||
**Runtime resolution note:** Mosaic warned that `gpt-5.6-sol` was not present in the provider model catalog and proceeded with it as a custom model ID. This warning was part of the original qualification log and is material provenance; downstream claims must not treat catalog recognition as verified.
|
||||
|
||||
**Verdict:** REQUEST CHANGES
|
||||
|
||||
**Evidence type:** Point-in-time qualification; later commits and PR #757 must be reviewed separately
|
||||
|
||||
## Purpose and provenance
|
||||
|
||||
This report preserves the complete independent qualification that was previously available only in `/tmp/tess-option2-qualification.log`. It distinguishes passing component tests from the missing operational proof required for identity-continuous Mos failover.
|
||||
|
||||
No credential values, OAuth tokens, Discord tokens, device codes, or auth-file contents are included. Commands and results are retained so another environment can reproduce or challenge the findings.
|
||||
|
||||
---
|
||||
|
||||
# 1. Verdict
|
||||
|
||||
## **REQUEST CHANGES**
|
||||
|
||||
The current Option 2 implementation is a useful portability foundation, but it is **not qualified against AC-TESS-01..11** and is not equivalent to true same-Mos-identity failover.
|
||||
|
||||
Primary blockers:
|
||||
|
||||
1. **AC-TESS-01/02:** The required `mosaic tess` command does not exist; only `mosaic interaction` is registered (`packages/mosaic/src/commands/interaction.ts:60`). The cross-surface test proves CLI enrollment followed by Discord approval/stop, not bidirectional Discord/CLI chat streaming.
|
||||
2. **AC-TESS-04:** Fleet/tmux and Matrix providers are implemented as libraries but are not registered in the production gateway. `AgentModule` registers only Hermes (`apps/gateway/src/agent/agent.module.ts:34`).
|
||||
3. **Mos handoff is not operational or durable:** Production uses `InMemoryInteractionCoordinationPort` (`apps/gateway/src/coord/coord.module.ts:18`), with no Mos-side consumer. Restart loses handoff ownership, idempotency, activity, and results.
|
||||
4. **AC-TESS-06/10:** Restart tests are good local persistence tests, but no real connector/harness failover or exercised rollback exists. Rollback is documentation-only.
|
||||
5. **AC-TESS-08:** The parity suite validates a selected shared intersection using mocked transports. Matrix is not production-wired and tmux drops the runtime message idempotency key before delivery.
|
||||
6. **AC-TESS-09:** M5 qualification remains `not-started`; no live Discord, Matrix homeserver, tmux/Mos consumer, Claude Code/Pi/Codex failover, or deployment rollback was tested.
|
||||
7. **PR #750 mismatch:** Its description promises send-error coverage as HTTP 400, but both gateway and TUI test use HTTP 403 (`packages/mosaic/src/tui/gateway-api.interaction-errors.test.ts:25-34`).
|
||||
|
||||
### AC disposition
|
||||
|
||||
| AC | Result | Evidence |
|
||||
| --- | ----------------- | ------------------------------------------------------------------------------- |
|
||||
| 01 | **Fail** | No `mosaic tess`; no bidirectional same-session chat/stream E2E |
|
||||
| 02 | **Fail** | Generic CLI exists, but fleet/Matrix providers are unreachable in production |
|
||||
| 03 | Pass | Pi profile/model/reasoning/effective-policy tests passed |
|
||||
| 04 | **Fail** | No registered fleet provider or real Mos consumer |
|
||||
| 05 | Partial | Hermes normalization/fail-closed matrix passes; live capability path is limited |
|
||||
| 06 | Partial | PGlite restart/idempotency passes; no actual harness failover |
|
||||
| 07 | Partial | Focused denial/replay tests pass; full M5 abuse qualification absent |
|
||||
| 08 | Partial | Mocked shared-intersection parity passes; Matrix not operationally wired |
|
||||
| 09 | **Fail** | Baselines/CI green, but required E2E/security/rollback qualification absent |
|
||||
| 10 | **Fail** | Inventory incomplete/inconsistent; rollback not exercised |
|
||||
| 11 | Pass/ledger stale | Documentation and sitemap exist; plugin/catalog ledger remains unresolved |
|
||||
|
||||
---
|
||||
|
||||
# 2. Exact test commands and results
|
||||
|
||||
Initial focused attempts failed before collection because this detached worktree had no dependencies:
|
||||
|
||||
```bash
|
||||
pnpm --filter @mosaicstack/agent exec vitest run ...
|
||||
```
|
||||
|
||||
Result: startup failure, `Cannot find module 'vitest/config'`.
|
||||
|
||||
Setup used:
|
||||
|
||||
```bash
|
||||
corepack pnpm --store-dir /home/jarvis/.local/share/pnpm/store/v10 \
|
||||
install --frozen-lockfile --ignore-scripts
|
||||
```
|
||||
|
||||
Result: PASS, 1,240 packages linked.
|
||||
|
||||
```bash
|
||||
corepack pnpm turbo run build \
|
||||
--filter='@mosaicstack/gateway^...' \
|
||||
--filter='@mosaicstack/mosaic^...'
|
||||
```
|
||||
|
||||
Result: **17/17 dependency builds successful**.
|
||||
|
||||
### Focused suites
|
||||
|
||||
```bash
|
||||
corepack pnpm --filter @mosaicstack/agent exec vitest run \
|
||||
src/runtime-provider-parity.test.ts \
|
||||
src/matrix-native-runtime-provider.test.ts \
|
||||
src/tmux-fleet-runtime-provider.test.ts \
|
||||
src/durable-session.test.ts \
|
||||
src/hermes-runtime-provider.test.ts
|
||||
```
|
||||
|
||||
Result: **5 files, 39/39 tests passed**.
|
||||
|
||||
```bash
|
||||
corepack pnpm --filter @mosaicstack/gateway exec vitest run \
|
||||
src/agent/durable-session.repository.test.ts \
|
||||
src/__tests__/integration/tess-cross-surface.integration.test.ts \
|
||||
src/plugin/discord-ingress.security.spec.ts \
|
||||
src/coord/interaction-coordination.service.test.ts \
|
||||
src/coord/interaction-coordination.routing.e2e.test.ts \
|
||||
src/agent/hermes-runtime-reachability.e2e.test.ts
|
||||
```
|
||||
|
||||
Result: **6 files, 36/36 tests passed**. PGlite close/reopen recovery passed in 504 ms.
|
||||
|
||||
```bash
|
||||
corepack pnpm --filter @mosaicstack/mosaic exec vitest run \
|
||||
src/fleet/matrix-native-runtime-transport.test.ts \
|
||||
src/fleet/tess-service-profile.test.ts \
|
||||
src/commands/interaction.test.ts \
|
||||
src/tui/gateway-api.interaction-errors.test.ts
|
||||
```
|
||||
|
||||
Result: **4 files, 15/15 tests passed**.
|
||||
|
||||
```bash
|
||||
corepack pnpm --filter @mosaicstack/coord exec vitest run \
|
||||
src/__tests__/interaction-coordination.test.ts
|
||||
```
|
||||
|
||||
Result: **1 file, 7/7 tests passed**.
|
||||
|
||||
```bash
|
||||
corepack pnpm --filter @mosaicstack/gateway exec vitest run \
|
||||
src/agent/interaction.controller.test.ts \
|
||||
src/commands/command-authorization.service.spec.ts \
|
||||
src/agent/__tests__/runtime-provider-registry.service.test.ts
|
||||
```
|
||||
|
||||
Result: **3 files, 27/27 tests passed**.
|
||||
|
||||
Focused total: **124/124 tests passed** after dependency setup.
|
||||
|
||||
### Baselines
|
||||
|
||||
```bash
|
||||
TURBO_FORCE=true corepack pnpm typecheck
|
||||
```
|
||||
|
||||
Result: **42/42 tasks successful**.
|
||||
|
||||
```bash
|
||||
TURBO_FORCE=true corepack pnpm lint
|
||||
```
|
||||
|
||||
Result: **23/23 tasks successful**.
|
||||
|
||||
```bash
|
||||
corepack pnpm format:check
|
||||
```
|
||||
|
||||
Result: **PASS — all files matched Prettier style**.
|
||||
|
||||
```bash
|
||||
~/.config/mosaic/tools/woodpecker/pipeline-status.sh \
|
||||
-r mosaicstack/stack -n 1796
|
||||
```
|
||||
|
||||
Result: **SUCCESS** at `d0771835542d`; all test, build, sanitization, typecheck, lint, format, and publish steps green.
|
||||
|
||||
No tracked files outside the pre-existing `.mosaic/orchestrator/*` launcher changes were modified.
|
||||
|
||||
---
|
||||
|
||||
# 3. Stale ledger inconsistencies
|
||||
|
||||
1. `docs/tess/MISSION-MANIFEST.md` still says:
|
||||
- current milestone M1;
|
||||
- progress 0/5;
|
||||
- M2/M3/M5 not started.
|
||||
2. `docs/tess/TASKS.md` says:
|
||||
- M4-V failed;
|
||||
- M4-W-001 and TESS-PLG-001 in progress;
|
||||
- M5-V not started.
|
||||
3. Provider issue state conflicts:
|
||||
- #707–#709 remain open although M1–M3 rows are recorded done/pass.
|
||||
- #710 and #711 are closed although M4-V failed and M5-V is not started.
|
||||
4. M5 work was marked done despite depending on failed M4-V.
|
||||
5. TESS-M3-002 says `mosaic tess` is done, but only `mosaic interaction` exists.
|
||||
6. PR #750 removed stale service references from operational docs, but `docs/tess/TASKS.md` still contains `MosCoordinationService` in historical notes.
|
||||
7. `docs/tess/MIGRATION-INVENTORY.md` remains an “initial inventory” with several capabilities marked `adapt`; `M5-MIGRATION-INVENTORY.md` marks grouped capabilities deferred/fail-closed. Neither supplies the complete owner/evidence matrix AC-TESS-10 requires.
|
||||
8. TESS-M2-FUP-001 remains real: the unkeyed SHA-256 compatibility branch still exists at `durable-session.repository.ts:427-431`.
|
||||
9. TESS-PLG-001 claims catalog registration was folded into W-001, but production evidence shows provider registration in the gateway—not a completed `packages/mosaic` plugin catalog.
|
||||
|
||||
---
|
||||
|
||||
# 4. Gap to true same-Mos-identity failover
|
||||
|
||||
Current code can relaunch the same roster name under another runtime and can rebind a durable interaction session to another provider/runtime ID. That is **replacement**, not identity-continuous failover.
|
||||
|
||||
Missing pieces:
|
||||
|
||||
- No canonical logical Mos identity independent of harness-native session IDs.
|
||||
- No exclusive connector lease or monotonic fencing epoch; session rebinding is effectively last-write-wins.
|
||||
- No stale-holder rejection preventing the old harness from continuing side effects.
|
||||
- No normalized Claude Code/Pi/Codex checkpoint/import/export adapters.
|
||||
- No durable Mos coordination transport or Mos consumer.
|
||||
- No canonical handoff containing mission/task refs, git state, causal sequence, pending operations, capability requirements, and acknowledgements.
|
||||
- No end-to-end receipt journal across connectors.
|
||||
- Matrix has deterministic transaction IDs, but tmux delivery discards `RuntimeMessage.idempotencyKey`.
|
||||
- No fault-injection test transferring Mos among Claude Code, Pi, and Codex and then rolling back.
|
||||
|
||||
---
|
||||
|
||||
# 5. Minimal follow-up issue decomposition
|
||||
|
||||
| Order | Issue | Minimum acceptance criteria |
|
||||
| ----- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 1 | **Logical identity and security fencing** | Server-derived `{tenant, logicalAgentId, connectorId, harness, leaseEpoch, scopes, expiry}`; signed/fenced execution grant; stale/forged/cross-tenant grants denied and audited; no connector credential in handoffs |
|
||||
| 2 | **Durable connector lease** | PostgreSQL-backed exclusive lease with CAS, monotonic epoch, TTL/heartbeat, explicit takeover, and gateway rejection of stale holders; connectors for Claude Code, Pi, and Codex |
|
||||
| 3 | **Canonical handoff/checkpoint** | Versioned, sealed schema containing canonical mission/task/git references, checkpoint digest, causal sequence, required capabilities, pending/ambiguous operation references, and source/destination acknowledgement; no raw secrets or mandatory harness transcript |
|
||||
| 4 | **Exactly-once connector journal** | Durable operation IDs and receipts; idempotency propagated through every adapter; Matrix transaction mapping; tmux replaced or wrapped with receiver-side durable dedupe; ambiguous effects remain held for authorized reconciliation |
|
||||
| 5 | **Cross-harness failover and rollback E2E** | Real Mos identity moves Claude Code → Pi → Codex and back; inject crashes before/after lease transfer, handoff persistence, send, and acknowledgement; stale connector fenced; no duplicate side effects; canonical state preserved; rollback evidence published |
|
||||
| 6 | **Generic gateway research ADR** | Evaluate LiteLLM subscription OAuth and Bifrost concepts without adding either to core; include terms/security review, credential lifecycle, tenant mapping, budgets, failover semantics, and adapter-only prototype |
|
||||
|
||||
## Generic gateway placement
|
||||
|
||||
Allowed topology:
|
||||
|
||||
```text
|
||||
Discord / CLI / web
|
||||
↓
|
||||
Mosaic Gateway: auth, tenant scope, policy, approvals, audit
|
||||
↓
|
||||
IProviderAdapter / AgentRuntimeProvider
|
||||
↓
|
||||
optional LiteLLM or Bifrost egress proxy
|
||||
↓
|
||||
upstream provider
|
||||
```
|
||||
|
||||
- **LiteLLM ChatGPT subscription OAuth:** research-only, opt-in, behind an adapter. Subscription credentials require explicit terms, revocation, scope, token-storage, and audit review. They must never become Mosaic identity or core configuration.
|
||||
- **Bifrost:** virtual keys are downstream proxy credentials, not Mosaic principals. Budget and failover concepts may inform Mosaic routing, but tenant policy, authorization, and audit remain in Mosaic.
|
||||
- Neither product may introduce schemas into Mosaic core, receive direct calls from channels/agents, or bypass `IProviderAdapter`/`AgentRuntimeProvider`.
|
||||
- Mosaic should also correct its existing “all providers unhealthy → use one anyway” fallback behavior before adopting more automatic failover (`routing-engine.service.ts:204-212`).
|
||||
Reference in New Issue
Block a user