|
1 | 1 | { |
2 | 2 | "project": "temporal-spring-ai", |
3 | 3 | "tasks": [ |
4 | | - { |
5 | | - "id": "T1", |
6 | | - "title": "Add unit tests for type conversion", |
7 | | - "description": "Test ChatModelTypes <-> Spring AI types round-trip in ActivityChatModel and ChatModelActivityImpl. Cover messages (all roles), tool calls, media content, model options, embeddings, vector store types.", |
8 | | - "severity": "high", |
9 | | - "category": "tests", |
10 | | - "depends_on": [], |
11 | | - "status": "completed" |
12 | | - }, |
13 | | - { |
14 | | - "id": "T2", |
15 | | - "title": "Add unit tests for tool detection and conversion", |
16 | | - "description": "Test TemporalToolUtil.convertTools() with activity stubs, local activity stubs, @DeterministicTool, @SideEffectTool, Nexus stubs, and rejection of unknown types. Test TemporalStubUtil detection methods.", |
17 | | - "severity": "high", |
18 | | - "category": "tests", |
19 | | - "depends_on": [], |
20 | | - "status": "completed" |
21 | | - }, |
22 | | - { |
23 | | - "id": "T3", |
24 | | - "title": "Add replay test for determinism", |
25 | | - "description": "Create a workflow that uses ActivityChatModel with tools, run it once to produce history, then replay from that history to verify determinism. Cover activity tools, @DeterministicTool, and @SideEffectTool.", |
26 | | - "severity": "high", |
27 | | - "category": "tests", |
28 | | - "depends_on": [], |
29 | | - "status": "completed" |
30 | | - }, |
31 | | - { |
32 | | - "id": "T4", |
33 | | - "title": "Add unit tests for plugin registration", |
34 | | - "description": "Test SpringAiPlugin.initializeWorker() registers correct activities based on available beans. Test single model, multi-model, with/without VectorStore, with/without EmbeddingModel.", |
35 | | - "severity": "medium", |
36 | | - "category": "tests", |
37 | | - "depends_on": [], |
38 | | - "status": "completed" |
39 | | - }, |
40 | | - { |
41 | | - "id": "T5", |
42 | | - "title": "Fix UUID.randomUUID() in workflow context", |
43 | | - "description": "Replace UUID.randomUUID() with Workflow.randomUUID() in LocalActivityToolCallbackWrapper.call(). One-line fix.", |
44 | | - "severity": "high", |
45 | | - "category": "bugfix", |
46 | | - "depends_on": [ |
47 | | - "T3" |
48 | | - ], |
49 | | - "status": "completed", |
50 | | - "notes": "Do after replay test exists so we can verify the fix." |
51 | | - }, |
52 | | - { |
53 | | - "id": "T6", |
54 | | - "title": "Split SpringAiPlugin for optional deps", |
55 | | - "description": "Refactor so VectorStore, EmbeddingModel, and MCP are handled by separate @ConditionalOnClass auto-configuration classes. Core SpringAiPlugin only references ChatModel. compileOnly scope stays correct.", |
56 | | - "severity": "high", |
57 | | - "category": "refactor", |
58 | | - "depends_on": [ |
59 | | - "T4" |
60 | | - ], |
61 | | - "status": "completed", |
62 | | - "notes": "Do after plugin registration tests exist so we can verify the refactor doesn't break registration. Also resolves T10 (unnecessary MCP reflection)." |
63 | | - }, |
64 | | - { |
65 | | - "id": "T14", |
66 | | - "title": "Fix NPE when ChatResponse metadata is null", |
67 | | - "description": "ActivityChatModel.toResponse() passes null metadata to ChatResponse.builder().metadata(null), which causes an NPE in Spring AI's builder. Fix: skip .metadata() call when metadata is null, or pass an empty ChatResponseMetadata.", |
68 | | - "severity": "high", |
69 | | - "category": "bugfix", |
70 | | - "depends_on": [], |
71 | | - "status": "completed" |
72 | | - }, |
73 | | - { |
74 | | - "id": "T7", |
75 | | - "title": "Add max iteration limit to ActivityChatModel tool loop", |
76 | | - "description": "Add a configurable max iteration count (default ~10) to the recursive call() loop in ActivityChatModel. Throw after limit to prevent infinite recursion from misbehaving models.", |
77 | | - "severity": "medium", |
78 | | - "category": "bugfix", |
79 | | - "depends_on": [ |
80 | | - "T1" |
81 | | - ], |
82 | | - "status": "reverted", |
83 | | - "notes": "Reverted: Spring AI does not limit tool call iterations either. Temporal activity timeouts and workflow execution timeout provide the safety net." |
84 | | - }, |
85 | | - { |
86 | | - "id": "T8", |
87 | | - "title": "Replace fragile stub detection with SDK internals", |
88 | | - "description": "TemporalStubUtil string-matches on internal handler class names. Since the plugin is in the SDK repo, use internal APIs or instanceof checks. Add tests to catch breakage.", |
89 | | - "severity": "medium", |
90 | | - "category": "refactor", |
91 | | - "depends_on": [ |
92 | | - "T2" |
93 | | - ], |
94 | | - "status": "completed", |
95 | | - "notes": "Do after tool detection tests exist so we can verify the refactor." |
96 | | - }, |
97 | | - { |
98 | | - "id": "T9", |
99 | | - "title": "Document static CALLBACK_REGISTRY lifecycle", |
100 | | - "description": "Add javadoc to LocalActivityToolCallbackWrapper explaining the leak risk when workflows are evicted mid-execution. Consider adding a size metric or periodic cleanup.", |
101 | | - "severity": "medium", |
102 | | - "category": "improvement", |
103 | | - "depends_on": [], |
104 | | - "status": "completed" |
105 | | - }, |
106 | | - { |
107 | | - "id": "T10", |
108 | | - "title": "Remove unnecessary MCP reflection", |
109 | | - "description": "SpringAiPlugin uses Class.forName() for McpClientActivityImpl which is in the same module. Will be resolved by T6 (split into conditional configs).", |
110 | | - "severity": "low", |
111 | | - "category": "refactor", |
112 | | - "depends_on": [ |
113 | | - "T6" |
114 | | - ], |
115 | | - "status": "completed", |
116 | | - "notes": "Likely resolved automatically by T6." |
117 | | - }, |
118 | | - { |
119 | | - "id": "T11", |
120 | | - "title": "Add UnsupportedOperationException for stream()", |
121 | | - "description": "Override stream() in ActivityChatModel to throw UnsupportedOperationException with a clear message that streaming is not supported through activities.", |
122 | | - "severity": "low", |
123 | | - "category": "improvement", |
124 | | - "depends_on": [], |
125 | | - "status": "completed" |
126 | | - }, |
127 | | - { |
128 | | - "id": "T12", |
129 | | - "title": "Verify all 5 samples run end-to-end", |
130 | | - "description": "Run chat, MCP, multi-model, RAG, and sandboxing samples interactively against a dev server. Verify tool calling works for each.", |
131 | | - "severity": "medium", |
132 | | - "category": "testing", |
133 | | - "depends_on": [ |
134 | | - "T6" |
135 | | - ], |
136 | | - "status": "completed", |
137 | | - "notes": "All 5 samples boot successfully. MCP requires Node.js/npx for MCP server (environment prereq, not a code issue)." |
138 | | - }, |
139 | 4 | { |
140 | 5 | "id": "T13", |
141 | 6 | "title": "Remove includeBuild from samples-java", |
|
145 | 10 | "depends_on": [], |
146 | 11 | "status": "blocked", |
147 | 12 | "notes": "Blocked on SDK release. Not actionable yet." |
| 13 | + }, |
| 14 | + { |
| 15 | + "id": "T15", |
| 16 | + "title": "Change default tool execution to run in workflow context", |
| 17 | + "description": "Currently unannotated tools passed to defaultTools() are rejected. Change so they execute directly in workflow context by default — user is responsible for determinism. Remove @DeterministicTool annotation (no longer needed since direct execution is the default). Remove SandboxingAdvisor and LocalActivityToolCallbackWrapper. Keep @SideEffectTool as a convenience for wrapping in Workflow.sideEffect(). Keep activity stub / nexus stub auto-detection as shortcuts.", |
| 18 | + "severity": "high", |
| 19 | + "category": "refactor", |
| 20 | + "depends_on": [], |
| 21 | + "status": "blocked", |
| 22 | + "notes": "Blocked on PR review discussion with tconley1428. Agreed on direction but need to finalize details before implementing. See sdk-java#2829 comment thread on SandboxingAdvisor." |
148 | 23 | } |
149 | | - ], |
150 | | - "execution_order_rationale": "Tests first (T1-T4) in parallel since they're independent. Then fixes that benefit from test coverage: T5 (UUID fix, verified by T3), T6 (plugin split, verified by T4), T7 (loop limit, verified by T1), T8 (stub detection, verified by T2). Then downstream: T10 (resolved by T6), T9/T11 (independent improvements). T12 after T6. T13 blocked on release." |
| 24 | + ] |
151 | 25 | } |
0 commit comments