An MCP server container is long-lived and restarts forever; an agent session pod
is the opposite — it does a unit of work and dies. ContainerSpec could not
express that: restartPolicy was hardcoded 'Always' in generatePodSpec, and there
were no volume, workdir, or init-container fields at all.
Adds four optional fields to ContainerSpec (restartPolicy, workdir, volumes,
initContainers) and implements them in both backends. All optional, so every
existing caller is byte-identical — generatePodSpec still emits 'Always' unless
asked otherwise, and omits volumes/initContainers keys entirely when unused.
Kubernetes gets this nearly free: initContainers run to completion in
declaration order before any app container starts, so "clone the repos, then
work them" needs no sequencing logic from us. generateDeploymentSpec
deliberately ignores spec.restartPolicy — k8s rejects anything but 'Always' on a
Deployment pod template — and says so in a comment.
Docker has no init containers, so they are emulated as sequential runs sharing
the same volumes. The important property is the failure path: a non-zero init
exit aborts BEFORE the main container is created, and the error carries the init
container's last 50 log lines. Otherwise a failed git clone would leave an empty
workspace that looks exactly like a successful one, and the agent would start
work against nothing. Named Docker volumes are namespaced by container name to
stand in for emptyDir.
Tests: 10 k8s manifest tests (defaults unchanged, each restart policy, volume
and mount emission, init ordering, name sanitization, security context still
hardened) and 9 Docker tests including the abort-before-main case and log
propagation.
Local: build clean, workspace 2310 passed (+19), lint unchanged at the repo's
pre-existing 869.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N4wNHWf7xSwnZCWpJcyv9p
Adds the foundation entities from docs/agentic-teams.md §5/§7: a versioned
vision layer (Epic -> EpicTask -> Task), git repositories attached to projects,
agents as many-to-many project members, and the ephemeral session that IS an
agent's workspace.
9 tables + 5 enums, purely additive — no drops and no column changes on
existing tables, since every new relation is held on the new side.
Shape notes:
- EpicTask chaining uses an explicit EpicTaskEdge table rather than a
self-referencing array, so the roadmap graph walks in both directions and
edges can carry a type later.
- TaskVerdict is commit-pinned and immutable: "QA verified 3f2ab" stays
reproducible, which is what lets later coverage claims be audited rather than
believed. TaskEvent is the append-only transition log.
- Task survives losing its repo and its assignee (both SetNull) — a work item
outlives whoever happened to be working it — but cascades from its EpicTask.
- CodeRepo, not Repository: `repository.repository.ts` next to 24 other
*.repository.ts data-access files would be actively confusing. CLI resource is
`repos`, with repo/repository/repositories aliased onto it.
- AgentProject.llmId exists so the brain-ownership question
(docs/agentic-teams.md §15 Q1) can be settled either way without a migration.
- Agent.projectId is retained and coexists with AgentProject for one release so
findByProjectId / prepareContext keep working. Note this partially reverses
20260223120000_remove_project_members — deliberately, and only for agents;
human membership stays RBAC-driven.
No CHECK constraints anywhere, on purpose: deploy/entrypoint.sh provisions with
`prisma db push`, so hand-written migration SQL never runs in production. The
migration file is kept for local `migrate dev` parity and as a readable record,
and says so in its header. Invariants that cannot be expressed in the schema
(EpicTaskEdge cycle rejection) belong to the service layer; a schema test
documents that boundary rather than pretending the database enforces it.
Tests: 23 schema tests covering defaults, per-project name scoping, cascade vs
SetNull on every FK, all 12 lifecycle states, and the GC-sweep predicate.
clearAllTables extended for all 9 models.
Verified locally against postgres:16-alpine on :5433 — db suite 128 passed
(baseline was 105; the same 4 pre-existing Secret_backendId_fkey failures
remain, unrelated). Workspace 2291 passed, build clean, lint unchanged at the
repo's pre-existing 869.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N4wNHWf7xSwnZCWpJcyv9p
Converts docs/agentic-teams.md §16 steps 1-3 into a trackable PRD and 48
appended tasks (IDs 115-162) in the master tag. Steps 4-8 land as 5 low
priority placeholders wired onto the spine, pending the §15 open questions.
The PRD is grounded in the current codebase rather than the design doc's
indicative sketches, which changed the shape of the work:
- RBAC `tasks` is already owned by the inference queue, and bindings are
normalized at parse time, so existing RbacDefinition rows literally hold
"tasks". Taking the name for work items needs a one-shot guarded backfill
to `inference-tasks` (task 116).
- deploy/entrypoint.sh uses `prisma db push`, so migration SQL never runs in
production. Invariants are service-layer, not CHECK constraints.
- Ephemeral pods do not exist: restartPolicy is hardcoded Always and
ContainerSpec has no volume/workdir fields (tasks 140-142).
- `exec` is cheap: KubernetesOrchestrator already implements exec/attach over
k8s.Exec/k8s.Attach; only an API + CLI surface is missing (tasks 144-145).
- No git provider client exists in product code (task 148).
- ChatService caps its tool loop at 12 iterations, so the AgentRuntime runs a
headless coding agent in-pod rather than extending chat (tasks 146-147).
Names the git-repo entity CodeRepo (CLI `repos`) to avoid colliding with the
repository/ data-access layer; AgentProject carries an optional llmId so the
brain-ownership question can be settled either way without a migration.
Generated task_*.md files are left untracked, matching how this repo has
treated them since the first commit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N4wNHWf7xSwnZCWpJcyv9p
- Add warmup() to LlmProvider interface for eager subprocess startup
- ManagedVllmProvider.warmup() starts vLLM in background on project load
- ProviderRegistry.warmupAll() triggers all managed providers
- NamedProvider proxies warmup() to inner provider
- paginate stage generates LLM-powered descriptive page titles when
available, cached by content hash, falls back to generic "Page N"
- project-mcp-endpoint calls warmupAll() on router creation so vLLM
is loading while the session initializes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the full gated session flow and prompt intelligence system:
- Prisma schema: add gated, priority, summary, chapters, linkTarget fields
- Session gate: state machine (gated → begin_session → ungated) with LLM-powered
tool selection based on prompt index
- Tag matcher: intelligent prompt-to-tool matching with project/server/action tags
- LLM selector: tiered provider selection (fast for gating, heavy for complex tasks)
- Link resolver: cross-project MCP resource references (project/server:uri format)
- Prompt summary service: LLM-generated summaries and chapter extraction
- System project bootstrap: ensures default project exists on startup
- Structural link health checks: enrichWithLinkStatus on prompt GET endpoints
- CLI: create prompt --priority/--link, create project --gated/--no-gated,
describe project shows prompts section, get prompts shows PRI/LINK/STATUS
- Apply/edit: priority, linkTarget, gated fields supported
- Shell completions: fish updated with new flags
- 1,253 tests passing across all packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add STDIO and HTTP upstream transports, McpRouter with tool namespacing
and discovery, and StdioProxyServer for aggregating multiple MCP servers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add validation schemas (Zod), repository pattern with Prisma, service layer
with business logic (NotFoundError, ConflictError), and REST routes for
MCP server and profile CRUD. 86 mcpd tests passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CLI entry point with Commander.js, config management (~/.mcpctl/config.json
with Zod validation), output formatters (table/json/yaml), config and status
commands with dependency injection for testing. Fix sanitizeString regex ordering.
67 tests passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add registry client that queries Official, Glama, and Smithery MCP
registries with caching, request deduplication, retry logic, and
result ranking/dedup. Includes 53 tests covering all components.
Also fix null priority values in cancelled tasks (19-21) that broke
Task Master, and add new tasks 25-27 for registry completion and
CLI discover/install commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>