Copy architecture docs, ADRs, storage domain specs, research, reviews, and 56 storage architecture tasks from the alkhub_ts monorepo. Adapt for standalone @alkdev/hub repo structure (src/ not packages/hub/). Sanitize all sensitive information: - Replace private IPs (10.0.0.1) with localhost defaults - Remove internal server hostnames (dev1, ns528096) - Replace /workspace/ private paths with npm package references - Remove hardcoded credentials from examples - Rewrite infrastructure.md without private network details Add Deno project scaffolding: deno.json (pinned deps), .gitignore, AGENTS.md, entry point. Migrate existing code stubs (crypto, config types, logger) with updated import paths.
521 lines
26 KiB
Markdown
521 lines
26 KiB
Markdown
---
|
|
status: open
|
|
created: 2026-05-18
|
|
last_updated: 2026-05-18
|
|
---
|
|
|
|
# Core Library Extraction Sync Review
|
|
|
|
Review of the impact of extracting three core libraries — `@alkdev/operations`, `@alkdev/pubsub`, and `@alkdev/taskgraph` — on the alkhub_ts codebase and architecture documentation. These packages are now published on npm and replace in-repo code plus implement previously "not started" functionality.
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
Three packages were extracted from (or designed for) this codebase and are now platform-agnostic npm packages:
|
|
|
|
| Package | Version | Replaces in `packages/core/` | New Capabilities |
|
|
|---------|---------|-------------------------------|------------------|
|
|
| `@alkdev/operations` | 0.1.0 | `operations/` (7 files) + `mcp/` (3 files) | Call protocol (PendingRequestMap), ResponseEnvelope, access control enforcement, CallError, SchemaAdapter, subscribe helper, SSE subscription handling |
|
|
| `@alkdev/pubsub` | 0.1.0 | `pubsub/` (5 files) | EventEnvelope, WebSocket client+server+worker event targets, 13 operators (was 3), inlined Repeater, `prefix`/`close()` on Redis ET |
|
|
| `@alkdev/taskgraph` | 0.0.2 | Nothing (new) | TaskGraph class, analysis (critical path, parallel groups, bottlenecks, risk, cost-benefit), frontmatter parsing |
|
|
|
|
The decision has been made to **remove `packages/core/` as a package entirely**. Its remaining modules (config, logger, crypto) will be relocated — most likely into hub directly, since spokes that need config can import `@alkdev/operations` config types or we create a minimal `@alkhub/config` package. The first spokes won't need provider key storage; eventual "hub-like spokes" will be addressed as a federation concern later.
|
|
|
|
---
|
|
|
|
## 1. Code Changes
|
|
|
|
### 1.1 Delete from `packages/core/`
|
|
|
|
All of these are replaced by npm packages:
|
|
|
|
**`core/pubsub/`** — replaced by `@alkdev/pubsub`:
|
|
- `create_pubsub.ts`
|
|
- `typed_event_target.ts`
|
|
- `redis_event_target.ts`
|
|
- `operators.ts`
|
|
- `mod.ts`
|
|
|
|
**`core/operations/`** — replaced by `@alkdev/operations`:
|
|
- `types.ts`
|
|
- `registry.ts`
|
|
- `env.ts`
|
|
- `scanner.ts`
|
|
- `validation.ts`
|
|
- `from_schema.ts`
|
|
- `from_openapi.ts`
|
|
- `mod.ts`
|
|
|
|
**`core/mcp/`** — replaced by `@alkdev/operations/from-mcp`:
|
|
- `wrapper.ts`
|
|
- `loader.ts`
|
|
- `mod.ts`
|
|
|
|
**Tests and fixtures** — for deleted modules:
|
|
- `tests/operations/registry.test.ts`
|
|
- `tests/operations/scanner.test.ts`
|
|
- `tests/pubsub/redis_event_target.test.ts`
|
|
- `tests/mcp/loader.test.ts`
|
|
- `tests/fixtures/registry.ts`
|
|
- `tests/fixtures/operations/demo/greet.ts`
|
|
- `tests/fixtures/operations/other/calculate.ts`
|
|
|
|
### 1.2 Relocate from `packages/core/`
|
|
|
|
These have no external replacement and need to be relocated:
|
|
|
|
| Module | Lines | Destination |
|
|
|--------|-------|-------------|
|
|
| `core/config/types.ts` | 169 | Hub package (or a thin `@alkhub/config` if spokes need shared config types) |
|
|
| `core/logger/mod.ts` | 27 | Hub package (logtape config is hub-specific anyway) |
|
|
| `core/utils/crypto.ts` | 119 | Hub package (encryption key management is hub-only) |
|
|
|
|
### 1.3 Delete `packages/core/` as a package
|
|
|
|
Once modules are relocated, remove:
|
|
- `packages/core/deno.json`
|
|
- `packages/core/mod.ts`
|
|
- The `"core"` entry from root `deno.json` workspace array
|
|
|
|
### 1.4 Update dependency declarations
|
|
|
|
**Root `deno.json`**:
|
|
- Remove `"packages/core"` from workspace array
|
|
- Add `@alkdev/operations`, `@alkdev/pubsub`, `@alkdev/taskgraph` to imports (if needed at root level)
|
|
|
|
**New `packages/hub/deno.json`** (when created):
|
|
- Add: `@alkdev/operations`, `@alkdev/pubsub`, `@alkdev/taskgraph`, `@alkdev/typebox`, `@alkdev/drizzlebox`, `hono`, `drizzle-orm`, `ioredis`, `logtape`, `@hono/mcp`, `ai`, `keypal`
|
|
- Remove (no longer direct): `@repeaterjs/repeater` (inlined in @alkdev/pubsub), `@modelcontextprotocol/sdk` (optional peer in @alkdev/operations)
|
|
|
|
**New `packages/spoke/deno.json`** (when created):
|
|
- Add: `@alkdev/operations`, `@alkdev/pubsub` (client event target only), `@alkdev/typebox`, `logtape`
|
|
|
|
### 1.5 Breaking API Changes
|
|
|
|
| Change | Impact | Migration |
|
|
|--------|--------|-----------|
|
|
| `registry.execute()` returns `ResponseEnvelope<T>` not `T` | All callers must `unwrap()` or access `.data` | `import { unwrap } from "@alkdev/operations"` |
|
|
| `OperationEnv` functions return `Promise<ResponseEnvelope>` not `Promise<unknown>` | All nested call sites | Same |
|
|
| `OperationContext` drops `stream`/`pubsub` fields | Handlers using these (none exist yet) | Use `PendingRequestMap.subscribe()` for subscriptions |
|
|
| `createPubSub` uses `PubSubEventMap` not `PubSubPublishArgsByKey` | Any pubsub usage | `createPubSub<{ eventType: PayloadType }>()` — publishes with `publish(type, id, payload)` |
|
|
| `createRedisEventTarget` takes `prefix` and has `close()` | Redis setup code | Add `prefix: "alk:events:"`, call `close()` on shutdown |
|
|
| Scanner uses `ScannerFS` interface, not `Deno.readDir` directly | Spoke scanner | Provide Deno adapter: `{ readdir: (p) => Deno.readDir(p), cwd: () => Deno.cwd() }` |
|
|
| `AccessControl` drops `customAuth` field | No code uses it yet | N/A |
|
|
| MCP adapter wraps results in `mcpEnvelope()` | MCP consumers | Use `unwrap()` or `isResponseEnvelope()` |
|
|
| `assertIsSchema` throws `Error` instead of `AssertionError` | Test code | Already the correct behavior per @alkdev/operations |
|
|
|
|
---
|
|
|
|
## 2. Architecture Spec Updates
|
|
|
|
### 2.1 AGENTS.md — Major Update
|
|
|
|
**Provenance table** — Replace all "Copied from predecessor project" and "Forked from graphql-yoga" entries:
|
|
|
|
| Module | Current Status | New Status |
|
|
|--------|---------------|------------|
|
|
| Operations system | "Working, 7 tests passing" | **Extracted to `@alkdev/operations` v0.1.0** |
|
|
| PubSub (createPubSub) | "Working" | **Extracted to `@alkdev/pubsub` v0.1.0** |
|
|
| PubSub (operators) | "Working" | **Extracted to `@alkdev/pubsub` v0.1.0** |
|
|
| TypedEventTarget | "Forked from graphql-yoga" | **Extracted to `@alkdev/pubsub` v0.1.0** |
|
|
| Redis EventTarget | "Working, 5 tests passing" | **Extracted to `@alkdev/pubsub` v0.1.0** |
|
|
| WebSocket EventTarget | "Not started" | **Implemented in `@alkdev/pubsub` v0.1.0** (client + server + worker) |
|
|
| MCP client | "Working, 1 test passing" | **Extracted to `@alkdev/operations/from-mcp` v0.1.0** |
|
|
| Call protocol | "Not started" | **Implemented in `@alkdev/operations` v0.1.0** |
|
|
| Config types | "Needs hub config" | Remains (to relocate) |
|
|
| Logger | "Needs proper config" | Remains (to relocate) |
|
|
| Storage | "Not started" | Not started (unchanged) |
|
|
|
|
**Key Patterns section** — Update:
|
|
- Operations: Reference `@alkdev/operations` package, add ResponseEnvelope and call protocol
|
|
- PubSub: Reference `@alkdev/pubsub` package, update from "graphql-yoga (MIT)" to standalone package with EventEnvelope pattern
|
|
- New: Task graph operations via `@alkdev/taskgraph`
|
|
|
|
**Reference Dependencies table** — Add:
|
|
| `@alkdev/operations` | `npm:@alkdev/operations@^0.1.0` | Operations, call protocol, MCP adapter, ResponseEnvelope |
|
|
| `@alkdev/pubsub` | `npm:@alkdev/pubsub@^0.1.0` | PubSub, EventEnvelope, event targets (Redis/WS/Worker) |
|
|
| `@alkdev/taskgraph` | `npm:@alkdev/taskgraph@^0.0.2` | Task graph, analysis, frontmatter |
|
|
|
|
Remove:
|
|
- `graphql-yoga` row (source now in `@alkdev/pubsub`)
|
|
|
|
Update:
|
|
- `graphology` row: note it's now a transitive dep of `@alkdev/taskgraph`, no longer a direct dep of this project
|
|
|
|
**Workspace Structure** — Remove `core/` package:
|
|
```
|
|
packages/
|
|
hub/ — Hono API server, storage (Drizzle+Postgres), auth, coordination, Redis events
|
|
spoke/ — Self-registering runner: websocket connection, dispatch, operation provider
|
|
```
|
|
|
|
Add note about external dependencies:
|
|
```
|
|
External @alkdev packages (npm):
|
|
@alkdev/operations — Operations registry, call protocol, MCP adapter, ResponseEnvelope
|
|
@alkdev/pubsub — PubSub, event targets (Redis/WS/Worker), operators
|
|
@alkdev/taskgraph — Task graph construction, analysis, frontmatter
|
|
```
|
|
|
|
**Constraints section** — Add:
|
|
- `@alkdev/pubsub`, `@alkdev/operations`, `@alkdev/taskgraph` are the canonical implementations — do not duplicate their code in-repo
|
|
|
|
### 2.2 overview.md — Major Update
|
|
|
|
**"What Exists" section** — Replace entirely:
|
|
|
|
| Module | Location | Status |
|
|
|--------|----------|--------|
|
|
| Operations system | `@alkdev/operations` | Published v0.1.0 |
|
|
| PubSub (createPubSub + operators) | `@alkdev/pubsub` | Published v0.1.0 |
|
|
| TypedEventTarget | `@alkdev/pubsub` | Published v0.1.0 |
|
|
| Redis EventTarget | `@alkdev/pubsub` | Published v0.1.0 |
|
|
| WebSocket EventTarget (client+server) | `@alkdev/pubsub` | Published v0.1.0 |
|
|
| Worker EventTarget | `@alkdev/pubsub` | Published v0.1.0 |
|
|
| MCP client adapter | `@alkdev/operations/from-mcp` | Published v0.1.0 |
|
|
| Call protocol (PendingRequestMap, CallHandler) | `@alkdev/operations` | Published v0.1.0 |
|
|
| Access control (enforceAccess) | `@alkdev/operations` | Published v0.1.0 |
|
|
| ResponseEnvelope | `@alkdev/operations` | Published v0.1.0 |
|
|
| SchemaAdapter (Zod/Valibot) | `@alkdev/operations/from-typemap` | Published v0.1.0 |
|
|
| SSE subscription handling | `@alkdev/operations/from-openapi` | Published v0.1.0 |
|
|
| Task graph + analysis | `@alkdev/taskgraph` | Published v0.0.2 |
|
|
| Config types | `packages/core/` | Stub — needs relocation |
|
|
| Logger | `packages/core/` | Stub — needs relocation |
|
|
|
|
**"What Needs Implementation"** — Remove completed items, keep remaining:
|
|
|
|
| Component | Spec | Priority |
|
|
|-----------|------|----------|
|
|
| ~~WebSocket EventTarget~~ | ~~spoke-runner.md~~ | ~~High~~ — **Done: `@alkdev/pubsub`** |
|
|
| ~~Call protocol (PendingRequestMap)~~ | ~~call-graph.md~~ | ~~High~~ — **Done: `@alkdev/operations`** |
|
|
| Storage (Drizzle+Postgres tables, migrations) | storage/ | High |
|
|
| Hub HTTP server (Hono) | hub-architecture.md | High |
|
|
| OpenAI proxy (Hono) | agent-sessions.md | High |
|
|
| Logger configuration | — | Medium |
|
|
| Hub config system | hub-config.md | Medium |
|
|
| MCP server (@hono/mcp) | mcp-server.md | Medium |
|
|
| Agent sessions (AI SDK) | agent-sessions.md | Medium |
|
|
| Coordination operations | coordination.md | Medium |
|
|
| Call graph storage | call-graph.md, storage/ | Medium |
|
|
| Operation graph | call-graph.md | Low |
|
|
| Call templates | call-graph.md | Low |
|
|
|
|
### 2.3 packages.md — Major Rewrite
|
|
|
|
**Remove `@alkhub/core` section entirely.** Add a new section for external `@alkdev/*` packages:
|
|
|
|
```
|
|
### `@alkdev/operations` (npm package)
|
|
|
|
Operations registry, call protocol, MCP adapter, ResponseEnvelope. Platform-agnostic.
|
|
|
|
Exports:
|
|
. — types, registry, call protocol (PendingRequestMap, buildCallHandler), subscribe, access control, error, env, scanner, validation, from_schema, response-envelope
|
|
./from-mcp — MCP tool adapter (ioredis optional peer)
|
|
./from-typemap — Zod/Valibot schema adapters (@alkdev/typemap optional peer)
|
|
./from-openapi — OpenAPI/SSE/HTTP service adapter
|
|
|
|
### `@alkdev/pubsub` (npm package)
|
|
|
|
PubSub, event targets, operators. Platform-agnostic.
|
|
|
|
Exports:
|
|
. — createPubSub, types, operators, repeater
|
|
./event-target-redis — Redis adapter (ioredis optional peer)
|
|
./event-target-websocket-client — Spoke-side WebSocket adapter
|
|
./event-target-websocket-server — Hub-side WebSocket adapter
|
|
./event-target-worker — Web Worker adapter (host + thread)
|
|
|
|
### `@alkdev/taskgraph` (npm package)
|
|
|
|
Task graph construction, analysis, frontmatter. Platform-agnostic.
|
|
|
|
Exports:
|
|
. — TaskGraph, analysis functions, schema, error types, frontmatter
|
|
```
|
|
|
|
**`@alkhub/hub` dependencies**: Add `@alkdev/operations`, `@alkdev/pubsub`, `@alkdev/taskgraph`. Remove `@repeaterjs/repeater` (inlined). Update: `ioredis` is optional (only if Redis ET is used directly; the package uses it).
|
|
|
|
**`@alkhub/spoke` dependencies**: Add `@alkdev/operations`, `@alkdev/pubsub`.
|
|
|
|
**Rules section** — Update rule 1: "core is transport-agnostic" becomes "packages should be transport-agnostic". Remove rule about core being persistence-agnostic (hub still is). Update dependency direction:
|
|
|
|
```
|
|
spoke → @alkdev/operations, @alkdev/pubsub
|
|
hub → @alkdev/operations, @alkdev/pubsub, @alkdev/taskgraph
|
|
hub ←/→ spoke (communicate via call protocol over WebSocket)
|
|
```
|
|
|
|
### 2.4 call-graph.md — Significant Update
|
|
|
|
**PendingRequestMap section** — Replace the schematic with actual `@alkdev/operations` API:
|
|
|
|
```ts
|
|
// From @alkdev/operations
|
|
import { PendingRequestMap } from "@alkdev/operations"
|
|
|
|
const prm = new PendingRequestMap({ eventTarget })
|
|
await prm.call(operationId, input, { deadline, identity })
|
|
const stream = prm.subscribe(operationId, input, { idleTimeout, identity })
|
|
prm.respond(requestId, output) // output must be ResponseEnvelope
|
|
prm.emitError(requestId, code, message, details?)
|
|
prm.complete(requestId)
|
|
prm.abort(requestId)
|
|
```
|
|
|
|
Key API differences from the doc:
|
|
- `call()` returns `Promise<ResponseEnvelope>` (not `Promise<unknown>`)
|
|
- `subscribe()` returns `AsyncIterable<ResponseEnvelope>`
|
|
- `respond()` requires output to be a `ResponseEnvelope`
|
|
- Deadline and idle timeout are built in
|
|
- Constructor takes optional `EventTarget` for pluggable transport
|
|
|
|
**CallHandler section** — Reference `buildCallHandler` from `@alkdev/operations`:
|
|
|
|
```ts
|
|
import { buildCallHandler } from "@alkdev/operations"
|
|
const handler = buildCallHandler({ registry, eventTarget })
|
|
```
|
|
|
|
**buildEnv section** — Remove `callMap` parameter. In `@alkdev/operations`, `buildEnv`:
|
|
- No longer takes `callMap` — uses `PendingRequestMap` internally
|
|
- Sets `trusted: true` on nested context
|
|
- Returns env functions that return `Promise<ResponseEnvelope>`
|
|
|
|
**Dependencies section** — Replace graphology direct deps. Graphology is now a transitive dependency through `@alkdev/taskgraph`. Call graph storage still uses graphology for runtime operations but should prefer `@alkdev/taskgraph`'s `TaskGraph` class when applicable.
|
|
|
|
### 2.5 operations.md — Major Rewrite
|
|
|
|
This doc needs significant restructuring since most of what it describes is now in `@alkdev/operations`.
|
|
|
|
**Key changes**:
|
|
- Remove "In-repo location: `packages/core/operations/`" — now external package
|
|
- Component descriptions should reference `@alkdev/operations` exports
|
|
- Schema Adapters section: Replace raw `@alkdev/typemap` dynamic import description with `SchemaAdapter` pattern
|
|
- Remove SSE Subscription Handler Fix from open issues — fixed in `@alkdev/operations/from-openapi`
|
|
- Update Call Protocol Integration section to reference `@alkdev/operations` API
|
|
- Add ResponseEnvelope concept (universal result wrapper: local/http/mcp)
|
|
- Add CallError/InfrastructureErrorCode concept
|
|
- Update access control: `enforceAccess` is now in the package, with `trusted` bypass
|
|
|
|
**New concepts to document**:
|
|
- `ResponseEnvelope<T>` with source discriminant (`"local"` | `"http"` | `"mcp"`)
|
|
- `subscribe()` helper for subscription operations
|
|
- `ScannerFS` interface (Deno runtime agnostic)
|
|
- `OpenAPIServiceRegistry` class for managing HTTP services
|
|
- `parseSSEFrames()` for SSE subscription handling
|
|
|
|
### 2.6 pubsub-redis.md — Major Rewrite
|
|
|
|
This doc describes code that's now in `@alkdev/pubsub`. Key changes:
|
|
|
|
- **Source location**: `@alkdev/pubsub` npm package, not `packages/core/pubsub/`
|
|
- **createPubSub API**: Uses `PubSubEventMap` (simple `{ [eventType: string]: payload }`) not `PubSubPublishArgsByKey`
|
|
- **EventEnvelope**: New concept — `{ type, id, payload }` is the cross-process message format. Reserved `__` prefix for control messages.
|
|
- **Redis EventTarget**: Now accepts `prefix` option (e.g., `"alk:events:"`) and has `close()` method. No need for serializer workaround to add prefix.
|
|
- **WebSocket EventTarget**: No longer "Not started" / "Deferred". Document both client and server adapters.
|
|
- **Worker EventTarget**: New adapter for Web Workers (host + thread).
|
|
- **Operators**: 13 operators, not 3. New: `take`, `reduce`, `toArray`, `batch`, `dedupe`, `window`, `flat`, `groupBy`, `chain`, `join`.
|
|
- **Repeater**: Inlined, no longer depends on `@repeaterjs/repeater` externally.
|
|
- **Prior Art section**: Update to reflect `@alkdev/pubsub` is a standalone package, not forked code in-repo.
|
|
|
|
### 2.7 storage/tasks.md — Update Graphology Section
|
|
|
|
**"Graphology Integration" section** — Replace direct graphology usage with `@alkdev/taskgraph`:
|
|
|
|
Instead of:
|
|
```
|
|
1. Load all tasks + task_dependencies rows for a project from the DB
|
|
2. Build a graphology DirectedGraph in memory
|
|
3. Run graph algorithms as needed
|
|
```
|
|
|
|
Use:
|
|
```
|
|
1. Load all tasks + task_dependencies rows for a project from the DB
|
|
2. Build a TaskGraph via TaskGraph.fromRecords(tasks, edges)
|
|
3. Run analysis functions as needed (criticalPath, parallelGroups, bottlenecks, riskPath, etc.)
|
|
```
|
|
|
|
**Frontmatter parsing** — Reference `@alkdev/taskgraph`'s `parseFrontmatter` and `serializeFrontmatter` functions instead of custom parsers. Note: `parseTaskFile` and `parseTaskDirectory` are Node.js only (use `node:fs/promises`).
|
|
|
|
**References section** — Update graphology reference to point to `@alkdev/taskgraph` package.
|
|
|
|
**NAPI note** — The doc says "Why not taskgraph NAPI for v1". This is now resolved: `@alkdev/taskgraph` is pure TypeScript (graphology-based), and the Rust CLI (`taskgraph`) is for offline analysis. The TS package handles runtime graph ops.
|
|
|
|
### 2.8 hub-architecture.md — Update Component Table
|
|
|
|
- Operations row: `@alkdev/operations` not `core/operations/`
|
|
- PubSub row: `@alkdev/pubsub` not `core/pubsub/`
|
|
- Call protocol row: `@alkdev/operations` not `core/` (see call-graph.md)
|
|
- WebSocket adapter: "pending" → "available in `@alkdev/pubsub`"
|
|
|
|
### 2.9 hub-config.md — Update Redis EventTarget Example
|
|
|
|
Update `createRedisEventTarget` example to include `prefix`:
|
|
|
|
```ts
|
|
createRedisEventTarget({
|
|
publishClient,
|
|
subscribeClient,
|
|
prefix: "alk:events:",
|
|
})
|
|
```
|
|
|
|
### 2.10 hub-startup.md — Update References
|
|
|
|
- PendingRequestMap + CallHandler: note these come from `@alkdev/operations`
|
|
- PubSub setup: reference `@alkdev/pubsub` with `prefix` option
|
|
|
|
### 2.11 spoke-runner.md — Update References
|
|
|
|
- WebSocketEventTarget: `@alkdev/pubsub/event-target-websocket-client`
|
|
- PendingRequestMap: `@alkdev/operations`
|
|
- Scanner: `@alkdev/operations` with `ScannerFS` Deno adapter
|
|
- SchemaAdapters: `@alkdev/operations/from-typemap`
|
|
- `FromSchema()` / `FromOpenAPI()`: `@alkdev/operations/from-schema` / `@alkdev/operations/from-openapi`
|
|
|
|
### 2.12 ADR-013 — Update Paths
|
|
|
|
- Update `packages/core/operations/scanner.ts` references to `@alkdev/operations/scanner`
|
|
- Update `packages/core/operations/from_schema.ts` references to `@alkdev/operations/from_schema`
|
|
- Update `packages/core/operations/from_openapi.ts` references to `@alkdev/operations/from_openapi`
|
|
- Update scanner enhancement task to reference `SchemaAdapter` pattern from `@alkdev/operations/from-typemap`
|
|
|
|
### 2.13 docs/research/migration/ — Update or Archive
|
|
|
|
Both `operations.md` and `pubsub.md` in this directory describe planned extractions that are now **complete**. Options:
|
|
- **Archive**: Move to `docs/research/migration/completed/` with a status note
|
|
- **Update**: Rewrite as "completed migration" docs showing before/after
|
|
|
|
Recommend: Archive both. They served their purpose and the current API surface is documented in the `@alkdev/*` package READMEs and this review.
|
|
|
|
### 2.14 docs/reviews/docs-consistency-review-2026-04-17.md — Superseded Entries
|
|
|
|
Several findings from the previous review are now resolved by the extractions:
|
|
|
|
| Finding | Original Issue | Resolution |
|
|
|---------|---------------|------------|
|
|
| C5 | PendingRequestMap is in core, not hub | **Resolved**: Now in `@alkdev/operations` |
|
|
| I2 | `env.ts` has PendingRequestMap interface only | **Resolved**: Full implementation in `@alkdev/operations` |
|
|
| I5 | `OperationContext.pubsub` typed as unknown | **Resolved**: `pubsub` field removed from context in `@alkdev/operations` |
|
|
| I6 | `OperationContext.stream` never populated | **Resolved**: `stream` field removed from context in `@alkdev/operations` |
|
|
| I7 | `@repeaterjs/repeater` version mismatch risk | **Resolved**: Inlined in `@alkdev/pubsub`, no external dep |
|
|
|
|
---
|
|
|
|
## 3. What's Now Unblocked
|
|
|
|
| Component | Previous Status | Now Available In |
|
|
|-----------|-----------------|------------------|
|
|
| Call protocol (PendingRequestMap, CallHandler) | Not started | `@alkdev/operations` |
|
|
| WebSocket transport (client + server) | Not started | `@alkdev/pubsub` |
|
|
| WebSocket connection management (backpressure, SpokeEventTarget) | Not started | `@alkdev/pubsub` |
|
|
| Access control enforcement (checkAccess, enforceAccess) | Not started | `@alkdev/operations` |
|
|
| Task graph operations (topo sort, cycles, critical path, risk) | Not started | `@alkdev/taskgraph` |
|
|
| ResponseEnvelope (source tracking) | Not started | `@alkdev/operations` |
|
|
| Schema conversion (Zod/Valibot) | Not started | `@alkdev/operations/from-typemap` |
|
|
| SSE subscription handling | Broken | `@alkdev/operations/from-openapi` |
|
|
| Error model (CallError, InfrastructureErrorCode) | Not started | `@alkdev/operations` |
|
|
| EventEnvelope (structured cross-process messages) | Not started | `@alkdev/pubsub` |
|
|
|
|
## 4. What Still Needs Implementation
|
|
|
|
All of these are hub or spoke level concerns that can now be built on top of the extracted packages:
|
|
|
|
| Component | Depends On | Spec |
|
|
|-----------|------------|------|
|
|
| Storage (Drizzle+Postgres tables, migrations) | `@alkdev/typebox`, `@alkdev/drizzlebox`, `drizzle-orm` | storage/ |
|
|
| Hub HTTP server (Hono) | `@alkdev/operations`, `@alkdev/pubsub`, `hono` | hub-architecture.md |
|
|
| Spoke WebSocket client | `@alkdev/operations`, `@alkdev/pubsub/event-target-websocket-client` | spoke-runner.md |
|
|
| Hub WebSocket server (spoke management) | `@alkdev/operations`, `@alkdev/pubsub/event-target-websocket-server` | spoke-runner.md |
|
|
| OpenAI proxy | `hono`, AI SDK | agent-sessions.md |
|
|
| Auth (keypal) | Hono middleware | — |
|
|
| MCP server (@hono/mcp) | `@alkdev/operations`, `@hono/mcp` | mcp-server.md |
|
|
| Agent sessions (AI SDK) | `@alkdev/operations`, AI SDK, storage | agent-sessions.md |
|
|
| Coordination operations | `@alkdev/operations`, storage | coordination.md |
|
|
| Call graph storage | `@alkdev/operations`, storage | storage/call-graph.md |
|
|
| Hub config loader | `@alkdev/operations` (config types) | hub-config.md |
|
|
| Logger configuration | logtape | — |
|
|
|
|
---
|
|
|
|
## 5. Package Dependency Graph (New)
|
|
|
|
```
|
|
@alkdev/operations → @alkdev/typebox, @alkdev/pubsub, @logtape/logtape
|
|
→ (optional peers): @alkdev/typemap, @modelcontextprotocol/sdk
|
|
|
|
@alkdev/pubsub → (no runtime deps)
|
|
→ (optional peer): ioredis (for ./event-target-redis)
|
|
|
|
@alkdev/taskgraph → @alkdev/typebox, graphology (+plugins), yaml
|
|
|
|
@alkhub/hub → @alkdev/operations, @alkdev/pubsub, @alkdev/taskgraph,
|
|
@alkdev/typebox, @alkdev/drizzlebox, hono, drizzle-orm,
|
|
ioredis, ai, keypal, logtape, @hono/mcp
|
|
|
|
@alkhub/spoke → @alkdev/operations, @alkdev/pubsub, @alkdev/typebox, logtape
|
|
```
|
|
|
|
No `@alkhub/core` package. Config types, logger, and crypto utils live in `@alkhub/hub` (or a thin shared package if spokes need config types — this can be decided when implementing the spoke).
|
|
|
|
---
|
|
|
|
## 6. Open Decisions
|
|
|
|
### 6.1 Where do config types go?
|
|
|
|
`core/config/types.ts` has `HubConfig`, `SpokeConfig`, `BaseConfig`, `PostgresConfig`, `RedisConfig`, `HttpConfig`, `AuthConfig`. These are used by both hub and spoke.
|
|
|
|
Options:
|
|
- **A**: Move to `@alkhub/hub`. Spokes that need config types import them from their own copy or a minimal `@alkhub/config` package.
|
|
- **B**: Create `@alkdev/config` npm package. Platform-agnostic like the other `@alkdev/*` packages.
|
|
- **C**: Put config types in `@alkdev/operations`. They're already TypeBox schemas and operations already depend on `@alkdev/typebox`.
|
|
|
|
**Recommendation**: A for now. First spokes won't need hub config. Re-evaluate when a spoke actually needs shared config types. The spoke config types are already minimal (`SpokeConfig` has `hub.url` and `hub.auth.tokenFile`).
|
|
|
|
### 6.2 Logger and crypto?
|
|
|
|
`core/logger/mod.ts` (27 lines) and `core/utils/crypto.ts` (119 lines) are hub-specific concerns. Move them into `@alkhub/hub` directly.
|
|
|
|
### 6.3 How to handle `ScannerFS` for Deno?
|
|
|
|
`@alkdev/operations` uses an abstract `ScannerFS` interface. The spoke needs a Deno adapter:
|
|
|
|
```ts
|
|
import { scanOperations } from "@alkdev/operations"
|
|
|
|
const DenoFS: ScannerFS = {
|
|
readdir: async (path) => Deno.readDir(path),
|
|
cwd: () => Deno.cwd(),
|
|
}
|
|
|
|
const operations = await scanOperations("./operations", DenoFS)
|
|
```
|
|
|
|
This is minimal (~3 lines) and can live in the spoke package.
|
|
|
|
### 6.4 Research migration docs?
|
|
|
|
`docs/research/migration/operations.md` and `docs/research/migration/pubsub.md` describe extraction plans that are now complete. They should be archived or removed — they're historical context, not current documentation.
|
|
|
|
### 6.5 Previous consistency review findings?
|
|
|
|
The `docs-consistency-review-2026-04-17.md` has several findings that are now resolved by the extractions (C5, I2, I5, I6, I7 at minimum). These should be marked resolved in that document or superseded by this review.
|
|
|
|
---
|
|
|
|
## 7. Suggested Execution Order
|
|
|
|
1. **Delete replaced code** from `packages/core/` (operations, pubsub, mcp dirs + their tests)
|
|
2. **Update `packages/core/deno.json`** — remove deleted exports and dependencies
|
|
3. **Relocate remaining core modules** (config, logger, crypto) into `packages/hub/`
|
|
4. **Remove `packages/core/`** from workspace
|
|
5. **Update architecture docs** (overview, packages, call-graph, operations, pubsub-redis as priority)
|
|
6. **Update AGENTS.md** — provenance, key patterns, reference deps, workspace structure
|
|
7. **Update storage/tasks.md** — taskgraph references
|
|
8. **Update secondary docs** (hub-architecture, hub-config, hub-startup, spoke-runner, ADR-013)
|
|
9. **Archive research/migration docs** or mark as completed
|
|
10. **Update docs-consistency-review-2026-04-17.md** — mark superseded findings as resolved |