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.
26 KiB
status, created, last_updated
| status | created | last_updated |
|---|---|---|
| open | 2026-05-18 | 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.tstyped_event_target.tsredis_event_target.tsoperators.tsmod.ts
core/operations/ — replaced by @alkdev/operations:
types.tsregistry.tsenv.tsscanner.tsvalidation.tsfrom_schema.tsfrom_openapi.tsmod.ts
core/mcp/ — replaced by @alkdev/operations/from-mcp:
wrapper.tsloader.tsmod.ts
Tests and fixtures — for deleted modules:
tests/operations/registry.test.tstests/operations/scanner.test.tstests/pubsub/redis_event_target.test.tstests/mcp/loader.test.tstests/fixtures/registry.tstests/fixtures/operations/demo/greet.tstests/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.jsonpackages/core/mod.ts- The
"core"entry from rootdeno.jsonworkspace array
1.4 Update dependency declarations
Root deno.json:
- Remove
"packages/core"from workspace array - Add
@alkdev/operations,@alkdev/pubsub,@alkdev/taskgraphto 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/operationspackage, add ResponseEnvelope and call protocol - PubSub: Reference
@alkdev/pubsubpackage, 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-yogarow (source now in@alkdev/pubsub)
Update:
graphologyrow: 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/taskgraphare 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 |
|---|---|---|
@alkdev/pubsub |
||
@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:
// 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()returnsPromise<ResponseEnvelope>(notPromise<unknown>)subscribe()returnsAsyncIterable<ResponseEnvelope>respond()requires output to be aResponseEnvelope- Deadline and idle timeout are built in
- Constructor takes optional
EventTargetfor pluggable transport
CallHandler section — Reference buildCallHandler from @alkdev/operations:
import { buildCallHandler } from "@alkdev/operations"
const handler = buildCallHandler({ registry, eventTarget })
buildEnv section — Remove callMap parameter. In @alkdev/operations, buildEnv:
- No longer takes
callMap— usesPendingRequestMapinternally - Sets
trusted: trueon 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/operationsexports - Schema Adapters section: Replace raw
@alkdev/typemapdynamic import description withSchemaAdapterpattern - Remove SSE Subscription Handler Fix from open issues — fixed in
@alkdev/operations/from-openapi - Update Call Protocol Integration section to reference
@alkdev/operationsAPI - Add ResponseEnvelope concept (universal result wrapper: local/http/mcp)
- Add CallError/InfrastructureErrorCode concept
- Update access control:
enforceAccessis now in the package, withtrustedbypass
New concepts to document:
ResponseEnvelope<T>with source discriminant ("local"|"http"|"mcp")subscribe()helper for subscription operationsScannerFSinterface (Deno runtime agnostic)OpenAPIServiceRegistryclass for managing HTTP servicesparseSSEFrames()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/pubsubnpm package, notpackages/core/pubsub/ - createPubSub API: Uses
PubSubEventMap(simple{ [eventType: string]: payload }) notPubSubPublishArgsByKey - EventEnvelope: New concept —
{ type, id, payload }is the cross-process message format. Reserved__prefix for control messages. - Redis EventTarget: Now accepts
prefixoption (e.g.,"alk:events:") and hasclose()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/repeaterexternally. - Prior Art section: Update to reflect
@alkdev/pubsubis 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/operationsnotcore/operations/ - PubSub row:
@alkdev/pubsubnotcore/pubsub/ - Call protocol row:
@alkdev/operationsnotcore/(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:
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/pubsubwithprefixoption
2.11 spoke-runner.md — Update References
- WebSocketEventTarget:
@alkdev/pubsub/event-target-websocket-client - PendingRequestMap:
@alkdev/operations - Scanner:
@alkdev/operationswithScannerFSDeno 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.tsreferences to@alkdev/operations/scanner - Update
packages/core/operations/from_schema.tsreferences to@alkdev/operations/from_schema - Update
packages/core/operations/from_openapi.tsreferences to@alkdev/operations/from_openapi - Update scanner enhancement task to reference
SchemaAdapterpattern 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/configpackage. - B: Create
@alkdev/confignpm 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:
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
- Delete replaced code from
packages/core/(operations, pubsub, mcp dirs + their tests) - Update
packages/core/deno.json— remove deleted exports and dependencies - Relocate remaining core modules (config, logger, crypto) into
packages/hub/ - Remove
packages/core/from workspace - Update architecture docs (overview, packages, call-graph, operations, pubsub-redis as priority)
- Update AGENTS.md — provenance, key patterns, reference deps, workspace structure
- Update storage/tasks.md — taskgraph references
- Update secondary docs (hub-architecture, hub-config, hub-startup, spoke-runner, ADR-013)
- Archive research/migration docs or mark as completed
- Update docs-consistency-review-2026-04-17.md — mark superseded findings as resolved