takomi 2.1.45 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "takomi",
3
- "version": "2.1.45",
3
+ "version": "2.5.1",
4
4
  "description": "🎯 Stop wrestling with AI. Start building with purpose. The artisan's toolkit for agent workflows, Codex skills, and original Takomi capabilities like 21st.dev integration.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -39,7 +39,7 @@
39
39
  "postinstall": "node src/postinstall.js",
40
40
  "test": "npm run test:typecheck && npm run test:regressions && npm run test:context-manager && npm run test:skills",
41
41
  "test:typecheck": "tsc --noEmit",
42
- "test:regressions": "node scripts/test-regressions.js && node scripts/test-subagent-renderers.js && node scripts/test-subagent-heartbeat.js && node scripts/test-subagent-production-lifecycle.js && node scripts/test-subagent-acceptance.js && node scripts/test-takomi-runtime-renderers.js && node scripts/test-workflow-catalog.js && node scripts/test-oauth-router-report-ui.js && node --experimental-specifier-resolution=node scripts/test-takomi-board-errors.js && node scripts/test-takomi-gate-provenance.js && node scripts/test-subagent-project-trust.js",
42
+ "test:regressions": "node scripts/test-regressions.js && node scripts/test-subagent-renderers.js && node scripts/test-subagent-heartbeat.js && node scripts/test-subagent-production-lifecycle.js && node scripts/test-subagent-acceptance.js && node scripts/test-takomi-runtime-renderers.js && node scripts/test-workflow-catalog.js && node scripts/test-oauth-router-report-ui.js && node --experimental-specifier-resolution=node scripts/test-takomi-board-errors.js && node scripts/test-takomi-gate-provenance.js && node scripts/test-takomi-routing-safety.js && node scripts/test-subagent-project-trust.js",
43
43
  "test:context-manager": "node --experimental-specifier-resolution=node scripts/test-context-manager-renderers.js",
44
44
  "test:skills": "node scripts/test-skill-selection.js",
45
45
  "takomi-flow:doctor": "node plugins/takomi-flow/scripts/takomi-flow.mjs doctor",
@@ -5,7 +5,8 @@ import type {
5
5
  OrchestratorTask,
6
6
  OrchestratorTaskStatus,
7
7
  SessionIntent,
8
- TakomiRole,
8
+ LegacyTakomiRole,
9
+ TakomiPersona,
9
10
  TaskChecklistItem,
10
11
  VibeLifecycleStage,
11
12
  } from "./types";
@@ -57,18 +58,24 @@ export function workflowToStage(workflow?: OrchestratorTask["workflow"]): VibeLi
57
58
  }
58
59
  }
59
60
 
60
- function defaultStageForRole(role: TakomiRole): VibeLifecycleStage | undefined {
61
+ export function canonicalizeTakomiPersona(role: TakomiPersona | LegacyTakomiRole): TakomiPersona {
61
62
  switch (role) {
62
- case "architect":
63
- return "genesis";
64
- case "design":
65
- return "design";
66
- case "code":
67
- case "review":
68
- case "orchestrator":
69
- return "build";
70
- default:
71
- return undefined;
63
+ case "design": return "designer";
64
+ case "code": return "coder";
65
+ case "review": return "reviewer";
66
+ case "general": return "worker";
67
+ default: return role;
68
+ }
69
+ }
70
+
71
+ function defaultStageForRole(role: TakomiPersona): VibeLifecycleStage | undefined {
72
+ switch (role) {
73
+ case "architect": return "genesis";
74
+ case "designer": return "design";
75
+ case "coder":
76
+ case "worker":
77
+ case "reviewer":
78
+ case "orchestrator": return "build";
72
79
  }
73
80
  }
74
81
 
@@ -123,19 +130,21 @@ export function normalizeChecklist(checklist?: Array<string | TaskChecklistItem>
123
130
  return checklist.map((item) => typeof item === "string" ? { text: item, done: false } : { text: item.text, done: item.done ?? false });
124
131
  }
125
132
 
126
- export function createTask(id: string, title: string, role: TakomiRole, extras?: Partial<OrchestratorTask>): OrchestratorTask {
127
- const preferredAgent = extras?.preferredAgent ?? (role === "design" ? "designer" : role === "architect" ? "architect" : role === "review" ? "reviewer" : role === "code" ? "coder" : "orchestrator");
128
- const stage = extras?.stage ?? workflowToStage(extras?.workflow) ?? defaultStageForRole(role);
133
+ export function createTask(id: string, title: string, role: TakomiPersona | LegacyTakomiRole, extras?: Partial<OrchestratorTask>): OrchestratorTask {
134
+ const persona = canonicalizeTakomiPersona(role);
135
+ const preferredAgent = extras?.preferredAgent ?? persona;
136
+ const stage = extras?.stage ?? workflowToStage(extras?.workflow) ?? defaultStageForRole(persona);
129
137
  return {
130
138
  id,
131
139
  title,
132
- role,
140
+ role: persona,
133
141
  status: "pending",
134
142
  ...extras,
135
143
  stage,
136
144
  preferredAgent,
137
145
  conversationId: extras?.conversationId ?? createConversationId(preferredAgent, id),
138
146
  preferredModel: extras?.preferredModel,
147
+ preferredModelConfirmed: extras?.preferredModelConfirmed,
139
148
  preferredModelHint: extras?.preferredModelHint,
140
149
  preferredThinking: extras?.preferredThinking,
141
150
  fallbackModels: extras?.fallbackModels,
@@ -392,10 +401,13 @@ export function buildSessionState(
392
401
  title: string,
393
402
  tasks: OrchestratorTask[],
394
403
  now = new Date(),
395
- extras?: Partial<Pick<OrchestratorSessionState, "sessionIntent" | "lifecycle">>,
404
+ extras?: Partial<Pick<OrchestratorSessionState, "sessionIntent" | "lifecycle" | "artifacts">>,
396
405
  ): OrchestratorSessionState {
397
406
  const stamp = now.toISOString();
398
- const normalizedTasks = tasks.map((task) => ({ ...task, stage: task.stage ?? workflowToStage(task.workflow) ?? defaultStageForRole(task.role) }));
407
+ const normalizedTasks = tasks.map((task) => {
408
+ const role = canonicalizeTakomiPersona(task.role as TakomiPersona | LegacyTakomiRole);
409
+ return { ...task, role, preferredAgent: task.preferredAgent ?? role, stage: task.stage ?? workflowToStage(task.workflow) ?? defaultStageForRole(role) };
410
+ });
399
411
  return {
400
412
  sessionId,
401
413
  title,
@@ -404,6 +416,7 @@ export function buildSessionState(
404
416
  mode: "hybrid",
405
417
  lifecycle: deriveLifecycleFromTasks(normalizedTasks, extras?.lifecycle),
406
418
  sessionIntent: extras?.sessionIntent ?? "full-project",
419
+ artifacts: extras?.artifacts,
407
420
  tasks: normalizedTasks,
408
421
  };
409
422
  }
@@ -411,7 +424,10 @@ export function buildSessionState(
411
424
  export function normalizeSessionState(
412
425
  session: Partial<OrchestratorSessionState> & Pick<OrchestratorSessionState, "sessionId" | "title">,
413
426
  ): OrchestratorSessionState {
414
- const tasks = (session.tasks ?? []).map((task) => ({ ...task, stage: task.stage ?? workflowToStage(task.workflow) ?? defaultStageForRole(task.role) }));
427
+ const tasks = (session.tasks ?? []).map((task) => {
428
+ const role = canonicalizeTakomiPersona(task.role as TakomiPersona | LegacyTakomiRole);
429
+ return { ...task, role, preferredAgent: task.preferredAgent ?? role, stage: task.stage ?? workflowToStage(task.workflow) ?? defaultStageForRole(role) };
430
+ });
415
431
  const normalized = buildSessionState(
416
432
  session.sessionId,
417
433
  session.title,
@@ -420,6 +436,7 @@ export function normalizeSessionState(
420
436
  {
421
437
  sessionIntent: session.sessionIntent ?? "full-project",
422
438
  lifecycle: session.lifecycle,
439
+ artifacts: session.artifacts,
423
440
  },
424
441
  );
425
442
 
@@ -428,6 +445,7 @@ export function normalizeSessionState(
428
445
  createdAt: session.createdAt ?? normalized.createdAt,
429
446
  updatedAt: session.updatedAt ?? normalized.updatedAt,
430
447
  mode: "hybrid",
448
+ artifacts: session.artifacts ?? normalized.artifacts,
431
449
  };
432
450
  }
433
451
 
@@ -458,10 +476,10 @@ export function createLifecycleStarterSession(
458
476
  ): OrchestratorSessionState {
459
477
  const sessionId = options?.sessionId ?? createSessionId(options?.now);
460
478
  const tasks = [
461
- createTask("01", "Genesis foundation", "orchestrator", {
479
+ createTask("01", "Genesis foundation", "architect", {
462
480
  stage: "genesis",
463
481
  workflow: "vibe-genesis",
464
- preferredAgent: "orchestrator",
482
+ preferredAgent: "architect",
465
483
  objective: "Establish the project foundation, produce the required planning docs, and decide what should split next.",
466
484
  scope: [
467
485
  "Clarify scope and mission",
@@ -1,5 +1,5 @@
1
1
  import { getWorkflowDefinition } from "./workflows";
2
- import type { RouteDecision, TakomiRole, TakomiWorkflowId, VibeLifecycleStage } from "./types";
2
+ import type { RouteDecision, TakomiPersona, TakomiWorkflowId, VibeLifecycleStage } from "./types";
3
3
 
4
4
  function stageToWorkflow(stage: VibeLifecycleStage): TakomiWorkflowId {
5
5
  switch (stage) {
@@ -15,19 +15,19 @@ function stageToWorkflow(stage: VibeLifecycleStage): TakomiWorkflowId {
15
15
 
16
16
  export function detectLifecycleStage(text: string): VibeLifecycleStage | undefined {
17
17
  const lowered = text.toLowerCase();
18
- if (/(\bgenesis\b|\brequirements\b|\bprd\b|\bscope\b|\bplan first\b|\bblueprint\b)/.test(lowered)) return "genesis";
19
- if (/(\bdesign\b|\bux\b|\bui\b|\bmockup\b|\bwireframe\b|\bvisual\b)/.test(lowered)) return "design";
18
+ if (/(\bgenesis\b|\brequirements\b|\bprd\b|\bscope\b|\bplan first\b|\bblueprint\b|\barchitecture\b|\bdesign the system\b|\btechnical plan\b)/.test(lowered)) return "genesis";
19
+ if (/(\bui\b|\bux\b|\bui design\b|\bux design\b|\buser interface\b|\bmockup\b|\bwireframe\b|\bvisual system\b)/.test(lowered)) return "design";
20
20
  if (/(\bbuild\b|\bimplement\b|\bcode\b|\bship\b|\bwire up\b|\bfeature\b)/.test(lowered)) return "build";
21
21
  return undefined;
22
22
  }
23
23
 
24
- export function detectRole(text: string): TakomiRole | undefined {
24
+ export function detectRole(text: string): TakomiPersona | undefined {
25
25
  const lowered = text.toLowerCase();
26
26
  if (/(\borchestrate\b|\bcoordinate\b|\bbreak this down\b|\bmulti-step\b|\bmulti step\b|\borchestration session\b)/.test(lowered)) return "orchestrator";
27
27
  if (/(\barchitect\b|\bdesign the system\b|\bplan\b|\bspec\b)/.test(lowered)) return "architect";
28
- if (/(\bdesign\b|\bdesigner\b|\bmockup\b|\bvisual\b)/.test(lowered)) return "design";
29
- if (/(\bcode\b|\bimplement\b|\bbuild\b|\bfix\b)/.test(lowered)) return "code";
30
- if (/(\breview\b|\baudit\b|\bcheck\b|\bqa\b)/.test(lowered)) return "review";
28
+ if (/(\bui\b|\bux\b|\bdesigner\b|\bmockup\b|\bwireframe\b|\bvisual system\b|\buser interface\b)/.test(lowered)) return "designer";
29
+ if (/(\bcode\b|\bimplement\b|\bbuild\b|\bfix\b)/.test(lowered)) return "coder";
30
+ if (/(\breview\b|\baudit\b|\bcheck\b|\bqa\b)/.test(lowered)) return "reviewer";
31
31
  return undefined;
32
32
  }
33
33
 
@@ -83,7 +83,7 @@ export function decideRoute(text: string): RouteDecision {
83
83
  }
84
84
 
85
85
  return {
86
- role: "general",
86
+ role: "worker",
87
87
  executionMode: "direct",
88
88
  sessionRecommendation: followUp ? "consider" : "none",
89
89
  reason: followUp
@@ -1,4 +1,11 @@
1
- export type TakomiRole = "general" | "orchestrator" | "architect" | "design" | "code" | "review";
1
+ export type TakomiPersona = "orchestrator" | "architect" | "designer" | "coder" | "worker" | "reviewer";
2
+
3
+ /** @deprecated Runtime and persisted tasks should use TakomiPersona names. */
4
+ export type LegacyTakomiRole = "general" | "design" | "code" | "review";
5
+
6
+ export type TakomiRole = TakomiPersona | "general";
7
+
8
+ export type TakomiMainMode = "idle" | "code" | "review" | "orchestrate";
2
9
 
3
10
  export type TakomiWorkflowId = "vibe-genesis" | "vibe-design" | "vibe-build";
4
11
 
@@ -38,7 +45,7 @@ export type TakomiProfile = {
38
45
  foreground?: boolean;
39
46
  background?: boolean;
40
47
  reviewAfterImplementation?: boolean;
41
- roles?: Partial<Record<TakomiRole, TakomiDispatchDefaults>>;
48
+ roles?: Partial<Record<TakomiPersona, TakomiDispatchDefaults>>;
42
49
  stages?: Partial<Record<VibeLifecycleStage, TakomiDispatchDefaults>>;
43
50
  review?: TakomiReviewProfile;
44
51
  };
@@ -111,7 +118,7 @@ export type WorkflowDefinition = {
111
118
  stage: VibeLifecycleStage;
112
119
  title: string;
113
120
  purpose: string;
114
- preferredRole: TakomiRole;
121
+ preferredRole: TakomiPersona;
115
122
  preferredAgent?: string;
116
123
  preferredModelHint?: string;
117
124
  nextStage?: VibeLifecycleStage;
@@ -119,7 +126,7 @@ export type WorkflowDefinition = {
119
126
  };
120
127
 
121
128
  export type RouteDecision = {
122
- role: TakomiRole;
129
+ role: TakomiPersona;
123
130
  workflow?: TakomiWorkflowId;
124
131
  stage?: VibeLifecycleStage;
125
132
  executionMode: "direct" | "orchestrate";
@@ -137,13 +144,14 @@ export type TaskChecklistItem = {
137
144
  export type OrchestratorTask = {
138
145
  id: string;
139
146
  title: string;
140
- role: TakomiRole;
147
+ role: TakomiPersona;
141
148
  stage?: VibeLifecycleStage;
142
149
  workflow?: TakomiWorkflowId;
143
150
  parentTaskId?: string;
144
151
  preferredAgent?: string;
145
152
  preferredModelHint?: string;
146
153
  preferredModel?: string;
154
+ preferredModelConfirmed?: boolean;
147
155
  preferredThinking?: TakomiThinkingLevel;
148
156
  fallbackModels?: string[];
149
157
  dispatchPolicy?: TakomiDispatchPolicy;
@@ -153,6 +161,7 @@ export type OrchestratorTask = {
153
161
  scope?: string[];
154
162
  definitionOfDone?: string[];
155
163
  expectedArtifacts?: string[];
164
+ requiredCapabilities?: string[];
156
165
  dependencies?: string[];
157
166
  reviewCheckpoint?: string;
158
167
  instructions?: string[];
@@ -171,6 +180,14 @@ export type LifecycleStageState = {
171
180
 
172
181
  export type SessionIntent = "full-project" | "feature-scope" | "follow-up-task";
173
182
 
183
+ export type MasterPlanOwner = "human" | "board" | "caller";
184
+
185
+ export type MasterPlanArtifactProvenance = {
186
+ owner: MasterPlanOwner;
187
+ sha256: string;
188
+ lastSeenAt: string;
189
+ };
190
+
174
191
  export type OrchestratorSessionState = {
175
192
  sessionId: string;
176
193
  title: string;
@@ -179,5 +196,8 @@ export type OrchestratorSessionState = {
179
196
  mode: "hybrid";
180
197
  lifecycle: Record<VibeLifecycleStage, LifecycleStageState>;
181
198
  sessionIntent?: SessionIntent;
199
+ artifacts?: {
200
+ masterPlan?: MasterPlanArtifactProvenance;
201
+ };
182
202
  tasks: OrchestratorTask[];
183
203
  };
@@ -40,15 +40,15 @@ const WORKFLOW_IMPLEMENTATIONS: Record<TakomiWorkflowId, Omit<WorkflowDefinition
40
40
  playbook: VIBE_GENESIS_PLAYBOOK,
41
41
  },
42
42
  "vibe-design": {
43
- preferredRole: "design",
43
+ preferredRole: "designer",
44
44
  preferredAgent: "designer",
45
45
  preferredModelHint: "Prefer Gemini 3.1 Pro Preview or another strong design-capable model actually available in Pi.",
46
46
  nextStage: "build",
47
47
  playbook: VIBE_DESIGN_PLAYBOOK,
48
48
  },
49
49
  "vibe-build": {
50
- preferredRole: "orchestrator",
51
- preferredAgent: "orchestrator",
50
+ preferredRole: "coder",
51
+ preferredAgent: "coder",
52
52
  playbook: VIBE_BUILD_PLAYBOOK,
53
53
  },
54
54
  };