docs(taskmaster): PRD + task graph for agentic teams foundation
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
This commit is contained in:
@@ -2549,16 +2549,710 @@
|
||||
"testStrategy": "1. Gate proxy model smoke test: identical behavior to current hardcoded gate (begin_session, tools/list filtering, ungating). 2. Composition test: model extending [gate, paginate] inherits both behaviors. 3. Conflict detection test: two parents intercepting same hook differently = compile-time error. 4. Discovery test: drop a .ts file in proxymodels dir, mcpctl get proxymodels shows it. 5. Existing smoke tests (proxy-pipeline.test.ts) pass unchanged after migration.",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-03-07T01:26:57.383Z"
|
||||
},
|
||||
{
|
||||
"id": "115",
|
||||
"title": "RBAC tasks namespace split and alias repoint",
|
||||
"description": "Split the RBAC 'tasks' resource into 'tasks' (work items) and 'inference-tasks', update RBAC_RESOURCES and RESOURCE_ALIASES in rbac-definition.schema.ts",
|
||||
"details": "In src/mcpd/src/validation/rbac-definition.schema.ts:\n1. Update RBAC_RESOURCES array to include: 'epics', 'epictasks', 'tasks', 'repos', 'sessions', 'inference-tasks'\n2. Update RESOURCE_ALIASES:\n - task → tasks (work items)\n - epic → epics\n - epictask → epictasks, et → epictasks\n - repo → repos, repository → repos, repositories → repos\n - session → sessions\n - inference-task → inference-tasks\n3. REMOVE the entry 'inference-tasks': 'tasks'\n4. Export normalizeResource unchanged (it uses the alias map)",
|
||||
"testStrategy": "Unit tests in src/mcpd/tests/validation/: verify normalizeResource('task') returns 'tasks', normalizeResource('inference-task') returns 'inference-tasks', normalizeResource('et') returns 'epictasks'. Test that RBAC_RESOURCES includes all new entries.",
|
||||
"priority": "high",
|
||||
"dependencies": [],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "116",
|
||||
"title": "One-shot RBAC binding backfill migration",
|
||||
"description": "Implement guarded startup migration to rewrite existing 'tasks' bindings to 'inference-tasks' so pre-existing grants continue authorizing inference endpoints",
|
||||
"details": "In src/mcpd/src/main.ts or a new bootstrap module:\n1. Read system settings from SYSTEM_SETTINGS_SECRET (see src/mcpd/src/bootstrap/system-settings.ts pattern)\n2. Check for boolean key 'rbacTasksBackfillComplete'\n3. If false/missing: iterate rbacRepo.findAll(), for each RbacDefinition row, rewrite roleBindings where resource === 'tasks' to resource: 'inference-tasks'\n4. Use rbacRepo.update() to persist changes\n5. Set 'rbacTasksBackfillComplete': true in system settings after completion\n6. Wildcard bindings (resource: '*') are untouched\n7. Model on migrateAdminRole pattern in main.ts",
|
||||
"testStrategy": "Unit test: create RbacDefinition with resource:'tasks', run backfill, verify resource changed to 'inference-tasks'. Test idempotency: run twice, verify no duplicate rewrites. Test wildcard unchanged.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"115"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "117",
|
||||
"title": "Add Epic, EpicTask, EpicTaskEdge Prisma models",
|
||||
"description": "Add Epic, EpicTask, EpicTaskEdge models with enums EpicStatus and EpicTaskStatus to schema.prisma following PRD specifications",
|
||||
"details": "In src/db/prisma/schema.prisma add:\n1. enum EpicStatus { open, delivered, delivered_with_tradeoffs, cancelled }\n2. enum EpicTaskStatus { todo, in_progress, done, cancelled }\n3. model Epic with: id, name, description, content (@db.Text), doneCriteria (Json), acceptedTradeoffs (Json), projectId, status, semver, currentRevisionId, ownerId, version, createdAt, updatedAt. Relations: project, owner (User), epicTasks[]. @@unique([name, projectId]), @@index([projectId]), @@index([name])\n4. model EpicTask with: id, name, description, epicId, doneCriteria (Json), status, ownerId, version, createdAt, updatedAt. Relations: epic, owner, tasks[], dependsOn (EpicTaskEdge[]), blocks (EpicTaskEdge[]). @@unique([name, epicId]), @@index([epicId])\n5. model EpicTaskEdge with: id, fromId, toId, createdAt. Relations using @relation names. @@unique([fromId, toId]), @@index([fromId]), @@index([toId])\n6. Add reverse relations to User and Project models",
|
||||
"testStrategy": "Schema tests in src/db/tests/: create Epic, verify unique constraint on (name, projectId), test cascade delete from Project, test EpicTask creation with Epic reference, test EpicTaskEdge uniqueness.",
|
||||
"priority": "high",
|
||||
"dependencies": [],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "118",
|
||||
"title": "Add Task, TaskVerdict, TaskEvent Prisma models",
|
||||
"description": "Add Task, TaskVerdict, TaskEvent models with enums TaskState and TaskRisk to schema.prisma for work item tracking",
|
||||
"details": "In src/db/prisma/schema.prisma add:\n1. enum TaskState { todo, in_progress, building, self_testing, qa_review, security_review, sre_review, done, awaiting_review, merged, reopened, cancelled }\n2. enum TaskRisk { trivial, normal, high }\n3. model Task with: id, name, title, description (@db.Text), epicTaskId, repoId?, assigneeId?, state, risk, branch?, headCommit?, prUrl?, prNumber?, reviewNote? (@db.Text), ownerId, version, createdAt, updatedAt. Relations: epicTask, repo (CodeRepo?), assignee (Agent?), owner, verdicts[], sessions[], events[]. @@unique([name, epicTaskId]), indexes on epicTaskId, state, assigneeId\n4. model TaskVerdict with: id, taskId, stage (TaskState), agentId?, commit, passed, summary (@db.Text), findings (Json), createdAt. Relations: task, agent. @@index([taskId]), @@index([taskId, stage])\n5. model TaskEvent with: id, taskId, fromState?, toState, actorType, actorId?, note? (@db.Text), createdAt. @@index([taskId, createdAt])\n6. Add reverse relations to Agent model (assignedTasks[], verdicts[])",
|
||||
"testStrategy": "Schema tests: create Task linked to EpicTask, verify cascade on EpicTask delete, test TaskVerdict immutability pattern, test TaskEvent append-only by creating multiple events for same task.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"117"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "119",
|
||||
"title": "Add CodeRepo Prisma model",
|
||||
"description": "Add CodeRepo model to schema.prisma for git repository management within projects",
|
||||
"details": "In src/db/prisma/schema.prisma add:\n1. model CodeRepo with: id, name, projectId, url, defaultBranch (@default(\"main\")), path (@default(\"\")), provider (@default(\"gitea\")), credSecretId?, credSecretKey?, ownerId, version, createdAt, updatedAt\n2. Relations: project (Project), cred (Secret?), owner (User), tasks (Task[])\n3. @@unique([name, projectId]), @@index([projectId])\n4. Add repos CodeRepo[] relation to Project model\n5. Add codeRepos CodeRepo[] relation to Secret model\n6. Add ownedRepos CodeRepo[] relation to User model",
|
||||
"testStrategy": "Schema tests: create CodeRepo linked to Project, verify unique constraint on (name, projectId), test cascade delete from Project, test SetNull behavior when Secret is deleted.",
|
||||
"priority": "high",
|
||||
"dependencies": [],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "120",
|
||||
"title": "Add AgentProject junction model",
|
||||
"description": "Add AgentProject many-to-many junction table linking Agents to Projects with role and optional LLM override",
|
||||
"details": "In src/db/prisma/schema.prisma add:\n1. model AgentProject with: id, agentId, projectId, role (@default(\"developer\")), llmId?, createdAt\n2. Relations: agent (Agent), project (Project), llm (Llm?)\n3. @@unique([agentId, projectId]), @@index([agentId]), @@index([projectId])\n4. Add projectMemberships AgentProject[] to Agent model\n5. Add agentMemberships AgentProject[] to Project model\n6. Add agentProjects AgentProject[] to Llm model\n7. Keep Agent.projectId for backward compatibility (one release)",
|
||||
"testStrategy": "Schema tests: create AgentProject junction, verify unique constraint prevents duplicate membership, test cascade on both Agent and Project delete, test SetNull on Llm delete.",
|
||||
"priority": "high",
|
||||
"dependencies": [],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "121",
|
||||
"title": "Add AgentSession Prisma model",
|
||||
"description": "Add AgentSession model with SessionState enum for ephemeral per-session pod tracking",
|
||||
"details": "In src/db/prisma/schema.prisma add:\n1. enum SessionState { pending, provisioning, running, ended, failed }\n2. model AgentSession with: id, agentId, projectId, taskId?, containerId?, state, image, expiresAt, lastError? (@db.Text), ownerId, createdAt, updatedAt, endedAt?\n3. Relations: agent (Agent), project (Project), task (Task?), owner (User)\n4. @@index([state]), @@index([taskId]), @@index([agentId])\n5. Add sessions AgentSession[] to Agent, Project, Task, User models",
|
||||
"testStrategy": "Schema tests: create AgentSession with all relations, test cascade on Agent/Project delete, test SetNull on Task delete, verify state enum transitions.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"118",
|
||||
"120"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "122",
|
||||
"title": "Update clearAllTables test helper",
|
||||
"description": "Add deleteMany calls for all new models to clearAllTables in src/db/tests/helpers.ts",
|
||||
"details": "In src/db/tests/helpers.ts clearAllTables function:\n1. Add deleteMany for TaskEvent (child first)\n2. Add deleteMany for TaskVerdict\n3. Add deleteMany for AgentSession\n4. Add deleteMany for Task\n5. Add deleteMany for EpicTaskEdge\n6. Add deleteMany for EpicTask\n7. Add deleteMany for Epic\n8. Add deleteMany for CodeRepo\n9. Add deleteMany for AgentProject\n10. Order matters: delete children before parents to avoid FK violations\n11. Follow existing pattern in the file",
|
||||
"testStrategy": "Run existing test suite to verify clearAllTables works correctly with new models. Add explicit test that creates rows in all new tables then calls clearAllTables and verifies tables are empty.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"117",
|
||||
"118",
|
||||
"119",
|
||||
"120",
|
||||
"121"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "123",
|
||||
"title": "Epic repository layer",
|
||||
"description": "Create EpicRepository in src/mcpd/src/repositories/ following existing repository patterns",
|
||||
"details": "Create src/mcpd/src/repositories/epic.repository.ts:\n1. Export EpicRepository class following agent.repository.ts pattern\n2. Methods: create, findById, findByName, findByProjectId, findAll, update, delete\n3. update must increment version (optimistic concurrency)\n4. Include relations in queries where needed (epicTasks, project, owner)\n5. Add type exports for CreateEpicData, UpdateEpicData\n6. Register in repository index file",
|
||||
"testStrategy": "Unit tests in src/mcpd/tests/repositories/: test CRUD operations, test optimistic concurrency version increment, test findByProjectId filtering, test cascade behavior.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"117"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "124",
|
||||
"title": "Epic service layer with revision integration",
|
||||
"description": "Create EpicService with CRUD operations, revision tracking via ResourceRevision, and done-criteria roll-up logic",
|
||||
"details": "Create src/mcpd/src/services/epic.service.ts:\n1. Inject EpicRepository, ResourceRevisionRepository, ProjectRepository\n2. create(): validate project exists, create Epic, create initial ResourceRevision with resourceType:'epic'\n3. update(): bump semver, create ResourceRevision, update currentRevisionId\n4. getById(), getByName(), listByProject()\n5. addTradeoff(): append to acceptedTradeoffs JSON array\n6. computeStatus(): roll up EpicTask completion to determine if Epic is delivered/delivered_with_tradeoffs\n7. getRoadmap(): return epictask graph with per-node completeness percentages\n8. Follow PromptService pattern for revision integration",
|
||||
"testStrategy": "Unit tests: test create writes revision, test update bumps semver and writes revision, test addTradeoff appends correctly, test computeStatus logic for all EpicStatus values.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"123"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "125",
|
||||
"title": "Epic zod validation schemas",
|
||||
"description": "Create Epic validation schemas in src/mcpd/src/validation/ for request/response validation",
|
||||
"details": "Create src/mcpd/src/validation/epic.schema.ts:\n1. DoneCriterionSchema: z.object({ id: z.string(), text: z.string(), kind: z.enum(['outcome', 'quality']), met: z.boolean() })\n2. AcceptedTradeoffSchema: z.object({ what: z.string(), why: z.string(), who: z.string(), deScopedBy: z.string().optional(), at: z.string() })\n3. CreateEpicSchema: name, content, doneCriteria (array), projectId or project (name), description optional\n4. UpdateEpicSchema: partial of create fields plus status\n5. EpicResponseSchema for API responses\n6. Follow prompt.schema.ts patterns",
|
||||
"testStrategy": "Unit tests: validate CreateEpicSchema accepts valid input, rejects missing required fields, validates doneCriteria array structure, validates status enum values.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"117"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "126",
|
||||
"title": "Epic routes and API endpoints",
|
||||
"description": "Create Epic routes in src/mcpd/src/routes/ with CRUD endpoints plus roadmap and tradeoffs",
|
||||
"details": "Create src/mcpd/src/routes/epic.routes.ts:\n1. GET /api/v1/epics - list with ?project=<name> filter\n2. POST /api/v1/epics - create, resolve project name to id\n3. GET /api/v1/epics/:id - get by id\n4. PUT /api/v1/epics/:id - update\n5. DELETE /api/v1/epics/:id - delete\n6. GET /api/v1/epics/:id/roadmap - return epictask graph with completeness\n7. POST /api/v1/epics/:id/tradeoffs - append accepted tradeoff\n8. Register routes in main.ts\n9. Follow agent-routes.ts pattern for auth and validation",
|
||||
"testStrategy": "Route tests in src/mcpd/tests/routes/: test CRUD endpoints, test project name resolution, test roadmap returns graph structure, test tradeoffs append correctly.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"124",
|
||||
"125"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "127",
|
||||
"title": "EpicTask repository and service layers",
|
||||
"description": "Create EpicTaskRepository and EpicTaskService with edge graph management and cycle detection",
|
||||
"details": "Create src/mcpd/src/repositories/epic-task.repository.ts and src/mcpd/src/services/epic-task.service.ts:\n1. Repository: CRUD for EpicTask, edge CRUD for EpicTaskEdge, findByEpicId\n2. Service.addEdge(): before creating edge, walk toId's transitive dependencies (via dependsOn edges), reject if fromId is reachable (cycle detection)\n3. Service.removeEdge(): simple delete\n4. Service.getGraph(): return nodes with edges for visualization\n5. Service.computeCompleteness(): calculate percentage of doneCriteria met per node\n6. Follow existing repository/service patterns",
|
||||
"testStrategy": "Unit tests: test edge creation, test cycle detection rejects A→B→C→A, test completeness calculation with mixed met/unmet criteria, test transitive dependency walk.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"117",
|
||||
"123"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "128",
|
||||
"title": "EpicTask routes and API endpoints",
|
||||
"description": "Create EpicTask routes with CRUD and edge management endpoints",
|
||||
"details": "Create src/mcpd/src/routes/epic-task.routes.ts:\n1. GET /api/v1/epictasks - list with ?epic=<name>&project=<name> filters\n2. POST /api/v1/epictasks - create\n3. GET /api/v1/epictasks/:id - get\n4. PUT /api/v1/epictasks/:id - update\n5. DELETE /api/v1/epictasks/:id - delete\n6. POST /api/v1/epictasks/:id/edges - add dependency edge { toId }\n7. DELETE /api/v1/epictasks/:id/edges - remove edge { toId }\n8. Register in main.ts",
|
||||
"testStrategy": "Route tests: test CRUD, test edge creation returns error on cycle, test edge deletion, test filters work correctly.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"127"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "129",
|
||||
"title": "Task repository with compare-and-swap transitions",
|
||||
"description": "Create TaskRepository with optimistic locking state transitions using updateMany with where clause",
|
||||
"details": "Create src/mcpd/src/repositories/task.repository.ts:\n1. Standard CRUD methods following existing patterns\n2. transition(id, fromState, toState): use prisma.task.updateMany({ where: { id, state: fromState }, data: { state: toState, version: { increment: 1 } } }), return affected count\n3. If affected count is 0, the transition failed (race or wrong state)\n4. findByFilters(): support epicTaskId, state, assigneeId filters\n5. Include verdict and event relations where appropriate",
|
||||
"testStrategy": "Unit tests: test transition succeeds when state matches, test transition returns 0 when state doesn't match (simulating race), test concurrent transitions only one wins.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"118"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "130",
|
||||
"title": "Task service with lifecycle state machine",
|
||||
"description": "Create TaskService implementing the full task lifecycle with transition guards and event logging",
|
||||
"details": "Create src/mcpd/src/services/task.service.ts:\n1. Define VALID_TRANSITIONS map: { [fromState]: [allowedToStates] } based on PRD lifecycle diagram\n2. transition(id, toState, actorType, actorId, note): check transition is valid, call repo.transition, if success create TaskEvent, return result\n3. assign(id, agentId): set assigneeId\n4. recordVerdict(id, stage, agentId, commit, passed, summary, findings): create TaskVerdict, if failed transition back to in_progress\n5. accept(id, userId, note): transition to merged, trigger merge via GitProvider\n6. reject(id, userId, note): transition to in_progress\n7. reopenOnPostMergeFailure(id): transition merged→reopened",
|
||||
"testStrategy": "Unit tests: test all valid transitions succeed, test invalid transitions throw, test TaskEvent created on every transition, test verdict creation, test accept triggers merge.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"129"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "131",
|
||||
"title": "Task routes and API endpoints",
|
||||
"description": "Create Task routes with CRUD, transition, verdict, accept/reject, and events endpoints",
|
||||
"details": "Create src/mcpd/src/routes/task.routes.ts:\n1. GET /api/v1/tasks - list with ?project=&epictask=&state=&assignee= filters\n2. POST /api/v1/tasks - create\n3. GET /api/v1/tasks/:id - get\n4. PUT /api/v1/tasks/:id - update\n5. DELETE /api/v1/tasks/:id - delete\n6. POST /api/v1/tasks/:id/transition - { toState, note? }\n7. POST /api/v1/tasks/:id/verdict - record QA/Security/SRE verdict\n8. POST /api/v1/tasks/:id/accept - { note? } human gate → merge\n9. POST /api/v1/tasks/:id/reject - { note } → back to in_progress\n10. GET /api/v1/tasks/:id/events - list TaskEvents\n11. Register in main.ts",
|
||||
"testStrategy": "Route tests: test CRUD, test transition endpoint, test verdict recording, test accept triggers merge, test reject changes state, test events returns ordered list.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"130"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "132",
|
||||
"title": "CodeRepo repository and service layers",
|
||||
"description": "Create CodeRepoRepository and CodeRepoService with credential resolution through SecretService",
|
||||
"details": "Create src/mcpd/src/repositories/code-repo.repository.ts and src/mcpd/src/services/code-repo.service.ts:\n1. Repository: standard CRUD, findByProjectId\n2. Service.create(): validate project exists, validate credSecretId/Key if provided\n3. Service.resolveCredentials(repoId): fetch Secret via SecretService, extract the key, return credential (never store plaintext)\n4. Service.update(): validate changes\n5. Service.delete(): check no active sessions reference this repo\n6. Follow existing service patterns for validation",
|
||||
"testStrategy": "Unit tests: test create with valid project, test credential resolution returns correct value, test create fails with invalid secret reference, test findByProjectId returns filtered list.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"119"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "133",
|
||||
"title": "CodeRepo routes and API endpoints",
|
||||
"description": "Create CodeRepo routes with CRUD endpoints",
|
||||
"details": "Create src/mcpd/src/routes/code-repo.routes.ts:\n1. GET /api/v1/repos - list with ?project=<name> filter\n2. POST /api/v1/repos - create, resolve project name\n3. GET /api/v1/repos/:id - get (credential fields return references, not values)\n4. PUT /api/v1/repos/:id - update\n5. DELETE /api/v1/repos/:id - delete\n6. Register in main.ts\n7. Ensure credentials are never exposed in responses",
|
||||
"testStrategy": "Route tests: test CRUD, test project filter, test response does not include credential values, test delete succeeds when no sessions reference repo.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"132"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "134",
|
||||
"title": "RBAC wiring for new resources",
|
||||
"description": "Update mapUrlToPermission and nameResolvers in main.ts for epics, epictasks, tasks, repos, sessions",
|
||||
"details": "In src/mcpd/src/main.ts:\n1. Add to mapUrlToPermission cases: epics, epictasks, tasks, repos, sessions\n2. Map /api/v1/inference-tasks to 'inference-tasks' resource\n3. Add non-CRUD verb cases above the map:\n - POST /tasks/:id/accept|reject|transition → run:tasks:<name>\n - POST /sessions/:id/exec, GET /sessions/:id/attach → run:sessions:<name>\n4. Add nameResolvers for epics, epictasks, tasks, repos, sessions (fetch by id, return name for scoped grants)\n5. Follow existing patterns for permission mapping",
|
||||
"testStrategy": "Unit tests: verify mapUrlToPermission returns correct permission strings for all new routes, test nameResolvers resolve id→name correctly, test non-CRUD verbs get run: prefix.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"115",
|
||||
"126",
|
||||
"128",
|
||||
"131",
|
||||
"133"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "135",
|
||||
"title": "Backup and YAML kinds for new resources",
|
||||
"description": "Add new resources to BACKUP_KINDS, APPLY_ORDER, kindMap, and export/import loops",
|
||||
"details": "Update backup/apply infrastructure:\n1. Add 'Epic', 'EpicTask', 'Task', 'CodeRepo' to BACKUP_KINDS array\n2. Update APPLY_ORDER for correct dependency ordering (Epic before EpicTask before Task)\n3. Add to kindMap: { Epic: 'epics', EpicTask: 'epictasks', Task: 'tasks', CodeRepo: 'repos' }\n4. Update serializeResource for each new kind\n5. Update kindFromSegment in main.ts import handler\n6. Update importResource for create/update logic per kind\n7. Update deleteResource for each kind\n8. Fix existing gap: add 'skill' to importResource/deleteResource if missing",
|
||||
"testStrategy": "Integration tests: test backup exports all new resource types, test apply imports Epic→EpicTask→Task in correct order, test round-trip export→import preserves data.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"126",
|
||||
"128",
|
||||
"131",
|
||||
"133"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "136",
|
||||
"title": "CLI get columns and describe formatters for new resources",
|
||||
"description": "Add column definitions and describe formatters for epics, epictasks, tasks, repos, sessions in CLI",
|
||||
"details": "In src/cli/src/commands/get.ts:\n1. Add row interfaces: EpicRow, EpicTaskRow, TaskRow, CodeRepoRow, AgentSessionRow\n2. Add to getColumnsForResource for each: define column names, widths, formatters\n3. Add to RESOURCE_KIND map: epics→Epic, epictasks→EpicTask, tasks→Task, repos→CodeRepo, sessions→AgentSession\n4. Add to toApplyDocs strip blocks\n\nIn src/cli/src/commands/describe.ts:\n5. Add describe handlers with clean sections and tables (not key-value dumps)\n6. For Epic: show roadmap section with epictask names and completeness\n7. For Task: show lifecycle state, assignee, PR link if present",
|
||||
"testStrategy": "Unit tests: test getColumnsForResource returns correct columns for each resource, test describe output formatting matches expected structure.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"126",
|
||||
"128",
|
||||
"131",
|
||||
"133"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "137",
|
||||
"title": "CLI create subcommands for new resources",
|
||||
"description": "Add create subcommands for epic, epictask, task, repo with all settable fields as flags",
|
||||
"details": "In src/cli/src/commands/create.ts:\n1. Add 'epic' subcommand: --name, --project, --content, --done-criteria (JSON), --description\n2. Add 'epictask' subcommand: --name, --epic, --project, --done-criteria, --description, --depends-on (comma-separated names)\n3. Add 'task' subcommand: --name, --title, --epictask, --epic, --project, --description, --risk, --repo\n4. Add 'repo' subcommand: --name, --project, --url, --default-branch, --path, --provider, --cred-secret, --cred-key\n5. Every field settable in apply must have a corresponding flag\n6. Follow existing create subcommand patterns",
|
||||
"testStrategy": "Unit tests: test each create subcommand parses all flags correctly, test required flags are enforced, test API calls are made with correct payload.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"136"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "138",
|
||||
"title": "CLI apply and edit support for new resources",
|
||||
"description": "Add new resources to apply -f spec schemas and edit validResources",
|
||||
"details": "In src/cli/src/commands/apply.ts:\n1. Add spec schemas: EpicSpecSchema, EpicTaskSpecSchema, TaskSpecSchema, CodeRepoSpecSchema\n2. Add to ApplyConfigSchema discriminated union\n3. Add to KIND_TO_RESOURCE map\n4. Update dry-run counts for new resources\n5. Add apply loops handling create/update for each resource\n\nIn src/cli/src/commands/edit.ts:\n6. Add 'epic', 'epictask', 'task', 'repo' to validResources array",
|
||||
"testStrategy": "Unit tests: test apply parses valid YAML for each new kind, test get -o yaml → apply -f round-trip for each resource type.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"137"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "139",
|
||||
"title": "CLI shell completions for new resources",
|
||||
"description": "Update completion generation for new resource names and aliases",
|
||||
"details": "In scripts/generate-completions.ts:\n1. Add to CANONICAL_RESOURCES: 'epics', 'epictasks', 'tasks', 'repos', 'sessions'\n2. Add to ALIAS_ENTRIES: epic→epics, epictask→epictasks, et→epictasks, task→tasks, repo→repos, repository→repos, repositories→repos, session→sessions\n3. Run pnpm completions:generate to regenerate completion scripts\n4. Completions are generated, never hand-edited\n\nIn src/cli/tests/completions.test.ts:\n5. Test assertions already run generator with --check, will fail on drift automatically",
|
||||
"testStrategy": "Run completions.test.ts which validates generated completions match source of truth. Manual test: source completions in shell, verify tab-completion works for new resources.",
|
||||
"priority": "low",
|
||||
"dependencies": [
|
||||
"138"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "140",
|
||||
"title": "Extend ContainerSpec for ephemeral pods",
|
||||
"description": "Add restartPolicy, workdir, volumes, and initContainers to ContainerSpec interface",
|
||||
"details": "In src/mcpd/src/services/orchestrator.ts:\n1. Add to ContainerSpec interface:\n - restartPolicy?: 'Always' | 'Never' | 'OnFailure'\n - workdir?: string\n - volumes?: Array<{ name: string; mountPath: string; kind: 'emptyDir' }>\n - initContainers?: Array<{ name: string; image: string; command: string[]; env?: Record<string, string>; volumeMounts?: Array<{ name: string; mountPath: string }> }>\n2. These enable ephemeral session pods with workspace volumes and repo-clone init containers",
|
||||
"testStrategy": "Type tests: verify ContainerSpec accepts all new optional fields, verify existing code still compiles without providing new fields.",
|
||||
"priority": "high",
|
||||
"dependencies": [],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "141",
|
||||
"title": "Kubernetes orchestrator ephemeral pod support",
|
||||
"description": "Update KubernetesOrchestrator to handle new ContainerSpec fields in generatePodSpec",
|
||||
"details": "In src/mcpd/src/services/k8s/manifest-generator.ts and KubernetesOrchestrator:\n1. Update generatePodSpec to use spec.restartPolicy if provided (default 'Always' unchanged)\n2. Add workingDir to container spec if workdir provided\n3. Add volumes array for emptyDir volumes\n4. Add volumeMounts to main container\n5. Add initContainers array with their own volumeMounts\n6. Ensure init containers complete before main container starts (Kubernetes handles this)",
|
||||
"testStrategy": "Unit tests: test generatePodSpec output includes restartPolicy, volumes, initContainers when provided. Integration test against test cluster: create pod with init container, verify init completes before main starts.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"140"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "142",
|
||||
"title": "Docker orchestrator ephemeral container support",
|
||||
"description": "Update DockerContainerManager to handle new ContainerSpec fields",
|
||||
"details": "In DockerContainerManager (src/mcpd/src/services/docker/):\n1. Map restartPolicy to Docker restart policy\n2. Set WorkingDir in container config\n3. Create volumes as Docker volumes, add Binds/Mounts\n4. For initContainers: run each sequentially before main container, fail if any init fails\n5. Docker doesn't have native init container support, so implement as sequential container runs that populate shared volume",
|
||||
"testStrategy": "Unit tests: test container spec translation. Integration test: create container with init, verify volume populated before main container runs.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"140"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "143",
|
||||
"title": "SessionService for pod provisioning and lifecycle",
|
||||
"description": "Create SessionService handling AgentSession creation, repo-clone init container, credential resolution, and GC sweep",
|
||||
"details": "Create src/mcpd/src/services/session.service.ts:\n1. create(agentId, projectId, taskId?, image, expiresAt): create AgentSession row in pending state\n2. provision(sessionId): resolve project's CodeRepo list, resolve credentials via SecretService (fail on resolution error like InstanceService.attemptStart), build ContainerSpec with init container that clones repos to workspace volume, create pod via orchestrator, transition to running\n3. end(sessionId): stop container, mark ended\n4. getById(), listByFilters()\n5. GC sweep: find sessions where now() > expiresAt, stop containers, mark ended. Run in same style as inference-task sweep in main.ts\n6. Note: assumes single mcpd replica (no leader election)",
|
||||
"testStrategy": "Unit tests: test provision builds correct init container command, test credential resolution failure aborts provision, test GC sweep marks expired sessions ended.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"121",
|
||||
"132",
|
||||
"141",
|
||||
"142"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "144",
|
||||
"title": "Session routes and exec/attach endpoints",
|
||||
"description": "Create Session routes with CRUD, one-shot exec, and WebSocket attach endpoints",
|
||||
"details": "Create src/mcpd/src/routes/session.routes.ts:\n1. GET /api/v1/sessions - list with ?project=&agent=&task= filters\n2. POST /api/v1/sessions - create and provision\n3. GET /api/v1/sessions/:id - get\n4. DELETE /api/v1/sessions/:id - end session\n5. POST /api/v1/sessions/:id/exec - one-shot exec, body: { command: string[] }, returns { exitCode, stdout, stderr }\n6. GET /api/v1/sessions/:id/attach - WebSocket upgrade, bidirectional stdio with terminal resize and exit code propagation\n7. Use existing execInContainer, attachInteractive from orchestrator\n8. Register in main.ts",
|
||||
"testStrategy": "Route tests: test CRUD, test exec returns command output, test attach upgrades to WebSocket. Integration: exec 'echo hello' in session pod, verify output.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"143"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "145",
|
||||
"title": "CLI exec command",
|
||||
"description": "Add mcpctl exec --project NAME AGENT -- command for interactive session access",
|
||||
"details": "In src/cli/src/commands/ add exec.ts or extend existing:\n1. Parse: mcpctl exec --project NAME AGENT -- command args\n2. Find or create AgentSession for agent in project\n3. If command provided: call POST /sessions/:id/exec, print output\n4. If no command (or -- bash): attach via WebSocket to /sessions/:id/attach\n5. Handle terminal resize (SIGWINCH), pass to WebSocket\n6. Propagate exit code from session\n7. Per design doc: exec drops human into working environment (cloned repos), NOT the agent's reasoning loop",
|
||||
"testStrategy": "Manual testing: mcpctl exec --project test myagent -- ls should list repo contents. mcpctl exec --project test myagent -- bash should give interactive shell.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"144"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "146",
|
||||
"title": "AgentRuntime interface definition",
|
||||
"description": "Define AgentRuntime adapter interface for swappable agent implementations",
|
||||
"details": "Create src/mcpd/src/services/agent-runtime.ts:\n1. Define RuntimeSessionOpts: { agentId, projectId, taskId?, image, persona (prompt files) }\n2. Define RuntimeStatus: 'starting' | 'running' | 'completed' | 'failed'\n3. Define RuntimeResult: { branch: string, headCommit: string, summary: string, prUrl?: string }\n4. Define AgentRuntime interface:\n - startSession(opts: RuntimeSessionOpts): Promise<{ sessionId: string }>\n - send(sessionId: string, message: string): Promise<void>\n - status(sessionId: string): Promise<RuntimeStatus>\n - result(sessionId: string): Promise<RuntimeResult>\n - endSession(sessionId: string): Promise<void>\n5. This is an interface, not an implementation - allows swapping runtimes later",
|
||||
"testStrategy": "Type tests: verify interface can be implemented, verify all methods have correct signatures.",
|
||||
"priority": "medium",
|
||||
"dependencies": [],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "147",
|
||||
"title": "Headless coding agent runtime adapter",
|
||||
"description": "Implement AgentRuntime adapter that runs a headless coding agent inside the session pod",
|
||||
"details": "Create src/mcpd/src/services/agent-runtime/headless-adapter.ts:\n1. Implement AgentRuntime interface\n2. startSession: create AgentSession, provision pod with coding agent image, inject persona as prompt files in container\n3. send: exec into container to send message to agent process (implementation depends on chosen agent's IPC)\n4. status: check agent process state via exec or container status\n5. result: read agent output (branch, commit, summary) from known output location\n6. endSession: stop container, update session state\n7. The coding agent handles git, branching, MCP tools, streaming internally\n8. Persona delivered via mounted files the agent reads",
|
||||
"testStrategy": "Integration tests against test cluster: start session, send simple task, verify branch created and pushed.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"143",
|
||||
"146"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "148",
|
||||
"title": "GitProvider interface and Gitea driver",
|
||||
"description": "Create GitProvider interface and Gitea implementation for PR creation, status check, and merge",
|
||||
"details": "Create src/mcpd/src/services/git-provider.ts and src/mcpd/src/services/git-provider/gitea.ts:\n1. GitProvider interface: createPullRequest(repo, branch, title, body), getPullRequest(repo, prNumber), getCombinedStatus(repo, ref), mergePullRequest(repo, prNumber, method?)\n2. Gitea driver: implement using Gitea API v1\n - POST /api/v1/repos/:owner/:repo/pulls for createPullRequest\n - GET /api/v1/repos/:owner/:repo/pulls/:id for getPullRequest\n - GET /api/v1/repos/:owner/:repo/commits/:sha/status for getCombinedStatus\n - POST /api/v1/repos/:owner/:repo/pulls/:id/merge for mergePullRequest\n3. Credentials resolved from CodeRepo's Secret via SecretService\n4. Reference pr.sh script for endpoint shapes",
|
||||
"testStrategy": "Unit tests with mocked HTTP: test each method sends correct request, handles success/error responses. Integration test against local Gitea instance if available.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"132"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "149",
|
||||
"title": "Task PR linkage and human accept gate",
|
||||
"description": "Integrate GitProvider into TaskService for PR creation on push and merge on accept",
|
||||
"details": "Update src/mcpd/src/services/task.service.ts:\n1. linkPR(taskId, branch, headCommit): create PR via GitProvider, update Task with prUrl, prNumber\n2. accept(taskId, userId, note):\n - Verify task is in awaiting_review state\n - Check PR combined status is success (optional gate based on project config)\n - Call gitProvider.mergePullRequest\n - Transition to merged state\n - Create TaskEvent\n3. If merge fails, keep in awaiting_review, surface error\n4. reject: transition to in_progress, clear PR linkage or keep for reference",
|
||||
"testStrategy": "Unit tests: test linkPR updates task fields, test accept calls merge API, test accept fails if PR status is failing.",
|
||||
"priority": "high",
|
||||
"dependencies": [
|
||||
"130",
|
||||
"148"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "150",
|
||||
"title": "QA/Security/SRE stage verdicts",
|
||||
"description": "Implement risk-scaled verification stages that record commit-pinned verdicts",
|
||||
"details": "Update TaskService:\n1. recordVerdict(taskId, stage, agentId, commit, passed, summary, findings): create TaskVerdict row\n2. If !passed: transition task back to in_progress, create TaskEvent explaining why\n3. Determine required stages based on Task.risk:\n - trivial: may pass on light self-check (no mandatory QA/Security/SRE)\n - normal: requires qa_review\n - high: requires qa_review + security_review + sre_review\n4. Verdicts are immutable - append only, pinned to commit SHA\n5. Each stage persona decides its own depth (not enforced in code, just recorded)\n6. Transition to done only when all required stages have passing verdicts for current headCommit",
|
||||
"testStrategy": "Unit tests: test verdict creation, test failed verdict transitions back to in_progress, test risk-based stage requirements.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"130"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "151",
|
||||
"title": "Git webhook receiver for post-merge failure",
|
||||
"description": "Create webhook endpoint that reopens tasks when post-merge CI fails",
|
||||
"details": "Create src/mcpd/src/routes/webhook.routes.ts:\n1. POST /api/v1/webhooks/git/:provider - receive webhook payloads\n2. Validate webhook signature using provider-specific method (Gitea uses HMAC-SHA256 with secret)\n3. Parse payload to identify: repo, commit SHA, status (success/failure/pending)\n4. If status is failure for a merged commit:\n - Find Task with that headCommit and state=merged\n - Call taskService.reopenOnPostMergeFailure(taskId)\n - This transitions merged→reopened and creates TaskEvent\n5. Register route in main.ts\n6. Webhook secret stored in CodeRepo's credential secret",
|
||||
"testStrategy": "Unit tests: test signature validation, test payload parsing, test reopen triggered on failure status. Integration: simulate Gitea webhook payload.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"130",
|
||||
"148"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "152",
|
||||
"title": "Agent membership routes",
|
||||
"description": "Create API endpoints for managing agent-project memberships",
|
||||
"details": "Add to existing agent routes or create new file:\n1. GET /api/v1/agents/:name/projects - list projects agent belongs to\n2. POST /api/v1/agents/:name/projects/:project - add membership { role?, llm? }\n3. DELETE /api/v1/agents/:name/projects/:project - remove membership\n4. GET /api/v1/projects/:name/agents - list agents in project\n5. Keep Agent.projectId in sync when membership added/removed (backward compat for one release)\n6. Follow existing route patterns",
|
||||
"testStrategy": "Route tests: test add membership creates junction row, test remove deletes it, test list returns correct memberships.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"120"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "153",
|
||||
"title": "CLI tasks accept and reject commands",
|
||||
"description": "Add mcpctl tasks accept and reject commands for human approval gate",
|
||||
"details": "In src/cli/src/commands/ add or extend:\n1. mcpctl tasks accept NAME [--note TEXT] - call POST /tasks/:id/accept, triggers merge\n2. mcpctl tasks reject NAME --note TEXT - call POST /tasks/:id/reject, note required\n3. Resolve task name to id via API\n4. Print result: merge URL on success, error message on failure\n5. Accept should not require going to git - the CLI is the approval surface",
|
||||
"testStrategy": "Unit tests: test accept sends correct API call, test reject requires note flag, test output formatting.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"131",
|
||||
"149"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "154",
|
||||
"title": "Documentation for new resources",
|
||||
"description": "Create docs for epics, tasks, repos, sessions and update README and CLAUDE.md",
|
||||
"details": "Create documentation files:\n1. docs/epics.md - Epic/EpicTask concepts, CLI usage, API reference\n2. docs/tasks.md - Task lifecycle, states, transitions, verdicts\n3. docs/repos.md - CodeRepo configuration, credential setup\n4. docs/sessions.md - AgentSession lifecycle, exec usage\n5. docs/inference-tasks.md - document the rename from 'tasks' RBAC resource\n6. Update README.md resources table with new resources\n7. Update CLAUDE.md resource cheatsheet with new resources",
|
||||
"testStrategy": "Manual review: verify docs are accurate, CLI examples work, API endpoints match implementation.",
|
||||
"priority": "low",
|
||||
"dependencies": [
|
||||
"126",
|
||||
"128",
|
||||
"131",
|
||||
"133",
|
||||
"144",
|
||||
"152"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "155",
|
||||
"title": "Smoke tests for Epic/EpicTask/Task CRUD",
|
||||
"description": "Create smoke tests for vision layer resources against live mcpd",
|
||||
"details": "Create src/mcplocal/tests/smoke/epic.smoke.test.ts:\n1. Follow personality.smoke.test.ts pattern: Date.now().toString(36) name suffix, healthz() preflight that skips when daemon unreachable, mcpctl --direct shelling, explicit afterAll cleanup\n2. Test Epic create/list/describe/delete\n3. Test EpicTask create with edge dependencies\n4. Test Task create linked to EpicTask\n5. Verify cascade: delete Epic removes EpicTasks and Tasks\n6. When test fails, fix environment not assertion",
|
||||
"testStrategy": "Run against live mcpd instance. Tests self-document expected behavior.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"126",
|
||||
"128",
|
||||
"131"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "156",
|
||||
"title": "Smoke tests for CodeRepo and Session",
|
||||
"description": "Create smoke tests for repo and session resources with credential resolution",
|
||||
"details": "Create src/mcplocal/tests/smoke/repo.smoke.test.ts and session.smoke.test.ts:\n1. repo tests: create CodeRepo with credential reference, list, describe, delete\n2. session tests: provision session pod, confirm repo cloned via exec, verify workspace mounted, verify pod reaped after expiry\n3. Follow smoke test patterns: preflight skip, cleanup in afterAll\n4. Session test requires real cluster access",
|
||||
"testStrategy": "Run against live mcpd with cluster access. Verify repo credentials resolve, session pod starts and has cloned repos.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"133",
|
||||
"144"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "157",
|
||||
"title": "Smoke test for task lifecycle transitions",
|
||||
"description": "Create smoke test driving a task through full lifecycle including rejected accept-gate bounce",
|
||||
"details": "Create src/mcplocal/tests/smoke/task-lifecycle.smoke.test.ts:\n1. Create Epic → EpicTask → Task\n2. Transition task: todo → in_progress → building → self_testing → qa_review → done → awaiting_review\n3. Test reject: awaiting_review → in_progress\n4. Advance again to awaiting_review\n5. Test accept: verify merge called (may need mock git provider for smoke)\n6. Verify TaskEvents recorded for all transitions\n7. Follow smoke test patterns",
|
||||
"testStrategy": "Run against live mcpd. Verify each transition succeeds, events logged, reject bounces state correctly.",
|
||||
"priority": "medium",
|
||||
"dependencies": [
|
||||
"131",
|
||||
"149",
|
||||
"153"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "158",
|
||||
"title": "Deferred: Tier-2 vision critic placeholder",
|
||||
"description": "Placeholder task for Tier-2 vision critic and Epic-comparison loop - blocked on design questions",
|
||||
"details": "DEFERRED - DO NOT IMPLEMENT YET\n\nBlocked on docs/agentic-teams.md §15 Q13: does this need render/screenshot infrastructure, or can a design-aware persona judge from a structured artifact?\n\nConcept: A review-only, non-executing design/product persona that judges the assembled result against the Epic in its native medium, producing reopen / new-task / exec outcomes.\n\nExpand this task when the blocking design question is answered.",
|
||||
"testStrategy": "N/A - placeholder only",
|
||||
"priority": "low",
|
||||
"dependencies": [
|
||||
"131",
|
||||
"149"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "159",
|
||||
"title": "Deferred: Collaboration modes placeholder",
|
||||
"description": "Placeholder task for async standup and exec joint sessions - blocked on design questions",
|
||||
"details": "DEFERRED - DO NOT IMPLEMENT YET\n\nBlocked on docs/agentic-teams.md §15 Q4 and Q5.\n\nConcepts:\n- mcpctl standup --project NAME: on-demand async standup\n- exec as a workflow rather than just a command\n\nExpand this task when the blocking design questions are answered.",
|
||||
"testStrategy": "N/A - placeholder only",
|
||||
"priority": "low",
|
||||
"dependencies": [
|
||||
"144",
|
||||
"145"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "160",
|
||||
"title": "Deferred: Confidence signal and escalation dashboard placeholder",
|
||||
"description": "Placeholder task for evidence-anchored confidence and human decision queue - blocked on design questions",
|
||||
"details": "DEFERRED - DO NOT IMPLEMENT YET\n\nBlocked on docs/agentic-teams.md §15 Q12: web / TUI / CLI?\n\nConcepts:\n- Evidence-anchored confidence: retrieve K similar past tasks with outcomes, assess confidence\n- Thresholds driving autonomy level\n- Single cross-project human decision queue\n- Retrieval quality is the crux - weak retrieval quietly poisons the model\n\nExpand this task when the blocking design question is answered.",
|
||||
"testStrategy": "N/A - placeholder only",
|
||||
"priority": "low",
|
||||
"dependencies": [
|
||||
"131",
|
||||
"150"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "161",
|
||||
"title": "Deferred: Per-agent memory and coverage ledger placeholder",
|
||||
"description": "Placeholder task for agent memory and commit-pinned coverage ledger - blocked on design questions",
|
||||
"details": "DEFERRED - DO NOT IMPLEMENT YET\n\nConcepts:\n- Global per-agent memory plus per-project knowledge\n- Commit-pinned coverage ledger enabling delta-verification\n- Non-negotiable: invalidation when covered region changes (or ledger becomes false confidence)\n- Trust boundary: ledger is platform-verified machine fact; agent prose notes are opinion, never the gate\n\nExpand this task when prerequisite infrastructure exists.",
|
||||
"testStrategy": "N/A - placeholder only",
|
||||
"priority": "low",
|
||||
"dependencies": [
|
||||
"147",
|
||||
"150"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
},
|
||||
{
|
||||
"id": "162",
|
||||
"title": "Deferred: Script artifacts and baseline scorecard placeholder",
|
||||
"description": "Placeholder task for reusable script artifacts and baseline rules scorecard - blocked on design questions",
|
||||
"details": "DEFERRED - DO NOT IMPLEMENT YET\n\nBlocked on docs/agentic-teams.md §15 Q15 and Q16.\n\nConcepts:\n- Reusable executable script artifacts at task, project, and agent scope\n- Provisioned baseline-rules scorecard\n- Watch incentive integrity risk: reward reused tools, not tool proliferation\n\nExpand this task when the blocking design questions are answered.",
|
||||
"testStrategy": "N/A - placeholder only",
|
||||
"priority": "low",
|
||||
"dependencies": [
|
||||
"147"
|
||||
],
|
||||
"status": "pending",
|
||||
"subtasks": [],
|
||||
"updatedAt": "2026-08-08T08:55:58.627Z"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"version": "1.0.0",
|
||||
"lastModified": "2026-03-07T23:36:15.981Z",
|
||||
"taskCount": 114,
|
||||
"completedCount": 96,
|
||||
"tags": [
|
||||
"master"
|
||||
]
|
||||
"created": "2026-08-08T08:54:31.861Z",
|
||||
"updated": "2026-08-08T08:54:31.861Z",
|
||||
"description": "Tasks for master context"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user