taskplane 0.21.5 → 0.21.7
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.
|
@@ -208,9 +208,9 @@ export function parsePromptForOrchestrator(
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
if (execTargetSectionBody !== null) {
|
|
211
|
-
// Match "Repo: api" or "**Repo:** api" or "
|
|
211
|
+
// Match "Repo: api" or "**Repo:** api" or "Workspace: api" with whitespace
|
|
212
212
|
const repoLineMatch = execTargetSectionBody.match(
|
|
213
|
-
/^\s*\*?\*?Repo:?\*?\*?\s+(\S+)/mi,
|
|
213
|
+
/^\s*\*?\*?(?:Repo|Workspace):?\*?\*?\s+(\S+)/mi,
|
|
214
214
|
);
|
|
215
215
|
if (repoLineMatch) {
|
|
216
216
|
const candidate = repoLineMatch[1].trim().toLowerCase();
|
|
@@ -220,10 +220,10 @@ export function parsePromptForOrchestrator(
|
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
// Priority 2 (fallback): Inline "**Repo:** <id>" anywhere in content
|
|
223
|
+
// Priority 2 (fallback): Inline "**Repo:** <id>" or "**Workspace:** <id>" anywhere in content
|
|
224
224
|
if (!promptRepoId) {
|
|
225
225
|
const inlineRepoMatch = content.match(
|
|
226
|
-
/^\*\*Repo:\*\*\s+(\S+)/m,
|
|
226
|
+
/^\*\*(?:Repo|Workspace):\*\*\s+(\S+)/m,
|
|
227
227
|
);
|
|
228
228
|
if (inlineRepoMatch) {
|
|
229
229
|
const candidate = inlineRepoMatch[1].trim().toLowerCase();
|
|
@@ -928,7 +928,40 @@ export function resolveTaskRouting(
|
|
|
928
928
|
}
|
|
929
929
|
}
|
|
930
930
|
|
|
931
|
-
// Precedence 3:
|
|
931
|
+
// Precedence 3: file scope inference — match file path prefixes against
|
|
932
|
+
// known workspace repo IDs. If file scope entries like "web-client/src/..."
|
|
933
|
+
// start with a repo name, route the task to that repo.
|
|
934
|
+
if (!resolvedId && task.fileScope && task.fileScope.length > 0) {
|
|
935
|
+
const repoIds = [...validRepoIds.keys()];
|
|
936
|
+
const repoCounts = new Map<string, number>();
|
|
937
|
+
for (const filePath of task.fileScope) {
|
|
938
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
939
|
+
for (const repoId of repoIds) {
|
|
940
|
+
if (normalized.startsWith(repoId + "/") || normalized === repoId) {
|
|
941
|
+
repoCounts.set(repoId, (repoCounts.get(repoId) || 0) + 1);
|
|
942
|
+
break; // first matching repo wins for this path
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
// Use the repo with the most file scope matches (majority vote)
|
|
947
|
+
if (repoCounts.size === 1) {
|
|
948
|
+
resolvedId = repoCounts.keys().next().value!;
|
|
949
|
+
source = "file-scope";
|
|
950
|
+
} else if (repoCounts.size > 1) {
|
|
951
|
+
// Multiple repos in file scope — pick the one with most entries.
|
|
952
|
+
// (Future: #51 will handle multi-repo tasks properly)
|
|
953
|
+
let maxCount = 0;
|
|
954
|
+
for (const [repoId, count] of repoCounts) {
|
|
955
|
+
if (count > maxCount) {
|
|
956
|
+
maxCount = count;
|
|
957
|
+
resolvedId = repoId;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
source = "file-scope";
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// Precedence 4: workspace default repo
|
|
932
965
|
if (!resolvedId) {
|
|
933
966
|
resolvedId = workspaceConfig.routing.defaultRepo;
|
|
934
967
|
source = "default";
|
|
@@ -940,7 +973,8 @@ export function resolveTaskRouting(
|
|
|
940
973
|
code: "TASK_REPO_UNRESOLVED",
|
|
941
974
|
message:
|
|
942
975
|
`Task ${task.taskId} has no resolved repo. ` +
|
|
943
|
-
`Add
|
|
976
|
+
`Add file scope paths prefixed with the repo name (e.g., "web-client/src/..."), ` +
|
|
977
|
+
`set repo_id on area "${task.areaName}", ` +
|
|
944
978
|
`or set routing.default_repo in the workspace config.`,
|
|
945
979
|
taskId: task.taskId,
|
|
946
980
|
taskPath: task.promptPath,
|