From 64b9c67b284365690a27ef539c46e7f3b73bec95 Mon Sep 17 00:00:00 2001 From: shlok sushil chorge Date: Fri, 8 May 2026 15:16:11 +0530 Subject: [PATCH 01/16] feat(matrix): MatrixEngine pipeline + system/user prompt split --- .../com/example/iaso/ConvexApiHelper.java | 53 +++++ .../com/example/iaso/matrix/MatrixEngine.java | 214 ++++++++++++++++++ .../example/iaso/matrix/MatrixPrompts.java | 49 ++++ 3 files changed, 316 insertions(+) create mode 100644 app/src/main/java/com/example/iaso/matrix/MatrixEngine.java create mode 100644 app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index 7292e05..26adb22 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -97,6 +97,59 @@ public void sendMessageToClaude(String userMessage, ClaudeResponseCallback callb }); } +// ==================== MATRIX METHOD (system + user split) ==================== + +/** + * For MatrixEngine — sends system prompt and user message separately + * System = rules/schema, User = just the goal data + */ +public void sendMessageToClaude( + String systemPrompt, + String userMessage, + ClaudeResponseCallback callback) { + + executor.execute(() -> { + try { + JSONObject argsObject = new JSONObject(); + argsObject.put("systemPrompt", systemPrompt); + argsObject.put("userMessage", userMessage); + + JSONObject requestJson = new JSONObject(); + requestJson.put("path", CONVEX_ACTION_PATH); + requestJson.put("args", argsObject); + + RequestBody body = RequestBody.create(requestJson.toString(), JSON); + Request request = new Request.Builder() + .url(CONVEX_URL + "/api/action") + .post(body) + .addHeader("Content-Type", "application/json") + .build(); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + postError(callback, "Server error: " + response.code()); + return; + } + + String responseBody = response.body() != null ? response.body().string() : ""; + JSONObject jsonResponse = new JSONObject(responseBody); + String status = jsonResponse.optString("status", ""); + + if ("success".equals(status)) { + postSuccess(callback, jsonResponse.optString("value", "")); + } else { + postError(callback, "Convex error: " + jsonResponse.optString("errorMessage", "Unknown error")); + } + } + + } catch (IOException e) { + postError(callback, "Network error: " + e.getMessage()); + } catch (JSONException e) { + postError(callback, "Error building request: " + e.getMessage()); + } + }); +} + // ==================== NEW METHOD (multi-turn conversation) ==================== /** diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java new file mode 100644 index 0000000..7e2ec18 --- /dev/null +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -0,0 +1,214 @@ +package com.example.iaso.matrix; + +import android.content.Context; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.example.iaso.ConvexApiHelper; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MatrixEngine { + + private static final String TAG = "MatrixEngine"; + + // ─── Callback ──────────────────────────────────────────────────────────── + + public interface MatrixEngineCallback { + void onTimelineGenerated(@NonNull MatrixGoal goal); + void onError(@NonNull String errorMessage); + } + + // ─── Public API ────────────────────────────────────────────────────────── + + public void generateTimeline( + @NonNull Context context, + @NonNull String goalDescription, + int dailyMinutes, + int totalDays, + @NonNull MatrixEngineCallback callback + ) { + // System prompt — fixed rules, never changes + String system = MatrixPrompts.TIMELINE_SYSTEM; + + // User message — just the goal data, changes every call + String user = MatrixPrompts.TIMELINE_USER + .replace("{goalDescription}", goalDescription) + .replace("{dailyMinutes}", String.valueOf(dailyMinutes)) + .replace("{totalDays}", String.valueOf(totalDays)); + + Log.d(TAG, "=== SYSTEM PROMPT ===\n" + system); + Log.d(TAG, "=== USER MESSAGE ===\n" + user); + + ConvexApiHelper api = new ConvexApiHelper(); + api.sendMessageToClaude(system, user, new ConvexApiHelper.ClaudeResponseCallback() { + + @Override + public void onSuccess(String response) { + Log.d(TAG, "=== RAW RESPONSE ===\n" + response); + try { + List milestones = parseMilestones(response); + + if (milestones.isEmpty()) { + callback.onError("No milestones could be parsed from the response."); + return; + } + + // Validate day sum — soft fix: redistribute remainder into last milestone + int sum = 0; + for (MatrixMilestone m : milestones) sum += m.getAllocatedDays(); + if (sum != totalDays) { + Log.w(TAG, "Day sum mismatch: expected " + totalDays + ", got " + sum); + MatrixMilestone last = milestones.get(milestones.size() - 1); + last.setAllocatedDays(Math.max(1, last.getAllocatedDays() + (totalDays - sum))); + } + + MatrixGoal goal = buildGoal(goalDescription, totalDays, milestones); + MatrixStorage.saveGoal(context, goal); + + MatrixSnapshot snapshot = new MatrixSnapshot(); + snapshot.setActiveGoalId(goal.getGoalId()); + snapshot.setActiveMilestoneIndex(0); + snapshot.setCurrentDayInMilestone(1); + snapshot.setTotalDaysElapsed(0); + snapshot.setTotalDaysRemaining(totalDays); + snapshot.setBufferRemaining(0); + MatrixStorage.saveSnapshot(context, snapshot); + + callback.onTimelineGenerated(goal); + + } catch (Exception e) { + Log.e(TAG, "Parse/build error: " + e.getMessage(), e); + callback.onError("Failed to build timeline: " + e.getMessage()); + } + } + + @Override + public void onError(String errorMessage) { + Log.e(TAG, "ConvexApiHelper error: " + errorMessage); + callback.onError(errorMessage); + } + }); + } + + // ─── Parsing ───────────────────────────────────────────────────────────── + + /** + * 3-layer parse fallback: + * 1) Strict JSON array + * 2) Bracket extraction (handles markdown fences or preamble) + * 3) Regex object-by-object extraction (last resort) + */ + private List parseMilestones(String raw) throws JSONException { + String trimmed = raw.trim(); + + // 1) Strict JSON array + try { + JSONArray array = new JSONArray(trimmed); + List milestones = buildMilestonesFromArray(array); + if (!milestones.isEmpty()) { + Log.d(TAG, "Parsed via strict JSON path."); + return milestones; + } + } catch (JSONException ignored) { } + + // 2) Bracket extraction + int start = trimmed.indexOf('['); + int end = trimmed.lastIndexOf(']'); + if (start != -1 && end > start) { + String extracted = trimmed.substring(start, end + 1); + try { + JSONArray array = new JSONArray(extracted); + List milestones = buildMilestonesFromArray(array); + if (!milestones.isEmpty()) { + Log.d(TAG, "Parsed via bracket extraction."); + return milestones; + } + } catch (JSONException ignored) { } + } + + // 3) Regex fallback + Log.w(TAG, "Falling back to regex milestone extraction."); + return parseMilestonesViaRegex(trimmed); + } + + private List parseMilestonesViaRegex(String raw) throws JSONException { + Pattern blockPattern = Pattern.compile("\\{[^{}]*\"name\"[^{}]*\\}"); + Matcher matcher = blockPattern.matcher(raw); + + JSONArray array = new JSONArray(); + while (matcher.find()) { + try { + array.put(new JSONObject(matcher.group())); + } catch (JSONException ignored) { } + } + + if (array.length() == 0) { + Log.e(TAG, "Regex extraction found no milestone blocks."); + } + + return buildMilestonesFromArray(array); + } + + /** + * Converts a JSONArray of milestone objects into MatrixMilestone list. + * Assigns UUIDs, orderIndex, and computes startDay from cumulative allocatedDays. + */ + private List buildMilestonesFromArray(JSONArray array) throws JSONException { + List milestones = new ArrayList<>(); + int startDay = 1; + + for (int i = 0; i < array.length(); i++) { + JSONObject obj = array.getJSONObject(i); + + String name = obj.optString("name", "Milestone " + (i + 1)); + String description = obj.optString("description", ""); + int allocatedDays = Math.max(1, obj.optInt("allocatedDays", 1)); + + // Parse dependencies — logged now, stored when MatrixMilestone supports it + JSONArray deps = obj.optJSONArray("dependencies"); + if (deps != null && deps.length() > 0) { + Log.d(TAG, "Milestone " + i + " dependencies: " + deps.toString()); + } + + MatrixMilestone milestone = new MatrixMilestone(); + milestone.setMilestoneId(UUID.randomUUID().toString()); + milestone.setName(name); + milestone.setDescription(description); + milestone.setOrderIndex(i); + milestone.setAllocatedDays(allocatedDays); + milestone.setBufferDays(0); + milestone.setStartDay(startDay); + + milestones.add(milestone); + startDay += allocatedDays; + } + + return milestones; + } + + // ─── Goal Assembly ─────────────────────────────────────────────────────── + + private MatrixGoal buildGoal(String goalDescription, int totalDays, List milestones) { + MatrixGoal goal = new MatrixGoal(); + goal.setGoalId(UUID.randomUUID().toString()); + goal.setHabitName(goalDescription); + goal.setGoalDescription(goalDescription); + + long now = System.currentTimeMillis(); + goal.setStartDate(now); + goal.setTotalDays(totalDays); + goal.setMilestones(milestones); + + return goal; + } +} diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java b/app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java new file mode 100644 index 0000000..d657259 --- /dev/null +++ b/app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java @@ -0,0 +1,49 @@ +ackage com.example.iaso.matrix; + +public final class MatrixPrompts { + private MatrixPrompts() {} + + // ── SYSTEM PROMPT ──────────────────────────────────────────────────────── + // Rules, persona, schema — sent to the system field. + // Fixed. Never changes between calls. Claude reads this first + // and treats it as standing instructions for the session. + // ───────────────────────────────────────────────────────────────────────── + public static final String TIMELINE_SYSTEM = + "You are Monad, a milestone planning engine.\n\n" + + + "TASK:\n" + + "Decompose the given goal into an ordered list of milestones.\n" + + "Each milestone must be a concrete, completable phase of work.\n\n" + + + "OUTPUT RULES (CRITICAL):\n" + + "1. Reply with a raw JSON array ONLY. No markdown, no backticks, no explanation.\n" + + "2. The array must start with [ and end with ].\n" + + "3. Every allocatedDays value must be >= 1.\n" + + "4. The SUM of all allocatedDays must equal exactly the totalDays given.\n" + + "5. No gaps between milestones. Milestone N starts the day after N-1 ends.\n" + + "6. Milestones must be ordered: foundational first, dependent last.\n" + + "7. description must be a specific, measurable definition of done\n" + + " (e.g. 'Can perform 10 pull-ups with correct form', not 'Get stronger').\n" + + "8. dependencies lists the zero-based indices of milestones that must\n" + + " be completed before this one. First milestone always has [].\n\n" + + + "SCHEMA (each element):\n" + + "{\n" + + " \"name\": \"Short milestone title\",\n" + + " \"description\": \"Measurable definition of done\",\n" + + " \"allocatedDays\": = 1>,\n" + + " \"dependencies\": []\n" + + "}\n\n" + + + "Begin your response with [ and nothing else."; + + // ── USER MESSAGE ───────────────────────────────────────────────────────── + // Just the goal data — sent to the user message field. + // Changes every call. Placeholders replaced at runtime in MatrixEngine. + // ───────────────────────────────────────────────────────────────────────── + public static final String TIMELINE_USER = + "Goal: {goalDescription}\n" + + "Daily time: {dailyMinutes} minutes/day\n" + + "Total days: {totalDays}"; +} + From 17b48a05676199bab2e9d08de81d78e0294d9d81 Mon Sep 17 00:00:00 2001 From: Shlok Chorge Date: Fri, 8 May 2026 15:24:56 +0530 Subject: [PATCH 02/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java b/app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java index d657259..5738cfd 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixPrompts.java @@ -1,4 +1,4 @@ -ackage com.example.iaso.matrix; +package com.example.iaso.matrix; public final class MatrixPrompts { private MatrixPrompts() {} From 96aaeb142364d97c477190643d365c52b29285bf Mon Sep 17 00:00:00 2001 From: Shlok Chorge Date: Fri, 8 May 2026 15:25:52 +0530 Subject: [PATCH 03/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../com/example/iaso/ConvexApiHelper.java | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index 26adb22..6bc10d4 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -97,58 +97,58 @@ public void sendMessageToClaude(String userMessage, ClaudeResponseCallback callb }); } -// ==================== MATRIX METHOD (system + user split) ==================== - -/** - * For MatrixEngine — sends system prompt and user message separately - * System = rules/schema, User = just the goal data - */ -public void sendMessageToClaude( - String systemPrompt, - String userMessage, - ClaudeResponseCallback callback) { - - executor.execute(() -> { - try { - JSONObject argsObject = new JSONObject(); - argsObject.put("systemPrompt", systemPrompt); - argsObject.put("userMessage", userMessage); - - JSONObject requestJson = new JSONObject(); - requestJson.put("path", CONVEX_ACTION_PATH); - requestJson.put("args", argsObject); - - RequestBody body = RequestBody.create(requestJson.toString(), JSON); - Request request = new Request.Builder() - .url(CONVEX_URL + "/api/action") - .post(body) - .addHeader("Content-Type", "application/json") - .build(); - - try (Response response = client.newCall(request).execute()) { - if (!response.isSuccessful()) { - postError(callback, "Server error: " + response.code()); - return; - } + // ==================== MATRIX METHOD (system + user split) ==================== - String responseBody = response.body() != null ? response.body().string() : ""; - JSONObject jsonResponse = new JSONObject(responseBody); - String status = jsonResponse.optString("status", ""); + /** + * For MatrixEngine — sends system prompt and user message separately + * System = rules/schema, User = just the goal data + */ + public void sendMessageToClaude( + String systemPrompt, + String userMessage, + ClaudeResponseCallback callback) { - if ("success".equals(status)) { - postSuccess(callback, jsonResponse.optString("value", "")); - } else { - postError(callback, "Convex error: " + jsonResponse.optString("errorMessage", "Unknown error")); + executor.execute(() -> { + try { + JSONObject argsObject = new JSONObject(); + argsObject.put("systemPrompt", systemPrompt); + argsObject.put("userMessage", userMessage); + + JSONObject requestJson = new JSONObject(); + requestJson.put("path", CONVEX_ACTION_PATH); + requestJson.put("args", argsObject); + + RequestBody body = RequestBody.create(requestJson.toString(), JSON); + Request request = new Request.Builder() + .url(CONVEX_URL + "/api/action") + .post(body) + .addHeader("Content-Type", "application/json") + .build(); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + postError(callback, "Server error: " + response.code()); + return; + } + + String responseBody = response.body() != null ? response.body().string() : ""; + JSONObject jsonResponse = new JSONObject(responseBody); + String status = jsonResponse.optString("status", ""); + + if ("success".equals(status)) { + postSuccess(callback, jsonResponse.optString("value", "")); + } else { + postError(callback, "Convex error: " + jsonResponse.optString("errorMessage", "Unknown error")); + } } - } - } catch (IOException e) { - postError(callback, "Network error: " + e.getMessage()); - } catch (JSONException e) { - postError(callback, "Error building request: " + e.getMessage()); - } - }); -} + } catch (IOException e) { + postError(callback, "Network error: " + e.getMessage()); + } catch (JSONException e) { + postError(callback, "Error building request: " + e.getMessage()); + } + }); + } // ==================== NEW METHOD (multi-turn conversation) ==================== From 2ed0c72b411baa23176060cd339547e0c5a13dc4 Mon Sep 17 00:00:00 2001 From: Shlok Chorge Date: Fri, 8 May 2026 15:26:05 +0530 Subject: [PATCH 04/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../main/java/com/example/iaso/matrix/MatrixEngine.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index 7e2ec18..abeba14 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -46,15 +46,18 @@ public void generateTimeline( .replace("{dailyMinutes}", String.valueOf(dailyMinutes)) .replace("{totalDays}", String.valueOf(totalDays)); - Log.d(TAG, "=== SYSTEM PROMPT ===\n" + system); - Log.d(TAG, "=== USER MESSAGE ===\n" + user); + Log.d(TAG, "Generating timeline request: dailyMinutes=" + dailyMinutes + + ", totalDays=" + totalDays + + ", systemPromptLength=" + system.length() + + ", userMessageLength=" + user.length()); ConvexApiHelper api = new ConvexApiHelper(); api.sendMessageToClaude(system, user, new ConvexApiHelper.ClaudeResponseCallback() { @Override public void onSuccess(String response) { - Log.d(TAG, "=== RAW RESPONSE ===\n" + response); + Log.d(TAG, "Received timeline response: responseLength=" + + (response != null ? response.length() : 0)); try { List milestones = parseMilestones(response); From 8c913db994bd6a20bca272a71437b063fdce746a Mon Sep 17 00:00:00 2001 From: Shlok Chorge Date: Fri, 8 May 2026 15:26:15 +0530 Subject: [PATCH 05/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../java/com/example/iaso/matrix/MatrixEngine.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index abeba14..0315cf3 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -41,10 +41,16 @@ public void generateTimeline( String system = MatrixPrompts.TIMELINE_SYSTEM; // User message — just the goal data, changes every call - String user = MatrixPrompts.TIMELINE_USER - .replace("{goalDescription}", goalDescription) - .replace("{dailyMinutes}", String.valueOf(dailyMinutes)) - .replace("{totalDays}", String.valueOf(totalDays)); + String userTemplate = MatrixPrompts.TIMELINE_USER + .replace("{goalDescription}", "%s") + .replace("{dailyMinutes}", "%s") + .replace("{totalDays}", "%s"); + String user = String.format( + userTemplate, + goalDescription, + String.valueOf(dailyMinutes), + String.valueOf(totalDays) + ); Log.d(TAG, "Generating timeline request: dailyMinutes=" + dailyMinutes + ", totalDays=" + totalDays From e1e5aec789ad98644f8f16f0935700b160fa54e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 10:02:46 +0000 Subject: [PATCH 06/16] fix(matrix): normalize milestone day overflow safely Agent-Logs-Url: https://github.com/openspace-inc/OpenSpace/sessions/5feba14b-fa98-4c8e-a695-06906f047ed3 Co-authored-by: shlokchorge <224512884+shlokchorge@users.noreply.github.com> --- .../com/example/iaso/matrix/MatrixEngine.java | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index 0315cf3..06d3bef 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -72,13 +72,16 @@ public void onSuccess(String response) { return; } - // Validate day sum — soft fix: redistribute remainder into last milestone + // Validate day sum and normalize to totalDays when possible int sum = 0; for (MatrixMilestone m : milestones) sum += m.getAllocatedDays(); if (sum != totalDays) { Log.w(TAG, "Day sum mismatch: expected " + totalDays + ", got " + sum); - MatrixMilestone last = milestones.get(milestones.size() - 1); - last.setAllocatedDays(Math.max(1, last.getAllocatedDays() + (totalDays - sum))); + boolean normalized = normalizeMilestoneDays(milestones, totalDays); + if (!normalized) { + callback.onError("Failed to normalize milestones to requested total days."); + return; + } } MatrixGoal goal = buildGoal(goalDescription, totalDays, milestones); @@ -205,6 +208,52 @@ private List buildMilestonesFromArray(JSONArray array) throws J return milestones; } + private boolean normalizeMilestoneDays(List milestones, int totalDays) { + int sum = 0; + for (MatrixMilestone milestone : milestones) { + sum += milestone.getAllocatedDays(); + } + + if (sum == totalDays) { + return true; + } + + if (sum < totalDays) { + MatrixMilestone last = milestones.get(milestones.size() - 1); + last.setAllocatedDays(last.getAllocatedDays() + (totalDays - sum)); + recomputeStartDays(milestones); + return true; + } + + int overflow = sum - totalDays; + for (int i = milestones.size() - 1; i >= 0 && overflow > 0; i--) { + MatrixMilestone milestone = milestones.get(i); + int reducible = milestone.getAllocatedDays() - 1; + if (reducible <= 0) { + continue; + } + + int reduction = Math.min(reducible, overflow); + milestone.setAllocatedDays(milestone.getAllocatedDays() - reduction); + overflow -= reduction; + } + + if (overflow > 0) { + return false; + } + + recomputeStartDays(milestones); + return true; + } + + private void recomputeStartDays(List milestones) { + int startDay = 1; + for (MatrixMilestone milestone : milestones) { + milestone.setStartDay(startDay); + startDay += milestone.getAllocatedDays(); + } + } + // ─── Goal Assembly ─────────────────────────────────────────────────────── private MatrixGoal buildGoal(String goalDescription, int totalDays, List milestones) { From 52bbb8f10454df9e7526b58ae8446d4888b1c395 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 10:43:45 +0000 Subject: [PATCH 07/16] fix(matrix): set parentGoalId on generated milestones Agent-Logs-Url: https://github.com/openspace-inc/OpenSpace/sessions/c366579a-c32c-4480-92c8-f46f945b16f3 Co-authored-by: shlokchorge <224512884+shlokchorge@users.noreply.github.com> --- app/src/main/java/com/example/iaso/matrix/MatrixEngine.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index 06d3bef..e7ec00a 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -258,13 +258,17 @@ private void recomputeStartDays(List milestones) { private MatrixGoal buildGoal(String goalDescription, int totalDays, List milestones) { MatrixGoal goal = new MatrixGoal(); - goal.setGoalId(UUID.randomUUID().toString()); + String goalId = UUID.randomUUID().toString(); + goal.setGoalId(goalId); goal.setHabitName(goalDescription); goal.setGoalDescription(goalDescription); long now = System.currentTimeMillis(); goal.setStartDate(now); goal.setTotalDays(totalDays); + for (MatrixMilestone milestone : milestones) { + milestone.setParentGoalId(goalId); + } goal.setMilestones(milestones); return goal; From 6606d359ae15b49bdd3639ab5d98f0509f70b5bf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 10:48:32 +0000 Subject: [PATCH 08/16] fix(matrix): align Convex payload and close helper executors Agent-Logs-Url: https://github.com/openspace-inc/OpenSpace/sessions/19d0b5fa-446e-4a03-98a3-5cb25c8cc2bf Co-authored-by: shlokchorge <224512884+shlokchorge@users.noreply.github.com> --- .../com/example/iaso/ConvexApiHelper.java | 32 +++++++++++++++++-- .../com/example/iaso/matrix/MatrixEngine.java | 10 ++++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index 6bc10d4..f31ed93 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -11,6 +11,8 @@ import java.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -110,9 +112,23 @@ public void sendMessageToClaude( executor.execute(() -> { try { + JSONArray messagesArray = new JSONArray(); + JSONObject userMsg = new JSONObject(); + userMsg.put("role", "user"); + userMsg.put("content", userMessage); + messagesArray.put(userMsg); + + int dailyMinutes = extractFirstInt(userMessage, "Daily\\s*time:\\s*(\\d+)", 30); + int totalDays = extractFirstInt(userMessage, "Total\\s*days:\\s*(\\d+)", 30); + + JSONObject contextObj = new JSONObject(); + contextObj.put("dailyMinutes", dailyMinutes); + contextObj.put("targetDays", totalDays); + contextObj.put("phase", "generating"); + JSONObject argsObject = new JSONObject(); - argsObject.put("systemPrompt", systemPrompt); - argsObject.put("userMessage", userMessage); + argsObject.put("messages", messagesArray); + argsObject.put("context", contextObj); JSONObject requestJson = new JSONObject(); requestJson.put("path", CONVEX_ACTION_PATH); @@ -235,7 +251,17 @@ private void postError(ClaudeResponseCallback callback, String errorMessage) { mainHandler.post(() -> callback.onError(errorMessage)); } + private int extractFirstInt(String input, String pattern, int fallback) { + Matcher matcher = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(input); + if (matcher.find()) { + try { + return Integer.parseInt(matcher.group(1)); + } catch (NumberFormatException ignored) { } + } + return fallback; + } + public void shutdown() { executor.shutdown(); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index e7ec00a..5c5aeca 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -101,13 +101,19 @@ public void onSuccess(String response) { } catch (Exception e) { Log.e(TAG, "Parse/build error: " + e.getMessage(), e); callback.onError("Failed to build timeline: " + e.getMessage()); + } finally { + api.shutdown(); } } @Override public void onError(String errorMessage) { - Log.e(TAG, "ConvexApiHelper error: " + errorMessage); - callback.onError(errorMessage); + try { + Log.e(TAG, "ConvexApiHelper error: " + errorMessage); + callback.onError(errorMessage); + } finally { + api.shutdown(); + } } }); } From 1b0ebfed8a525dee3bdb0263096ed5191aca0a06 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 10:50:09 +0000 Subject: [PATCH 09/16] refactor(convex): extract parsing patterns and defaults Agent-Logs-Url: https://github.com/openspace-inc/OpenSpace/sessions/19d0b5fa-446e-4a03-98a3-5cb25c8cc2bf Co-authored-by: shlokchorge <224512884+shlokchorge@users.noreply.github.com> --- .../java/com/example/iaso/ConvexApiHelper.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index f31ed93..2b14b36 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -26,6 +26,12 @@ public class ConvexApiHelper { private static final String CONVEX_URL = "https://neighborly-chihuahua-847.convex.cloud"; private static final String CONVEX_ACTION_PATH = "workhorse:getClaudeResponse"; + private static final int DEFAULT_DAILY_MINUTES = 30; + private static final int DEFAULT_TOTAL_DAYS = 30; + private static final Pattern DAILY_TIME_PATTERN = + Pattern.compile("Daily\\s*time:\\s*(\\d+)", Pattern.CASE_INSENSITIVE); + private static final Pattern TOTAL_DAYS_PATTERN = + Pattern.compile("Total\\s*days:\\s*(\\d+)", Pattern.CASE_INSENSITIVE); // ==================== SETUP ==================== @@ -118,8 +124,8 @@ public void sendMessageToClaude( userMsg.put("content", userMessage); messagesArray.put(userMsg); - int dailyMinutes = extractFirstInt(userMessage, "Daily\\s*time:\\s*(\\d+)", 30); - int totalDays = extractFirstInt(userMessage, "Total\\s*days:\\s*(\\d+)", 30); + int dailyMinutes = extractFirstInt(userMessage, DAILY_TIME_PATTERN, DEFAULT_DAILY_MINUTES); + int totalDays = extractFirstInt(userMessage, TOTAL_DAYS_PATTERN, DEFAULT_TOTAL_DAYS); JSONObject contextObj = new JSONObject(); contextObj.put("dailyMinutes", dailyMinutes); @@ -251,8 +257,12 @@ private void postError(ClaudeResponseCallback callback, String errorMessage) { mainHandler.post(() -> callback.onError(errorMessage)); } - private int extractFirstInt(String input, String pattern, int fallback) { - Matcher matcher = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(input); + /** + * Extracts the first integer captured by the provided regex pattern. + * Returns fallback when no match is found or parsing fails. + */ + private int extractFirstInt(String input, Pattern pattern, int fallback) { + Matcher matcher = pattern.matcher(input); if (matcher.find()) { try { return Integer.parseInt(matcher.group(1)); From bb4df1412716067943dd4bc33c8be9030fac4130 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 10:51:43 +0000 Subject: [PATCH 10/16] chore(convex): log defaults when timeline context parsing falls back Agent-Logs-Url: https://github.com/openspace-inc/OpenSpace/sessions/19d0b5fa-446e-4a03-98a3-5cb25c8cc2bf Co-authored-by: shlokchorge <224512884+shlokchorge@users.noreply.github.com> --- app/src/main/java/com/example/iaso/ConvexApiHelper.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index 2b14b36..c34ee74 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -2,6 +2,7 @@ import android.os.Handler; import android.os.Looper; +import android.util.Log; import org.json.JSONArray; import org.json.JSONException; @@ -24,6 +25,7 @@ public class ConvexApiHelper { // ==================== CONFIGURATION ==================== + private static final String TAG = "ConvexApiHelper"; private static final String CONVEX_URL = "https://neighborly-chihuahua-847.convex.cloud"; private static final String CONVEX_ACTION_PATH = "workhorse:getClaudeResponse"; private static final int DEFAULT_DAILY_MINUTES = 30; @@ -124,8 +126,8 @@ public void sendMessageToClaude( userMsg.put("content", userMessage); messagesArray.put(userMsg); - int dailyMinutes = extractFirstInt(userMessage, DAILY_TIME_PATTERN, DEFAULT_DAILY_MINUTES); - int totalDays = extractFirstInt(userMessage, TOTAL_DAYS_PATTERN, DEFAULT_TOTAL_DAYS); + int dailyMinutes = extractFirstInt(userMessage, DAILY_TIME_PATTERN, DEFAULT_DAILY_MINUTES, "dailyMinutes"); + int totalDays = extractFirstInt(userMessage, TOTAL_DAYS_PATTERN, DEFAULT_TOTAL_DAYS, "totalDays"); JSONObject contextObj = new JSONObject(); contextObj.put("dailyMinutes", dailyMinutes); @@ -261,13 +263,14 @@ private void postError(ClaudeResponseCallback callback, String errorMessage) { * Extracts the first integer captured by the provided regex pattern. * Returns fallback when no match is found or parsing fails. */ - private int extractFirstInt(String input, Pattern pattern, int fallback) { + private int extractFirstInt(String input, Pattern pattern, int fallback, String fieldName) { Matcher matcher = pattern.matcher(input); if (matcher.find()) { try { return Integer.parseInt(matcher.group(1)); } catch (NumberFormatException ignored) { } } + Log.w(TAG, "Falling back to default " + fieldName + "=" + fallback); return fallback; } From 45d9eda40ee7d8859a10e6f76f429654b919a932 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 10:53:07 +0000 Subject: [PATCH 11/16] fix(convex): add explicit timeline-context overload for matrix calls Agent-Logs-Url: https://github.com/openspace-inc/OpenSpace/sessions/19d0b5fa-446e-4a03-98a3-5cb25c8cc2bf Co-authored-by: shlokchorge <224512884+shlokchorge@users.noreply.github.com> --- .../com/example/iaso/ConvexApiHelper.java | 21 +++++++++++++++---- .../com/example/iaso/matrix/MatrixEngine.java | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index c34ee74..74ee8e0 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -117,7 +117,21 @@ public void sendMessageToClaude( String systemPrompt, String userMessage, ClaudeResponseCallback callback) { + int dailyMinutes = extractFirstInt(userMessage, DAILY_TIME_PATTERN, DEFAULT_DAILY_MINUTES, "dailyMinutes"); + int totalDays = extractFirstInt(userMessage, TOTAL_DAYS_PATTERN, DEFAULT_TOTAL_DAYS, "totalDays"); + sendMessageToClaude(systemPrompt, userMessage, dailyMinutes, totalDays, callback); + } + /** + * Matrix-specific overload that forwards to the current Convex action schema: + * args = { messages, context } where context includes timeline params. + */ + public void sendMessageToClaude( + String systemPrompt, + String userMessage, + int dailyMinutes, + int totalDays, + ClaudeResponseCallback callback) { executor.execute(() -> { try { JSONArray messagesArray = new JSONArray(); @@ -126,9 +140,6 @@ public void sendMessageToClaude( userMsg.put("content", userMessage); messagesArray.put(userMsg); - int dailyMinutes = extractFirstInt(userMessage, DAILY_TIME_PATTERN, DEFAULT_DAILY_MINUTES, "dailyMinutes"); - int totalDays = extractFirstInt(userMessage, TOTAL_DAYS_PATTERN, DEFAULT_TOTAL_DAYS, "totalDays"); - JSONObject contextObj = new JSONObject(); contextObj.put("dailyMinutes", dailyMinutes); contextObj.put("targetDays", totalDays); @@ -268,7 +279,9 @@ private int extractFirstInt(String input, Pattern pattern, int fallback, String if (matcher.find()) { try { return Integer.parseInt(matcher.group(1)); - } catch (NumberFormatException ignored) { } + } catch (NumberFormatException ignored) { + Log.w(TAG, "Failed parsing " + fieldName + " from input, using default " + fallback); + } } Log.w(TAG, "Falling back to default " + fieldName + "=" + fallback); return fallback; diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index 5c5aeca..51f228a 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -58,7 +58,7 @@ public void generateTimeline( + ", userMessageLength=" + user.length()); ConvexApiHelper api = new ConvexApiHelper(); - api.sendMessageToClaude(system, user, new ConvexApiHelper.ClaudeResponseCallback() { + api.sendMessageToClaude(system, user, dailyMinutes, totalDays, new ConvexApiHelper.ClaudeResponseCallback() { @Override public void onSuccess(String response) { From 2b8fc0032cbc867d0fe8e0a21ca4b62c779791b7 Mon Sep 17 00:00:00 2001 From: Shlok Chorge Date: Fri, 8 May 2026 16:31:36 +0530 Subject: [PATCH 12/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- app/src/main/java/com/example/iaso/matrix/MatrixEngine.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index 51f228a..108cc05 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -11,7 +11,6 @@ import org.json.JSONException; import org.json.JSONObject; -import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.regex.Matcher; From a6252c4645a015c559e4cf3abd5da5bacd4cc9d1 Mon Sep 17 00:00:00 2001 From: Shlok Chorge Date: Fri, 8 May 2026 16:31:50 +0530 Subject: [PATCH 13/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../main/java/com/example/iaso/ConvexApiHelper.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index 74ee8e0..4cb2f5a 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -110,24 +110,23 @@ public void sendMessageToClaude(String userMessage, ClaudeResponseCallback callb // ==================== MATRIX METHOD (system + user split) ==================== /** - * For MatrixEngine — sends system prompt and user message separately - * System = rules/schema, User = just the goal data + * MatrixEngine entry point for the current Convex action contract. + * Sends only the user message plus timeline context derived from that message. */ public void sendMessageToClaude( - String systemPrompt, String userMessage, ClaudeResponseCallback callback) { int dailyMinutes = extractFirstInt(userMessage, DAILY_TIME_PATTERN, DEFAULT_DAILY_MINUTES, "dailyMinutes"); int totalDays = extractFirstInt(userMessage, TOTAL_DAYS_PATTERN, DEFAULT_TOTAL_DAYS, "totalDays"); - sendMessageToClaude(systemPrompt, userMessage, dailyMinutes, totalDays, callback); + sendMessageToClaude(userMessage, dailyMinutes, totalDays, callback); } /** * Matrix-specific overload that forwards to the current Convex action schema: - * args = { messages, context } where context includes timeline params. + * args = { messages, context } where messages contains only the user message + * and context includes timeline params. */ public void sendMessageToClaude( - String systemPrompt, String userMessage, int dailyMinutes, int totalDays, From 5483b99ac43e987fc4b15c0035d7c278dcc63d9f Mon Sep 17 00:00:00 2001 From: Shlok Chorge Date: Fri, 8 May 2026 16:38:16 +0530 Subject: [PATCH 14/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- app/src/main/java/com/example/iaso/matrix/MatrixEngine.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index 108cc05..474f01b 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -50,14 +50,14 @@ public void generateTimeline( String.valueOf(dailyMinutes), String.valueOf(totalDays) ); + String prompt = system + "\n\n" + user; Log.d(TAG, "Generating timeline request: dailyMinutes=" + dailyMinutes + ", totalDays=" + totalDays - + ", systemPromptLength=" + system.length() - + ", userMessageLength=" + user.length()); + + ", promptLength=" + prompt.length()); ConvexApiHelper api = new ConvexApiHelper(); - api.sendMessageToClaude(system, user, dailyMinutes, totalDays, new ConvexApiHelper.ClaudeResponseCallback() { + api.sendMessageToClaude(prompt, dailyMinutes, totalDays, new ConvexApiHelper.ClaudeResponseCallback() { @Override public void onSuccess(String response) { From fa0717e1d9d3dedcc99550791cc5685212717d4e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 11:11:44 +0000 Subject: [PATCH 15/16] fix(matrix): restore system prompt passthrough and helper overloads Agent-Logs-Url: https://github.com/openspace-inc/OpenSpace/sessions/d2364f56-6741-4d48-b160-253ec0c8a9e1 Co-authored-by: shlokchorge <224512884+shlokchorge@users.noreply.github.com> --- .../com/example/iaso/ConvexApiHelper.java | 63 +++++-------------- .../com/example/iaso/matrix/MatrixEngine.java | 6 +- convex/workhorse.ts | 19 +++--- 3 files changed, 28 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index 4cb2f5a..5acec75 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -64,69 +64,31 @@ public ConvexApiHelper() { * Do NOT remove until workhorse.java is fully migrated */ public void sendMessageToClaude(String userMessage, ClaudeResponseCallback callback) { - executor.execute(() -> { - try { - JSONObject argsObject = new JSONObject(); - argsObject.put("userMessage", userMessage); - - JSONObject requestJson = new JSONObject(); - requestJson.put("path", CONVEX_ACTION_PATH); - requestJson.put("args", argsObject); - - RequestBody body = RequestBody.create(requestJson.toString(), JSON); - Request request = new Request.Builder() - .url(CONVEX_URL + "/api/action") - .post(body) - .addHeader("Content-Type", "application/json") - .build(); - - try (Response response = client.newCall(request).execute()) { - if (!response.isSuccessful()) { - postError(callback, "Server error: " + response.code()); - return; - } - - String responseBody = response.body() != null ? response.body().string() : ""; - JSONObject jsonResponse = new JSONObject(responseBody); - String status = jsonResponse.optString("status", ""); - - if ("success".equals(status)) { - String claudeResponse = jsonResponse.optString("value", ""); - postSuccess(callback, claudeResponse); - } else { - String errorMessage = jsonResponse.optString("errorMessage", "Unknown error from Convex"); - postError(callback, "Convex error: " + errorMessage); - } - } - - } catch (IOException e) { - postError(callback, "Network error: " + e.getMessage()); - } catch (JSONException e) { - postError(callback, "Error parsing response: " + e.getMessage()); - } - }); + int dailyMinutes = extractFirstInt(userMessage, DAILY_TIME_PATTERN, DEFAULT_DAILY_MINUTES, "dailyMinutes"); + int totalDays = extractFirstInt(userMessage, TOTAL_DAYS_PATTERN, DEFAULT_TOTAL_DAYS, "totalDays"); + sendMessageToClaude(null, userMessage, dailyMinutes, totalDays, callback); } - // ==================== MATRIX METHOD (system + user split) ==================== - /** - * MatrixEngine entry point for the current Convex action contract. - * Sends only the user message plus timeline context derived from that message. + * Matrix-specific overload that forwards to the current Convex action schema + * without a custom system prompt. */ public void sendMessageToClaude( String userMessage, + int dailyMinutes, + int totalDays, ClaudeResponseCallback callback) { - int dailyMinutes = extractFirstInt(userMessage, DAILY_TIME_PATTERN, DEFAULT_DAILY_MINUTES, "dailyMinutes"); - int totalDays = extractFirstInt(userMessage, TOTAL_DAYS_PATTERN, DEFAULT_TOTAL_DAYS, "totalDays"); - sendMessageToClaude(userMessage, dailyMinutes, totalDays, callback); + sendMessageToClaude(null, userMessage, dailyMinutes, totalDays, callback); } /** * Matrix-specific overload that forwards to the current Convex action schema: * args = { messages, context } where messages contains only the user message - * and context includes timeline params. + * and context includes timeline params. A custom system prompt can be passed + * through to Convex for prompt-control use cases (e.g. Matrix JSON schema). */ public void sendMessageToClaude( + String systemPrompt, String userMessage, int dailyMinutes, int totalDays, @@ -147,6 +109,9 @@ public void sendMessageToClaude( JSONObject argsObject = new JSONObject(); argsObject.put("messages", messagesArray); argsObject.put("context", contextObj); + if (systemPrompt != null && !systemPrompt.trim().isEmpty()) { + argsObject.put("systemPrompt", systemPrompt); + } JSONObject requestJson = new JSONObject(); requestJson.put("path", CONVEX_ACTION_PATH); diff --git a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java index 474f01b..432c6ae 100644 --- a/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java +++ b/app/src/main/java/com/example/iaso/matrix/MatrixEngine.java @@ -11,6 +11,7 @@ import org.json.JSONException; import org.json.JSONObject; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.regex.Matcher; @@ -50,14 +51,13 @@ public void generateTimeline( String.valueOf(dailyMinutes), String.valueOf(totalDays) ); - String prompt = system + "\n\n" + user; Log.d(TAG, "Generating timeline request: dailyMinutes=" + dailyMinutes + ", totalDays=" + totalDays - + ", promptLength=" + prompt.length()); + + ", promptLength=" + (system.length() + user.length())); ConvexApiHelper api = new ConvexApiHelper(); - api.sendMessageToClaude(prompt, dailyMinutes, totalDays, new ConvexApiHelper.ClaudeResponseCallback() { + api.sendMessageToClaude(system, user, dailyMinutes, totalDays, new ConvexApiHelper.ClaudeResponseCallback() { @Override public void onSuccess(String response) { diff --git a/convex/workhorse.ts b/convex/workhorse.ts index 348b886..41416e0 100644 --- a/convex/workhorse.ts +++ b/convex/workhorse.ts @@ -148,6 +148,7 @@ function extractGoalSummary( export const getClaudeResponse = action({ args: { + systemPrompt: v.optional(v.string()), messages: v.array( v.object({ role: v.union(v.literal("user"), v.literal("assistant")), @@ -169,13 +170,15 @@ export const getClaudeResponse = action({ // Select system prompt based on current phase const systemPrompt = - args.context.phase === "refining" - ? buildRefiningPrompt(args.context.dailyMinutes, args.context.targetDays) - : buildGeneratingPrompt( - args.context.dailyMinutes, - args.context.targetDays, - extractGoalSummary(args.messages) - ); + args.systemPrompt && args.systemPrompt.trim().length > 0 + ? args.systemPrompt + : args.context.phase === "refining" + ? buildRefiningPrompt(args.context.dailyMinutes, args.context.targetDays) + : buildGeneratingPrompt( + args.context.dailyMinutes, + args.context.targetDays, + extractGoalSummary(args.messages) + ); const response = await fetch("https://api.anthropic.com/v1/messages", { method: "POST", @@ -205,4 +208,4 @@ export const getClaudeResponse = action({ throw new Error("Unexpected response format from Claude API"); }, -}); \ No newline at end of file +}); From 5ac605796774a033f54661622efdae43186baf3e Mon Sep 17 00:00:00 2001 From: Shlok Chorge Date: Fri, 8 May 2026 16:54:35 +0530 Subject: [PATCH 16/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- app/src/main/java/com/example/iaso/ConvexApiHelper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/example/iaso/ConvexApiHelper.java b/app/src/main/java/com/example/iaso/ConvexApiHelper.java index 5acec75..5fb529f 100644 --- a/app/src/main/java/com/example/iaso/ConvexApiHelper.java +++ b/app/src/main/java/com/example/iaso/ConvexApiHelper.java @@ -247,7 +247,6 @@ private int extractFirstInt(String input, Pattern pattern, int fallback, String Log.w(TAG, "Failed parsing " + fieldName + " from input, using default " + fallback); } } - Log.w(TAG, "Falling back to default " + fieldName + "=" + fallback); return fallback; }