Compare commits
2 Commits
feat/kanba
...
feat/ms22-
| Author | SHA1 | Date | |
|---|---|---|---|
| 57c58dd2f4 | |||
| c640d22394 |
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "tasks" ADD COLUMN "assigned_agent" TEXT;
|
||||||
@@ -379,6 +379,7 @@ model Task {
|
|||||||
creatorId String @map("creator_id") @db.Uuid
|
creatorId String @map("creator_id") @db.Uuid
|
||||||
projectId String? @map("project_id") @db.Uuid
|
projectId String? @map("project_id") @db.Uuid
|
||||||
parentId String? @map("parent_id") @db.Uuid
|
parentId String? @map("parent_id") @db.Uuid
|
||||||
|
assignedAgent String? @map("assigned_agent")
|
||||||
domainId String? @map("domain_id") @db.Uuid
|
domainId String? @map("domain_id") @db.Uuid
|
||||||
sortOrder Int @default(0) @map("sort_order")
|
sortOrder Int @default(0) @map("sort_order")
|
||||||
metadata Json @default("{}")
|
metadata Json @default("{}")
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ export class CreateTaskDto {
|
|||||||
@IsUUID("4", { message: "parentId must be a valid UUID" })
|
@IsUUID("4", { message: "parentId must be a valid UUID" })
|
||||||
parentId?: string;
|
parentId?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString({ message: "assignedAgent must be a string" })
|
||||||
|
@MinLength(1, { message: "assignedAgent must not be empty" })
|
||||||
|
@MaxLength(255, { message: "assignedAgent must not exceed 255 characters" })
|
||||||
|
assignedAgent?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsInt({ message: "sortOrder must be an integer" })
|
@IsInt({ message: "sortOrder must be an integer" })
|
||||||
@Min(0, { message: "sortOrder must be at least 0" })
|
@Min(0, { message: "sortOrder must be at least 0" })
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ export class UpdateTaskDto {
|
|||||||
@IsUUID("4", { message: "parentId must be a valid UUID" })
|
@IsUUID("4", { message: "parentId must be a valid UUID" })
|
||||||
parentId?: string | null;
|
parentId?: string | null;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString({ message: "assignedAgent must be a string" })
|
||||||
|
@MinLength(1, { message: "assignedAgent must not be empty" })
|
||||||
|
@MaxLength(255, { message: "assignedAgent must not exceed 255 characters" })
|
||||||
|
assignedAgent?: string | null;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsInt({ message: "sortOrder must be an integer" })
|
@IsInt({ message: "sortOrder must be an integer" })
|
||||||
@Min(0, { message: "sortOrder must be at least 0" })
|
@Min(0, { message: "sortOrder must be at least 0" })
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ describe("TasksService", () => {
|
|||||||
creatorId: mockUserId,
|
creatorId: mockUserId,
|
||||||
projectId: null,
|
projectId: null,
|
||||||
parentId: null,
|
parentId: null,
|
||||||
|
assignedAgent: null,
|
||||||
sortOrder: 0,
|
sortOrder: 0,
|
||||||
metadata: {},
|
metadata: {},
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
@@ -158,6 +159,28 @@ describe("TasksService", () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should include assignedAgent when provided", async () => {
|
||||||
|
const createDto = {
|
||||||
|
title: "Agent-owned Task",
|
||||||
|
assignedAgent: "fleet-worker-1",
|
||||||
|
};
|
||||||
|
|
||||||
|
mockPrismaService.task.create.mockResolvedValue({
|
||||||
|
...mockTask,
|
||||||
|
assignedAgent: createDto.assignedAgent,
|
||||||
|
});
|
||||||
|
|
||||||
|
await service.create(mockWorkspaceId, mockUserId, createDto);
|
||||||
|
|
||||||
|
expect(prisma.task.create).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: expect.objectContaining({
|
||||||
|
assignedAgent: createDto.assignedAgent,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("findAll", () => {
|
describe("findAll", () => {
|
||||||
@@ -469,6 +492,26 @@ describe("TasksService", () => {
|
|||||||
service.update(mockTaskId, mockWorkspaceId, mockUserId, { title: "Test" })
|
service.update(mockTaskId, mockWorkspaceId, mockUserId, { title: "Test" })
|
||||||
).rejects.toThrow(NotFoundException);
|
).rejects.toThrow(NotFoundException);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should update assignedAgent when provided", async () => {
|
||||||
|
const updateDto = { assignedAgent: "fleet-worker-2" };
|
||||||
|
|
||||||
|
mockPrismaService.task.findUnique.mockResolvedValue(mockTask);
|
||||||
|
mockPrismaService.task.update.mockResolvedValue({
|
||||||
|
...mockTask,
|
||||||
|
assignedAgent: updateDto.assignedAgent,
|
||||||
|
});
|
||||||
|
|
||||||
|
await service.update(mockTaskId, mockWorkspaceId, mockUserId, updateDto);
|
||||||
|
|
||||||
|
expect(prisma.task.update).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: expect.objectContaining({
|
||||||
|
assignedAgent: updateDto.assignedAgent,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("remove", () => {
|
describe("remove", () => {
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ export class TasksService {
|
|||||||
metadata: createTaskDto.metadata
|
metadata: createTaskDto.metadata
|
||||||
? (createTaskDto.metadata as unknown as Prisma.InputJsonValue)
|
? (createTaskDto.metadata as unknown as Prisma.InputJsonValue)
|
||||||
: {},
|
: {},
|
||||||
|
...(createTaskDto.assignedAgent !== undefined && {
|
||||||
|
assignedAgent: createTaskDto.assignedAgent,
|
||||||
|
}),
|
||||||
...(assigneeConnection && { assignee: assigneeConnection }),
|
...(assigneeConnection && { assignee: assigneeConnection }),
|
||||||
...(projectConnection && { project: projectConnection }),
|
...(projectConnection && { project: projectConnection }),
|
||||||
...(parentConnection && { parent: parentConnection }),
|
...(parentConnection && { parent: parentConnection }),
|
||||||
@@ -291,6 +294,9 @@ export class TasksService {
|
|||||||
if (updateTaskDto.parentId !== undefined && updateTaskDto.parentId !== null) {
|
if (updateTaskDto.parentId !== undefined && updateTaskDto.parentId !== null) {
|
||||||
data.parent = { connect: { id: updateTaskDto.parentId } };
|
data.parent = { connect: { id: updateTaskDto.parentId } };
|
||||||
}
|
}
|
||||||
|
if (updateTaskDto.assignedAgent !== undefined) {
|
||||||
|
data.assignedAgent = updateTaskDto.assignedAgent;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle completedAt based on status changes
|
// Handle completedAt based on status changes
|
||||||
if (updateTaskDto.status) {
|
if (updateTaskDto.status) {
|
||||||
|
|||||||
@@ -52,3 +52,22 @@
|
|||||||
| **Total** | **31** | **15** | **~371K** | **~175K** |
|
| **Total** | **31** | **15** | **~371K** | **~175K** |
|
||||||
|
|
||||||
Remaining estimate: ~143K tokens (Codex budget).
|
Remaining estimate: ~143K tokens (Codex budget).
|
||||||
|
|
||||||
|
## MS22 — Fleet Evolution (Phase 0: Knowledge Layer)
|
||||||
|
|
||||||
|
| id | status | milestone | description | issue | repo | branch | depends_on | blocks | agent | started_at | completed_at | estimate | used | notes |
|
||||||
|
| --------------- | ----------- | ------------ | ------------------------------------------------------------ | -------- | ----- | ------------------------------ | --------------------------------------------------------- | ------------- | ------------ | ---------- | ------------ | -------- | ---- | --------------------------------------------- |
|
||||||
|
| MS22-PLAN-001 | done | p0-knowledge | PRD + mission bootstrap + TASKS.md | TASKS:P0 | stack | feat/ms22-knowledge-schema | — | MS22-DB-001 | orchestrator | 2026-02-28 | 2026-02-28 | 10K | 8K | PRD-MS22.md, mission fleet-evolution-20260228 |
|
||||||
|
| MS22-DB-001 | done | p0-knowledge | Findings module (pgvector, CRUD, similarity search) | TASKS:P0 | api | feat/ms22-findings | MS22-PLAN-001 | — | codex | 2026-02-28 | 2026-02-28 | 20K | ~22K | PR #585 merged, CI green |
|
||||||
|
| MS22-API-001 | done | p0-knowledge | Findings API endpoints | TASKS:P0 | api | feat/ms22-findings | MS22-DB-001 | — | codex | 2026-02-28 | 2026-02-28 | — | — | Combined with DB-001 |
|
||||||
|
| MS22-DB-002 | done | p0-knowledge | AgentMemory module (key/value store, upsert) | TASKS:P0 | api | feat/ms22-agent-memory | MS22-DB-001 | — | codex | 2026-02-28 | 2026-02-28 | 15K | ~16K | PR #586 merged, CI green |
|
||||||
|
| MS22-API-002 | done | p0-knowledge | AgentMemory API endpoints | TASKS:P0 | api | feat/ms22-agent-memory | MS22-DB-002 | — | codex | 2026-02-28 | 2026-02-28 | — | — | Combined with DB-002 |
|
||||||
|
| MS22-DB-004 | done | p0-knowledge | ConversationArchive module (pgvector, ingest, search) | TASKS:P0 | api | feat/ms22-conversation-archive | MS22-DB-001 | — | codex | 2026-02-28 | 2026-02-28 | 20K | ~18K | PR #587 merged, CI green |
|
||||||
|
| MS22-API-004 | done | p0-knowledge | ConversationArchive API endpoints | TASKS:P0 | api | feat/ms22-conversation-archive | MS22-DB-004 | — | codex | 2026-02-28 | 2026-02-28 | — | — | Combined with DB-004 |
|
||||||
|
| MS22-API-005 | done | p0-knowledge | EmbeddingService (reuse existing KnowledgeModule) | TASKS:P0 | api | — | — | — | orchestrator | 2026-02-28 | 2026-02-28 | 0 | 0 | Already existed; no work needed |
|
||||||
|
| MS22-DB-003 | not-started | p0-knowledge | Task model: add assigned_agent field + migration | TASKS:P0 | api | feat/ms22-task-agent | MS22-DB-001 | MS22-API-003 | — | — | — | 8K | — | Small schema + migration only |
|
||||||
|
| MS22-API-003 | not-started | p0-knowledge | Task API: expose assigned_agent in CRUD | TASKS:P0 | api | feat/ms22-task-agent | MS22-DB-003 | MS22-TEST-001 | — | — | — | 8K | — | Extend existing TaskModule |
|
||||||
|
| MS22-TEST-001 | not-started | p0-knowledge | Integration tests: Findings + AgentMemory + ConvArchive | TASKS:P0 | api | test/ms22-integration | MS22-API-001,MS22-API-002,MS22-API-004 | MS22-VER-P0 | — | — | — | 20K | — | E2E with live postgres |
|
||||||
|
| MS22-SKILL-001 | not-started | p0-knowledge | OpenClaw mosaic skill (agents read/write findings/memory) | TASKS:P0 | stack | feat/ms22-openclaw-skill | MS22-API-001,MS22-API-002 | MS22-VER-P0 | — | — | — | 15K | — | Skill in ~/.agents/skills/mosaic/ |
|
||||||
|
| MS22-INGEST-001 | not-started | p0-knowledge | Session log ingestion pipeline (OpenClaw logs → ConvArchive) | TASKS:P0 | stack | feat/ms22-ingest | MS22-API-004 | MS22-VER-P0 | — | — | — | 20K | — | Script to batch-ingest existing logs |
|
||||||
|
| MS22-VER-P0 | not-started | p0-knowledge | Phase 0 verification: all modules deployed + smoke tested | TASKS:P0 | stack | — | MS22-TEST-001,MS22-SKILL-001,MS22-INGEST-001,MS22-API-003 | — | — | — | — | 5K | — | |
|
||||||
|
|||||||
Reference in New Issue
Block a user