@thxgg/steward 0.1.17 → 0.1.19

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.
Files changed (124) hide show
  1. package/.env.example +0 -6
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/_nuxt/{BlTKcjLJ.js → BCiXS3ZV.js} +2 -2
  4. package/.output/public/_nuxt/BfUfZSFp.js +60 -0
  5. package/.output/public/_nuxt/{BMdjSp24.js → BfV4oCiT.js} +1 -1
  6. package/.output/public/_nuxt/{BSZqAKg4.js → Bs6UO7IT.js} +1 -1
  7. package/.output/public/_nuxt/C9AsKFSQ.js +1 -0
  8. package/.output/public/_nuxt/{BdjPva1I.js → C9jB6HQI.js} +1 -1
  9. package/.output/public/_nuxt/CCruYste.js +3 -0
  10. package/.output/public/_nuxt/CIIE0-WR.js +1 -0
  11. package/.output/public/_nuxt/{By7gAVcL.js → Cg4hnDua.js} +1 -1
  12. package/.output/public/_nuxt/CwdD8083.js +30 -0
  13. package/.output/public/_nuxt/{4r0X30JV.js → D2RLSKEu.js} +1 -1
  14. package/.output/public/_nuxt/{CbkpNvIu.js → D30YtxUg.js} +1 -1
  15. package/.output/public/_nuxt/{Beeir9iR.js → DEekox9p.js} +1 -1
  16. package/.output/public/_nuxt/{nX8Sf7cz.js → DddVAa3N.js} +1 -1
  17. package/.output/public/_nuxt/{Bh3vsUvl.js → MO41rxll.js} +1 -1
  18. package/.output/public/_nuxt/builds/latest.json +1 -1
  19. package/.output/public/_nuxt/builds/meta/627332c0-2e14-4849-8cac-e350f64ed513.json +1 -0
  20. package/.output/public/_nuxt/entry.Dp3jx0Yw.css +1 -0
  21. package/.output/public/_nuxt/f7vKgp5U.js +1 -0
  22. package/.output/public/_nuxt/xc3v2JZH.js +1 -0
  23. package/.output/server/chunks/_/git-api.mjs +1 -1
  24. package/.output/server/chunks/_/prd-service.mjs +177 -12
  25. package/.output/server/chunks/_/prd-service.mjs.map +1 -1
  26. package/.output/server/chunks/_/repos.mjs +272 -0
  27. package/.output/server/chunks/_/repos.mjs.map +1 -0
  28. package/.output/server/chunks/_/task-graph.mjs +19 -16
  29. package/.output/server/chunks/_/task-graph.mjs.map +1 -1
  30. package/.output/server/chunks/_/watcher.mjs +11 -35
  31. package/.output/server/chunks/_/watcher.mjs.map +1 -1
  32. package/.output/server/chunks/build/{Detail-MGwP_u2d.mjs → Detail-BcQGdJY5.mjs} +112 -46
  33. package/.output/server/chunks/build/Detail-BcQGdJY5.mjs.map +1 -0
  34. package/.output/server/chunks/build/{_prd_-C-Aj4fVa.mjs → _prd_-CD_Bds_B.mjs} +80 -7
  35. package/.output/server/chunks/build/_prd_-CD_Bds_B.mjs.map +1 -0
  36. package/.output/server/chunks/build/client.precomputed.mjs +1 -1
  37. package/.output/server/chunks/build/{default-Cao5eO80.mjs → default-BKKgG7HJ.mjs} +220 -24
  38. package/.output/server/chunks/build/default-BKKgG7HJ.mjs.map +1 -0
  39. package/.output/server/chunks/build/error-404-Bf6kdO80.mjs +1 -1
  40. package/.output/server/chunks/build/error-500-D_bcARXN.mjs +1 -1
  41. package/.output/server/chunks/build/{index-ljj9uTXI.mjs → index-DE1tjHAd.mjs} +3 -4
  42. package/.output/server/chunks/build/index-DE1tjHAd.mjs.map +1 -0
  43. package/.output/server/chunks/build/nuxt-link-SvT1nf8Z.mjs +1 -1
  44. package/.output/server/chunks/build/{repo-graph-EuhMeFt7.mjs → repo-graph-CBfhpnd5.mjs} +25 -12
  45. package/.output/server/chunks/build/repo-graph-CBfhpnd5.mjs.map +1 -0
  46. package/.output/server/chunks/build/server.mjs +14 -14
  47. package/.output/server/chunks/build/styles.mjs +2 -2
  48. package/.output/server/chunks/build/{usePrd-f7ylhIqs.mjs → usePrd-hXZOmvAv.mjs} +113 -9
  49. package/.output/server/chunks/build/usePrd-hXZOmvAv.mjs.map +1 -0
  50. package/.output/server/chunks/nitro/nitro.mjs +1051 -1365
  51. package/.output/server/chunks/nitro/nitro.mjs.map +1 -1
  52. package/.output/server/chunks/routes/api/browse.get.mjs +24 -6
  53. package/.output/server/chunks/routes/api/browse.get.mjs.map +1 -1
  54. package/.output/server/chunks/routes/api/index.get.mjs +3 -2
  55. package/.output/server/chunks/routes/api/index.get.mjs.map +1 -1
  56. package/.output/server/chunks/routes/api/index.post.mjs +22 -8
  57. package/.output/server/chunks/routes/api/index.post.mjs.map +1 -1
  58. package/.output/server/chunks/routes/api/repos/_repoId/git/commits.get.mjs +20 -11
  59. package/.output/server/chunks/routes/api/repos/_repoId/git/commits.get.mjs.map +1 -1
  60. package/.output/server/chunks/routes/api/repos/_repoId/git/diff.get.mjs +3 -2
  61. package/.output/server/chunks/routes/api/repos/_repoId/git/diff.get.mjs.map +1 -1
  62. package/.output/server/chunks/routes/api/repos/_repoId/git/file-content.get.mjs +3 -2
  63. package/.output/server/chunks/routes/api/repos/_repoId/git/file-content.get.mjs.map +1 -1
  64. package/.output/server/chunks/routes/api/repos/_repoId/git/file-diff.get.mjs +3 -2
  65. package/.output/server/chunks/routes/api/repos/_repoId/git/file-diff.get.mjs.map +1 -1
  66. package/.output/server/chunks/routes/api/repos/_repoId/graph.get.mjs +27 -3
  67. package/.output/server/chunks/routes/api/repos/_repoId/graph.get.mjs.map +1 -1
  68. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/archive.post.mjs +93 -0
  69. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/archive.post.mjs.map +1 -0
  70. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/graph.get.mjs +3 -2
  71. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/graph.get.mjs.map +1 -1
  72. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/progress.get.mjs +4 -3
  73. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/progress.get.mjs.map +1 -1
  74. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks/_taskId/commits.get.mjs +4 -3
  75. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks/_taskId/commits.get.mjs.map +1 -1
  76. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks.get.mjs +4 -3
  77. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks.get.mjs.map +1 -1
  78. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug_.get.mjs +3 -2
  79. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug_.get.mjs.map +1 -1
  80. package/.output/server/chunks/routes/api/repos/_repoId/prds.get.mjs +27 -3
  81. package/.output/server/chunks/routes/api/repos/_repoId/prds.get.mjs.map +1 -1
  82. package/.output/server/chunks/routes/api/repos/_repoId/refresh-git-repos.post.mjs +3 -2
  83. package/.output/server/chunks/routes/api/repos/_repoId/refresh-git-repos.post.mjs.map +1 -1
  84. package/.output/server/chunks/routes/api/repos/_repoId_.delete.mjs +3 -2
  85. package/.output/server/chunks/routes/api/repos/_repoId_.delete.mjs.map +1 -1
  86. package/.output/server/chunks/routes/api/runtime.get.mjs +2 -2
  87. package/.output/server/chunks/routes/api/state-migration/status.get.mjs +21 -0
  88. package/.output/server/chunks/routes/api/state-migration/status.get.mjs.map +1 -0
  89. package/.output/server/chunks/routes/api/watch.get.mjs +3 -2
  90. package/.output/server/chunks/routes/api/watch.get.mjs.map +1 -1
  91. package/.output/server/chunks/routes/renderer.mjs +1 -1
  92. package/.output/server/index.mjs +2 -2
  93. package/.output/server/package.json +1 -1
  94. package/README.md +5 -7
  95. package/dist/host/src/api/repos.js +0 -2
  96. package/dist/host/src/api/state.js +1 -7
  97. package/dist/host/src/index.js +2 -7
  98. package/dist/host/src/ui.js +2 -7
  99. package/dist/server/utils/db.js +15 -0
  100. package/dist/server/utils/prd-archive.js +53 -0
  101. package/dist/server/utils/prd-service.js +27 -11
  102. package/dist/server/utils/prd-state.js +11 -122
  103. package/dist/server/utils/repos.js +14 -4
  104. package/dist/server/utils/state-migration.js +225 -0
  105. package/dist/server/utils/state-schema.js +181 -4
  106. package/dist/server/utils/task-graph.js +21 -14
  107. package/package.json +1 -1
  108. package/.output/public/_nuxt/CbJfCtEa.js +0 -1
  109. package/.output/public/_nuxt/CmhLcqDu.js +0 -1
  110. package/.output/public/_nuxt/DC6iPLz1.js +0 -30
  111. package/.output/public/_nuxt/DD--ojY9.js +0 -3
  112. package/.output/public/_nuxt/DhKWRjCh.js +0 -60
  113. package/.output/public/_nuxt/builds/meta/f3f42dbd-d501-442b-871c-3d06157e7aa1.json +0 -1
  114. package/.output/public/_nuxt/c1sXju8w.js +0 -1
  115. package/.output/public/_nuxt/eGCjCghR.js +0 -1
  116. package/.output/public/_nuxt/entry.LcDOtJnR.css +0 -1
  117. package/.output/server/chunks/build/Detail-MGwP_u2d.mjs.map +0 -1
  118. package/.output/server/chunks/build/_prd_-C-Aj4fVa.mjs.map +0 -1
  119. package/.output/server/chunks/build/default-Cao5eO80.mjs.map +0 -1
  120. package/.output/server/chunks/build/index-ByZO4Bvq.mjs +0 -76
  121. package/.output/server/chunks/build/index-ByZO4Bvq.mjs.map +0 -1
  122. package/.output/server/chunks/build/index-ljj9uTXI.mjs.map +0 -1
  123. package/.output/server/chunks/build/repo-graph-EuhMeFt7.mjs.map +0 -1
  124. package/.output/server/chunks/build/usePrd-f7ylhIqs.mjs.map +0 -1
@@ -1,14 +1,13 @@
1
- import { defineComponent, markRaw, ref, watch, computed, mergeProps, unref, withCtx, createVNode, useModel, createTextVNode, toDisplayString, openBlock, createBlock, createCommentVNode, resolveDynamicComponent, Fragment, renderList, mergeModels, renderSlot, readonly, useSSRContext } from 'vue';
2
- import { ssrRenderAttrs, ssrRenderComponent, ssrInterpolate, ssrRenderVNode, ssrRenderList, ssrRenderClass, ssrRenderSlot, ssrRenderAttr, ssrRenderStyle } from 'vue/server-renderer';
3
- import { useMediaQuery, reactiveOmit } from '@vueuse/core';
1
+ import { defineComponent, unref, mergeProps, withCtx, renderSlot, markRaw, ref, watch, computed, createVNode, useModel, createTextVNode, toDisplayString, openBlock, createBlock, createCommentVNode, resolveDynamicComponent, Fragment, renderList, mergeModels, readonly, useSSRContext } from 'vue';
2
+ import { ssrRenderComponent, ssrRenderSlot, ssrRenderAttrs, ssrInterpolate, ssrRenderVNode, ssrRenderList, ssrRenderClass, ssrRenderAttr, ssrRenderStyle } from 'vue/server-renderer';
3
+ import { reactiveOmit, useMediaQuery } from '@vueuse/core';
4
4
  import { Background } from '@vue-flow/background';
5
5
  import { Controls } from '@vue-flow/controls';
6
6
  import { MarkerType, VueFlow, Position, Handle } from '@vue-flow/core';
7
7
  import { Loader2, AlertCircle, GitBranch, Circle, Clock3, CheckCircle2, AlertTriangle, Clock, ArrowLeft, Tag, ListOrdered, CheckSquare, Check, Link2, Diff, Calendar, ExternalLink, X, RefreshCw, Keyboard, FileDiff, FileCode, GitCommit, FileText, Plus, Minus, FolderGit2, ArrowRight, FileWarning, ChevronDown, Link, Link2Off, FileEdit, FileX, FilePlus } from 'lucide-vue-next';
8
- import { B as Button } from './index-ByZO4Bvq.mjs';
8
+ import { c as cn, B as Button, b as useToast } from './usePrd-hXZOmvAv.mjs';
9
9
  import { _ as _export_sfc } from './_plugin-vue_export-helper-1tPrXgE0.mjs';
10
10
  import { Primitive, useForwardPropsEmits, DialogRoot, DialogPortal, DialogContent, DialogClose, DialogTitle, DialogDescription, Separator as Separator$1, DialogOverlay, TooltipProvider as TooltipProvider$1, TooltipRoot, TooltipTrigger as TooltipTrigger$1, TooltipPortal, TooltipContent as TooltipContent$1, TooltipArrow, ScrollAreaRoot, ScrollAreaViewport, ScrollAreaCorner, ScrollAreaScrollbar, ScrollAreaThumb, DialogTrigger } from 'reka-ui';
11
- import { c as cn, b as useToast } from './usePrd-f7ylhIqs.mjs';
12
11
  import { cva } from 'class-variance-authority';
13
12
  import { _ as __nuxt_component_0$3 } from './nuxt-link-SvT1nf8Z.mjs';
14
13
 
@@ -1379,7 +1378,7 @@ function useGit() {
1379
1378
  return files;
1380
1379
  } catch (error) {
1381
1380
  showError("Failed to fetch diff", getErrorMessage(error));
1382
- return [];
1381
+ throw error;
1383
1382
  } finally {
1384
1383
  isLoadingDiff.value = false;
1385
1384
  }
@@ -1401,7 +1400,7 @@ function useGit() {
1401
1400
  return hunks;
1402
1401
  } catch (error) {
1403
1402
  showError("Failed to fetch file diff", getErrorMessage(error));
1404
- return [];
1403
+ throw error;
1405
1404
  } finally {
1406
1405
  isLoadingFileDiff.value = false;
1407
1406
  }
@@ -1423,7 +1422,7 @@ function useGit() {
1423
1422
  return result.content;
1424
1423
  } catch (error) {
1425
1424
  showError("Failed to fetch file content", getErrorMessage(error));
1426
- return null;
1425
+ throw error;
1427
1426
  } finally {
1428
1427
  isLoadingFileContent.value = false;
1429
1428
  }
@@ -1460,19 +1459,28 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1460
1459
  const error = ref(null);
1461
1460
  const fileDiffError = ref(null);
1462
1461
  const viewMode = ref("changes");
1462
+ function getErrorMessage(error2, fallback) {
1463
+ if (error2 && typeof error2 === "object") {
1464
+ const fetchError = error2;
1465
+ return fetchError.data?.message || fetchError.data?.statusMessage || fetchError.statusMessage || fetchError.message || fallback;
1466
+ }
1467
+ return fallback;
1468
+ }
1463
1469
  const selectedFileDiff = computed(() => files.value.find((f) => f.path === selectedFile.value));
1464
1470
  async function loadDiff() {
1465
1471
  error.value = null;
1466
1472
  files.value = [];
1467
1473
  selectedFile.value = void 0;
1468
1474
  hunks.value = [];
1469
- const result = await fetchDiff(props.repoId, props.commitSha, props.repoPath);
1470
- if (result.length === 0 && !isLoadingDiff.value) {
1471
- error.value = null;
1472
- }
1473
- files.value = result;
1474
- if (result.length > 0) {
1475
- selectedFile.value = result[0].path;
1475
+ fileContent.value = null;
1476
+ try {
1477
+ const result = await fetchDiff(props.repoId, props.commitSha, props.repoPath);
1478
+ files.value = result;
1479
+ if (result.length > 0) {
1480
+ selectedFile.value = result[0].path;
1481
+ }
1482
+ } catch (loadError) {
1483
+ error.value = getErrorMessage(loadError, "Could not load commit diff.");
1476
1484
  }
1477
1485
  }
1478
1486
  async function loadFileDiff() {
@@ -1482,11 +1490,17 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1482
1490
  return;
1483
1491
  }
1484
1492
  fileDiffError.value = null;
1485
- const result = await fetchFileDiff(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1486
- hunks.value = result;
1487
- if (viewMode.value === "full") {
1488
- const content = await fetchFileContent(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1489
- fileContent.value = content;
1493
+ try {
1494
+ const result = await fetchFileDiff(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1495
+ hunks.value = result;
1496
+ if (viewMode.value === "full") {
1497
+ const content = await fetchFileContent(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1498
+ fileContent.value = content;
1499
+ } else {
1500
+ fileContent.value = null;
1501
+ }
1502
+ } catch (loadError) {
1503
+ fileDiffError.value = getErrorMessage(loadError, "Could not load file diff.");
1490
1504
  }
1491
1505
  }
1492
1506
  function toggleViewMode() {
@@ -1494,8 +1508,13 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1494
1508
  }
1495
1509
  watch(viewMode, async (mode) => {
1496
1510
  if (mode === "full" && selectedFile.value && !fileContent.value) {
1497
- const content = await fetchFileContent(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1498
- fileContent.value = content;
1511
+ try {
1512
+ const content = await fetchFileContent(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1513
+ fileContent.value = content;
1514
+ fileDiffError.value = null;
1515
+ } catch (loadError) {
1516
+ fileDiffError.value = getErrorMessage(loadError, "Could not load file content.");
1517
+ }
1499
1518
  }
1500
1519
  });
1501
1520
  function handleFileSelect(path) {
@@ -1934,6 +1953,21 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1934
1953
  const { fetchCommits, isLoadingCommits } = useGit();
1935
1954
  const commitDetails = ref(/* @__PURE__ */ new Map());
1936
1955
  const failedCommits = ref(/* @__PURE__ */ new Set());
1956
+ function toShaLookupValue(sha) {
1957
+ return sha.trim().toLowerCase();
1958
+ }
1959
+ function toRepoLookupValue(repo) {
1960
+ return (repo || "").trim();
1961
+ }
1962
+ function createCommitKey(sha, repo) {
1963
+ return `${toRepoLookupValue(repo)}::${toShaLookupValue(sha)}`;
1964
+ }
1965
+ function matchesRequestedSha(requestedSha, commit) {
1966
+ const requested = toShaLookupValue(requestedSha);
1967
+ const fullSha = toShaLookupValue(commit.sha);
1968
+ const shortSha = toShaLookupValue(commit.shortSha);
1969
+ return fullSha === requested || shortSha === requested || fullSha.startsWith(requested) || requested.startsWith(fullSha) || shortSha.startsWith(requested) || requested.startsWith(shortSha);
1970
+ }
1937
1971
  const hasMultipleRepos = computed(() => {
1938
1972
  const repos = new Set(props.commits.map((c) => c.repo).filter(Boolean));
1939
1973
  return repos.size > 1;
@@ -1958,19 +1992,34 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1958
1992
  Array.from(commitsByRepo.entries()).map(async ([repoPath, shas]) => {
1959
1993
  const result = await fetchCommits(repoId, shas, repoPath || void 0);
1960
1994
  return {
1961
- commits: result.commits.map((c) => ({ ...c, repoPath })),
1995
+ repoPath,
1996
+ requestedShas: [...shas],
1997
+ commits: result.commits,
1962
1998
  failedShas: result.failedShas
1963
1999
  };
1964
2000
  })
1965
2001
  );
1966
2002
  const detailsMap = /* @__PURE__ */ new Map();
1967
2003
  const failed = /* @__PURE__ */ new Set();
1968
- for (const { commits: repoCommits, failedShas } of results) {
1969
- for (const commit of repoCommits) {
1970
- detailsMap.set(commit.shortSha, commit);
2004
+ for (const { repoPath, requestedShas, commits: repoCommits, failedShas } of results) {
2005
+ const remainingCommits = [...repoCommits];
2006
+ for (const requestedSha of requestedShas) {
2007
+ const key = createCommitKey(requestedSha, repoPath);
2008
+ const matchIndex = remainingCommits.findIndex((commit) => matchesRequestedSha(requestedSha, commit));
2009
+ if (matchIndex >= 0) {
2010
+ const [matchedCommit] = remainingCommits.splice(matchIndex, 1);
2011
+ if (matchedCommit) {
2012
+ detailsMap.set(key, {
2013
+ ...matchedCommit,
2014
+ repoPath
2015
+ });
2016
+ continue;
2017
+ }
2018
+ }
2019
+ failed.add(key);
1971
2020
  }
1972
2021
  for (const sha of failedShas) {
1973
- failed.add(sha);
2022
+ failed.add(createCommitKey(sha, repoPath));
1974
2023
  }
1975
2024
  }
1976
2025
  commitDetails.value = detailsMap;
@@ -1998,20 +2047,37 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1998
2047
  return date.toLocaleDateString();
1999
2048
  }
2000
2049
  }
2001
- function getDetails(sha) {
2002
- const direct = commitDetails.value.get(sha);
2003
- if (direct) return direct;
2050
+ function getDetails(commitRef) {
2051
+ const direct = commitDetails.value.get(createCommitKey(commitRef.sha, commitRef.repo));
2052
+ if (direct) {
2053
+ return direct;
2054
+ }
2055
+ const requestedSha = toShaLookupValue(commitRef.sha);
2056
+ const repoPrefix = `${toRepoLookupValue(commitRef.repo)}::`;
2004
2057
  for (const [key, commit] of commitDetails.value) {
2005
- if (key.startsWith(sha) || sha.startsWith(key)) {
2058
+ if (!key.startsWith(repoPrefix)) {
2059
+ continue;
2060
+ }
2061
+ const storedSha = key.slice(repoPrefix.length);
2062
+ if (storedSha.startsWith(requestedSha) || requestedSha.startsWith(storedSha)) {
2006
2063
  return commit;
2007
2064
  }
2008
2065
  }
2009
2066
  return void 0;
2010
2067
  }
2011
- function isFailed(sha) {
2012
- if (failedCommits.value.has(sha)) return true;
2013
- for (const failedSha of failedCommits.value) {
2014
- if (failedSha.startsWith(sha) || sha.startsWith(failedSha)) {
2068
+ function isFailed(commitRef) {
2069
+ const directKey = createCommitKey(commitRef.sha, commitRef.repo);
2070
+ if (failedCommits.value.has(directKey)) {
2071
+ return true;
2072
+ }
2073
+ const requestedSha = toShaLookupValue(commitRef.sha);
2074
+ const repoPrefix = `${toRepoLookupValue(commitRef.repo)}::`;
2075
+ for (const failedKey of failedCommits.value) {
2076
+ if (!failedKey.startsWith(repoPrefix)) {
2077
+ continue;
2078
+ }
2079
+ const failedSha = failedKey.slice(repoPrefix.length);
2080
+ if (failedSha.startsWith(requestedSha) || requestedSha.startsWith(failedSha)) {
2015
2081
  return true;
2016
2082
  }
2017
2083
  }
@@ -2032,15 +2098,15 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
2032
2098
  ssrRenderList(__props.commits, (commit) => {
2033
2099
  _push(`<button class="w-full rounded-lg border bg-card p-3 text-left transition-colors hover:bg-muted/50 focus:outline-none focus:ring-2 focus:ring-ring"><div class="flex items-start gap-3">`);
2034
2100
  _push(ssrRenderComponent(unref(GitCommit), { class: "mt-0.5 size-5 shrink-0 text-muted-foreground" }, null, _parent));
2035
- _push(`<div class="min-w-0 flex-1"><div class="flex flex-wrap items-center gap-2"><code class="font-mono text-xs font-medium text-primary">${ssrInterpolate(getDetails(commit.sha)?.shortSha || commit.sha.substring(0, 7))}</code>`);
2036
- if (getDetails(commit.sha)) {
2101
+ _push(`<div class="min-w-0 flex-1"><div class="flex flex-wrap items-center gap-2"><code class="font-mono text-xs font-medium text-primary">${ssrInterpolate(getDetails(commit)?.shortSha || commit.sha.substring(0, 7))}</code>`);
2102
+ if (getDetails(commit)) {
2037
2103
  _push(`<!--[--><span class="flex items-center gap-1 text-xs text-muted-foreground">`);
2038
2104
  _push(ssrRenderComponent(unref(FileText), { class: "size-3" }, null, _parent));
2039
- _push(` ${ssrInterpolate(getDetails(commit.sha).filesChanged)}</span><span class="flex items-center gap-0.5 text-xs text-green-600 dark:text-green-400">`);
2105
+ _push(` ${ssrInterpolate(getDetails(commit).filesChanged)}</span><span class="flex items-center gap-0.5 text-xs text-green-600 dark:text-green-400">`);
2040
2106
  _push(ssrRenderComponent(unref(Plus), { class: "size-3" }, null, _parent));
2041
- _push(`${ssrInterpolate(getDetails(commit.sha).additions)}</span><span class="flex items-center gap-0.5 text-xs text-red-600 dark:text-red-400">`);
2107
+ _push(`${ssrInterpolate(getDetails(commit).additions)}</span><span class="flex items-center gap-0.5 text-xs text-red-600 dark:text-red-400">`);
2042
2108
  _push(ssrRenderComponent(unref(Minus), { class: "size-3" }, null, _parent));
2043
- _push(`${ssrInterpolate(getDetails(commit.sha).deletions)}</span><!--]-->`);
2109
+ _push(`${ssrInterpolate(getDetails(commit).deletions)}</span><!--]-->`);
2044
2110
  } else {
2045
2111
  _push(`<!---->`);
2046
2112
  }
@@ -2066,9 +2132,9 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
2066
2132
  _push(`<!---->`);
2067
2133
  }
2068
2134
  _push(`</div><p class="mt-1 truncate text-sm">`);
2069
- if (getDetails(commit.sha)) {
2070
- _push(`<!--[-->${ssrInterpolate(getDetails(commit.sha).message)}<!--]-->`);
2071
- } else if (isFailed(commit.sha)) {
2135
+ if (getDetails(commit)) {
2136
+ _push(`<!--[-->${ssrInterpolate(getDetails(commit).message)}<!--]-->`);
2137
+ } else if (isFailed(commit)) {
2072
2138
  _push(`<span class="flex items-center gap-1 text-muted-foreground">`);
2073
2139
  _push(ssrRenderComponent(unref(AlertCircle), { class: "size-3" }, null, _parent));
2074
2140
  _push(` Commit unavailable </span>`);
@@ -2076,8 +2142,8 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
2076
2142
  _push(`<span class="text-muted-foreground">Loading...</span>`);
2077
2143
  }
2078
2144
  _push(`</p>`);
2079
- if (getDetails(commit.sha)) {
2080
- _push(`<p class="mt-1 text-xs text-muted-foreground">${ssrInterpolate(getDetails(commit.sha).author)} · ${ssrInterpolate(formatRelativeDate(getDetails(commit.sha).date))}</p>`);
2145
+ if (getDetails(commit)) {
2146
+ _push(`<p class="mt-1 text-xs text-muted-foreground">${ssrInterpolate(getDetails(commit).author)} · ${ssrInterpolate(formatRelativeDate(getDetails(commit).date))}</p>`);
2081
2147
  } else {
2082
2148
  _push(`<!---->`);
2083
2149
  }
@@ -3474,4 +3540,4 @@ _sfc_main.setup = (props, ctx) => {
3474
3540
  const __nuxt_component_1 = Object.assign(_sfc_main, { __name: "TasksDetail" });
3475
3541
 
3476
3542
  export { Badge as B, __nuxt_component_0$2 as _, __nuxt_component_1 as a };
3477
- //# sourceMappingURL=Detail-MGwP_u2d.mjs.map
3543
+ //# sourceMappingURL=Detail-BcQGdJY5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Detail-BcQGdJY5.mjs","sources":["../../../../node_modules/@dagrejs/dagre/dist/dagre.esm.js","../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/Detail-BcQGdJY5.js"],"names":[],"mappings":"","x_google_ignoreList":[0,1]}
@@ -1,16 +1,15 @@
1
1
  import { _ as __nuxt_component_0$2 } from './nuxt-link-SvT1nf8Z.mjs';
2
- import { defineComponent, computed, ref, watch, inject, mergeProps, unref, withCtx, createVNode, createTextVNode, isRef, openBlock, createBlock, toDisplayString, createCommentVNode, renderSlot, resolveDynamicComponent, useSSRContext } from 'vue';
2
+ import { defineComponent, computed, ref, watch, inject, mergeProps, unref, withCtx, createVNode, createTextVNode, openBlock, createBlock, toDisplayString, isRef, createCommentVNode, renderSlot, resolveDynamicComponent, useSSRContext } from 'vue';
3
3
  import { ssrRenderAttrs, ssrRenderComponent, ssrInterpolate, ssrRenderAttr, ssrRenderSlot, ssrRenderList, ssrRenderClass, ssrRenderVNode } from 'vue/server-renderer';
4
4
  import { Loader2, AlertCircle, RefreshCw, FileText, LayoutGrid, GitBranch, User, Calendar, CircleDot, ExternalLink, Circle, CheckCircle2, PlayCircle, Minus, ArrowDown, ArrowUp } from 'lucide-vue-next';
5
- import { _ as __nuxt_component_0$2$1, a as __nuxt_component_1$1, B as Badge } from './Detail-MGwP_u2d.mjs';
5
+ import { B as Badge, _ as __nuxt_component_0$2$1, a as __nuxt_component_1$1 } from './Detail-BcQGdJY5.mjs';
6
6
  import { marked } from 'marked';
7
7
  import { codeToHtml } from 'shiki';
8
8
  import DOMPurify from 'dompurify';
9
- import { u as useRepos, a as usePrd, b as useToast, c as cn } from './usePrd-f7ylhIqs.mjs';
9
+ import { u as useRepos, a as usePrd, B as Button, b as useToast, c as cn } from './usePrd-hXZOmvAv.mjs';
10
10
  import { _ as _export_sfc } from './_plugin-vue_export-helper-1tPrXgE0.mjs';
11
11
  import { reactiveOmit } from '@vueuse/core';
12
12
  import { useForwardPropsEmits, TabsRoot, TabsList as TabsList$1, useForwardProps, TabsTrigger as TabsTrigger$1, TabsContent as TabsContent$1 } from 'reka-ui';
13
- import { B as Button } from './index-ByZO4Bvq.mjs';
14
13
  import { b as useRoute, a as useRouter } from './server.mjs';
15
14
  import '../nitro/nitro.mjs';
16
15
  import 'node:http';
@@ -20,9 +19,9 @@ import 'node:buffer';
20
19
  import 'node:fs';
21
20
  import 'node:path';
22
21
  import 'node:crypto';
23
- import 'node:url';
24
22
  import 'node:os';
25
23
  import 'zod';
24
+ import 'node:url';
26
25
  import '@vue-flow/background';
27
26
  import '@vue-flow/controls';
28
27
  import '@vue-flow/core';
@@ -919,6 +918,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
919
918
  const router = useRouter();
920
919
  const { selectRepo } = useRepos();
921
920
  const {
921
+ prds,
922
+ showArchived,
923
+ setPrdArchived,
922
924
  fetchDocument,
923
925
  fetchTasks,
924
926
  fetchProgress,
@@ -942,6 +944,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
942
944
  const selectedTaskPrdSlug = ref(null);
943
945
  const detailOpen = ref(false);
944
946
  const selectedTaskCommits = ref([]);
947
+ const isUpdatingArchive = ref(false);
945
948
  const taskQueryId = computed(() => getSingleQueryParam(route.query[TASK_QUERY_KEY]));
946
949
  const taskQueryPrd = computed(() => getSingleQueryParam(route.query[TASK_PRD_QUERY_KEY]));
947
950
  const routeTaskSelection = computed(() => {
@@ -1225,6 +1228,34 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1225
1228
  }
1226
1229
  await openTaskDetail(task, payload.prdSlug);
1227
1230
  }
1231
+ async function handleArchiveToggle(archived) {
1232
+ if (!document.value || isUpdatingArchive.value) {
1233
+ return;
1234
+ }
1235
+ isUpdatingArchive.value = true;
1236
+ try {
1237
+ const archiveState = await setPrdArchived(prdSlug.value, archived);
1238
+ if (document.value) {
1239
+ document.value = {
1240
+ ...document.value,
1241
+ archived: archiveState.archived,
1242
+ archivedAt: archiveState.archivedAt
1243
+ };
1244
+ }
1245
+ if (archived && !showArchived.value) {
1246
+ const nextPrd = prds.value?.find((entry) => entry.slug !== prdSlug.value);
1247
+ if (nextPrd) {
1248
+ await router.push(`/${repoId.value}/${nextPrd.slug}`);
1249
+ } else {
1250
+ await router.push("/");
1251
+ }
1252
+ }
1253
+ } catch (err) {
1254
+ showError("Failed to update archive state", getErrorMessage(err, "Could not update this PRD archive state."));
1255
+ } finally {
1256
+ isUpdatingArchive.value = false;
1257
+ }
1258
+ }
1228
1259
  return (_ctx, _push, _parent, _attrs) => {
1229
1260
  const _component_NuxtLink = __nuxt_component_0$2;
1230
1261
  const _component_PrdMeta = __nuxt_component_1;
@@ -1295,11 +1326,53 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1295
1326
  }, _parent));
1296
1327
  _push(`</div></div></div>`);
1297
1328
  } else if (unref(document)) {
1298
- _push(`<div class="mx-auto max-w-6xl space-y-6"><div class="space-y-2"><h1 class="text-2xl font-bold tracking-tight">${ssrInterpolate(unref(document).name)}</h1>`);
1329
+ _push(`<div class="mx-auto max-w-6xl space-y-6"><div class="flex flex-wrap items-start justify-between gap-3"><div class="space-y-2"><div class="flex flex-wrap items-center gap-2"><h1 class="text-2xl font-bold tracking-tight">${ssrInterpolate(unref(document).name)}</h1>`);
1330
+ if (unref(document).archived) {
1331
+ _push(ssrRenderComponent(unref(Badge), {
1332
+ variant: "outline",
1333
+ class: "text-[10px] uppercase tracking-wide"
1334
+ }, {
1335
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
1336
+ if (_push2) {
1337
+ _push2(` Archived `);
1338
+ } else {
1339
+ return [
1340
+ createTextVNode(" Archived ")
1341
+ ];
1342
+ }
1343
+ }),
1344
+ _: 1
1345
+ }, _parent));
1346
+ } else {
1347
+ _push(`<!---->`);
1348
+ }
1349
+ _push(`</div>`);
1299
1350
  _push(ssrRenderComponent(_component_PrdMeta, {
1300
1351
  metadata: unref(document).metadata
1301
1352
  }, null, _parent));
1302
1353
  _push(`</div>`);
1354
+ _push(ssrRenderComponent(unref(Button), {
1355
+ variant: "outline",
1356
+ size: "sm",
1357
+ disabled: unref(isUpdatingArchive),
1358
+ onClick: ($event) => handleArchiveToggle(!unref(document).archived)
1359
+ }, {
1360
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
1361
+ if (_push2) {
1362
+ if (unref(isUpdatingArchive)) {
1363
+ _push2(`<span${_scopeId}>Saving...</span>`);
1364
+ } else {
1365
+ _push2(`<span${_scopeId}>${ssrInterpolate(unref(document).archived ? "Restore document" : "Archive document")}</span>`);
1366
+ }
1367
+ } else {
1368
+ return [
1369
+ unref(isUpdatingArchive) ? (openBlock(), createBlock("span", { key: 0 }, "Saving...")) : (openBlock(), createBlock("span", { key: 1 }, toDisplayString(unref(document).archived ? "Restore document" : "Archive document"), 1))
1370
+ ];
1371
+ }
1372
+ }),
1373
+ _: 1
1374
+ }, _parent));
1375
+ _push(`</div>`);
1303
1376
  _push(ssrRenderComponent(unref(Tabs), {
1304
1377
  modelValue: unref(activeTab),
1305
1378
  "onUpdate:modelValue": ($event) => isRef(activeTab) ? activeTab.value = $event : null,
@@ -1635,4 +1708,4 @@ _sfc_main.setup = (props, ctx) => {
1635
1708
  };
1636
1709
 
1637
1710
  export { _sfc_main as default };
1638
- //# sourceMappingURL=_prd_-C-Aj4fVa.mjs.map
1711
+ //# sourceMappingURL=_prd_-CD_Bds_B.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_prd_-CD_Bds_B.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/_prd_-CD_Bds_B.js"],"names":["__nuxt_component_0$3"],"mappings":"","x_google_ignoreList":[0]}