specsmd 0.1.42 → 0.1.43
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/lib/dashboard/tui/app.js +68 -14
- package/package.json +1 -1
package/lib/dashboard/tui/app.js
CHANGED
|
@@ -905,6 +905,46 @@ function buildIntentScopedLabel(snapshot, intentId, filePath, fallbackName = 'fi
|
|
|
905
905
|
return safeIntentId ? `${safeIntentId}/${safeFallback}` : safeFallback;
|
|
906
906
|
}
|
|
907
907
|
|
|
908
|
+
function findIntentIdForWorkItem(snapshot, workItemId) {
|
|
909
|
+
if (typeof workItemId !== 'string' || workItemId.trim() === '') {
|
|
910
|
+
return '';
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
const intents = Array.isArray(snapshot?.intents) ? snapshot.intents : [];
|
|
914
|
+
for (const intent of intents) {
|
|
915
|
+
const items = Array.isArray(intent?.workItems) ? intent.workItems : [];
|
|
916
|
+
if (items.some((item) => item?.id === workItemId)) {
|
|
917
|
+
return intent?.id || '';
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
return '';
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
function resolveFireWorkItemPath(snapshot, intentId, workItemId, explicitPath) {
|
|
925
|
+
if (typeof explicitPath === 'string' && explicitPath.trim() !== '') {
|
|
926
|
+
return explicitPath;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
if (typeof snapshot?.rootPath !== 'string' || snapshot.rootPath.trim() === '') {
|
|
930
|
+
return null;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
if (typeof workItemId !== 'string' || workItemId.trim() === '') {
|
|
934
|
+
return null;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
const safeIntentId = typeof intentId === 'string' && intentId.trim() !== ''
|
|
938
|
+
? intentId
|
|
939
|
+
: findIntentIdForWorkItem(snapshot, workItemId);
|
|
940
|
+
|
|
941
|
+
if (!safeIntentId) {
|
|
942
|
+
return null;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
return path.join(snapshot.rootPath, 'intents', safeIntentId, 'work-items', `${workItemId}.md`);
|
|
946
|
+
}
|
|
947
|
+
|
|
908
948
|
function collectFireRunFiles(run) {
|
|
909
949
|
if (!run || typeof run.folderPath !== 'string') {
|
|
910
950
|
return [];
|
|
@@ -1156,13 +1196,32 @@ function buildFireCurrentRunGroups(snapshot) {
|
|
|
1156
1196
|
const status = currentWorkItem?.status || 'pending';
|
|
1157
1197
|
const statusTag = status === 'in_progress' ? 'current' : status;
|
|
1158
1198
|
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1199
|
+
const runIntentId = typeof run?.intent === 'string' ? run.intent : '';
|
|
1200
|
+
const currentWorkItemFiles = workItems.map((item, index) => {
|
|
1201
|
+
const itemId = typeof item?.id === 'string' && item.id !== '' ? item.id : `work-item-${index + 1}`;
|
|
1202
|
+
const intentId = typeof item?.intent === 'string' && item.intent !== ''
|
|
1203
|
+
? item.intent
|
|
1204
|
+
: (runIntentId || findIntentIdForWorkItem(snapshot, itemId));
|
|
1205
|
+
const filePath = resolveFireWorkItemPath(snapshot, intentId, itemId, item?.filePath);
|
|
1206
|
+
if (!filePath) {
|
|
1207
|
+
return null;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
const itemMode = String(item?.mode || 'confirm').toUpperCase();
|
|
1211
|
+
const itemStatus = item?.status || 'pending';
|
|
1212
|
+
const isCurrent = Boolean(currentWorkItem?.id) && itemId === currentWorkItem.id;
|
|
1213
|
+
const itemScope = isCurrent
|
|
1214
|
+
? 'active'
|
|
1215
|
+
: (itemStatus === 'completed' ? 'completed' : 'upcoming');
|
|
1216
|
+
const itemStatusTag = isCurrent ? 'current' : itemStatus;
|
|
1217
|
+
const labelPath = buildIntentScopedLabel(snapshot, intentId, filePath, `${itemId}.md`);
|
|
1218
|
+
|
|
1219
|
+
return {
|
|
1220
|
+
label: `${labelPath} [${itemMode}] [${itemStatusTag}]`,
|
|
1221
|
+
path: filePath,
|
|
1222
|
+
scope: itemScope
|
|
1223
|
+
};
|
|
1224
|
+
}).filter(Boolean);
|
|
1166
1225
|
|
|
1167
1226
|
const currentRunFiles = collectFireRunFiles(run).map((fileEntry) => ({
|
|
1168
1227
|
...fileEntry,
|
|
@@ -1178,7 +1237,7 @@ function buildFireCurrentRunGroups(snapshot) {
|
|
|
1178
1237
|
},
|
|
1179
1238
|
{
|
|
1180
1239
|
key: `current:run:${run.id}:work-items`,
|
|
1181
|
-
label:
|
|
1240
|
+
label: `WORK ITEMS (${currentWorkItemFiles.length})`,
|
|
1182
1241
|
files: filterExistingFiles(currentWorkItemFiles)
|
|
1183
1242
|
},
|
|
1184
1243
|
{
|
|
@@ -2774,11 +2833,6 @@ function createDashboardApp(deps) {
|
|
|
2774
2833
|
}, [activeFlow, rowLengthSignature, snapshot?.generatedAt]);
|
|
2775
2834
|
|
|
2776
2835
|
useEffect(() => {
|
|
2777
|
-
if (ui.view !== 'runs') {
|
|
2778
|
-
setDeferredTabsReady(true);
|
|
2779
|
-
return undefined;
|
|
2780
|
-
}
|
|
2781
|
-
|
|
2782
2836
|
setDeferredTabsReady(false);
|
|
2783
2837
|
const timer = setTimeout(() => {
|
|
2784
2838
|
setDeferredTabsReady(true);
|
|
@@ -2786,7 +2840,7 @@ function createDashboardApp(deps) {
|
|
|
2786
2840
|
return () => {
|
|
2787
2841
|
clearTimeout(timer);
|
|
2788
2842
|
};
|
|
2789
|
-
}, [activeFlow
|
|
2843
|
+
}, [activeFlow]);
|
|
2790
2844
|
|
|
2791
2845
|
useEffect(() => {
|
|
2792
2846
|
setPaneFocus('main');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specsmd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.43",
|
|
4
4
|
"description": "Multi-agent orchestration system for AI-native software development. Delivers AI-DLC, Agile, and custom SDLC flows as markdown-based agent systems.",
|
|
5
5
|
"main": "lib/installer.js",
|
|
6
6
|
"bin": {
|