@shivaedev/work-board 0.17.0 → 0.17.1

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 (181) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +4 -4
  3. package/assets/react.css +1 -1
  4. package/assets/react.js +34 -33
  5. package/dist/browser/responses/cardContext.d.ts +8 -1
  6. package/dist/browser/responses/cardContext.d.ts.map +1 -1
  7. package/dist/browser/responses/cardContext.js +14 -6
  8. package/dist/browser/responses/cardContext.js.map +1 -1
  9. package/dist/browser/views/schema.d.ts +11 -0
  10. package/dist/browser/views/schema.d.ts.map +1 -1
  11. package/dist/browser/views/schema.js +1 -0
  12. package/dist/browser/views/schema.js.map +1 -1
  13. package/dist/client/formStatus.d.ts +1 -1
  14. package/dist/client/formStatus.d.ts.map +1 -1
  15. package/dist/client/formStatus.js +2 -2
  16. package/dist/client/formStatus.js.map +1 -1
  17. package/dist/client/react/AnswerContext.d.ts.map +1 -1
  18. package/dist/client/react/AnswerContext.js +5 -2
  19. package/dist/client/react/AnswerContext.js.map +1 -1
  20. package/dist/client/react/AnswerForm.d.ts.map +1 -1
  21. package/dist/client/react/AnswerForm.js +6 -2
  22. package/dist/client/react/AnswerForm.js.map +1 -1
  23. package/dist/client/react/AnswerMarkdown.d.ts +6 -0
  24. package/dist/client/react/AnswerMarkdown.d.ts.map +1 -0
  25. package/dist/client/react/AnswerMarkdown.js +7 -0
  26. package/dist/client/react/AnswerMarkdown.js.map +1 -0
  27. package/dist/client/react/AnswerMore.d.ts.map +1 -1
  28. package/dist/client/react/AnswerMore.js +2 -1
  29. package/dist/client/react/AnswerMore.js.map +1 -1
  30. package/dist/client/react/AnswerPanel.d.ts.map +1 -1
  31. package/dist/client/react/AnswerPanel.js +3 -2
  32. package/dist/client/react/AnswerPanel.js.map +1 -1
  33. package/dist/client/react/AnswerPrompts.d.ts.map +1 -1
  34. package/dist/client/react/AnswerPrompts.js +16 -10
  35. package/dist/client/react/AnswerPrompts.js.map +1 -1
  36. package/dist/client/react/BoardShell.js +1 -1
  37. package/dist/client/react/BoardShell.js.map +1 -1
  38. package/dist/client/react/DocumentMain.d.ts.map +1 -1
  39. package/dist/client/react/DocumentMain.js +1 -1
  40. package/dist/client/react/DocumentMain.js.map +1 -1
  41. package/dist/client/react/GoalPage.js +1 -1
  42. package/dist/client/react/GoalPage.js.map +1 -1
  43. package/dist/client/react/GoalProgressHeader.js +1 -1
  44. package/dist/client/react/GoalProgressHeader.js.map +1 -1
  45. package/dist/client/react/LibraryMain.d.ts.map +1 -1
  46. package/dist/client/react/LibraryMain.js +1 -1
  47. package/dist/client/react/LibraryMain.js.map +1 -1
  48. package/dist/client/react/LibraryPage.js +1 -1
  49. package/dist/client/react/LibraryPage.js.map +1 -1
  50. package/dist/client/react/ProjectionMain.d.ts.map +1 -1
  51. package/dist/client/react/ProjectionMain.js +1 -1
  52. package/dist/client/react/ProjectionMain.js.map +1 -1
  53. package/dist/client/react/PromptOption.d.ts.map +1 -1
  54. package/dist/client/react/PromptOption.js +7 -5
  55. package/dist/client/react/PromptOption.js.map +1 -1
  56. package/dist/client/react/RemainingMain.d.ts.map +1 -1
  57. package/dist/client/react/RemainingMain.js +1 -1
  58. package/dist/client/react/RemainingMain.js.map +1 -1
  59. package/dist/client/react/ResponseHistory.d.ts.map +1 -1
  60. package/dist/client/react/ResponseHistory.js +11 -5
  61. package/dist/client/react/ResponseHistory.js.map +1 -1
  62. package/dist/client/react/SystemMain.d.ts.map +1 -1
  63. package/dist/client/react/SystemMain.js +1 -1
  64. package/dist/client/react/SystemMain.js.map +1 -1
  65. package/dist/client/react/TodayNeeds.d.ts +5 -0
  66. package/dist/client/react/TodayNeeds.d.ts.map +1 -1
  67. package/dist/client/react/TodayNeeds.js +6 -3
  68. package/dist/client/react/TodayNeeds.js.map +1 -1
  69. package/dist/client/react/TodayOptionButton.d.ts +15 -0
  70. package/dist/client/react/TodayOptionButton.d.ts.map +1 -0
  71. package/dist/client/react/TodayOptionButton.js +10 -0
  72. package/dist/client/react/TodayOptionButton.js.map +1 -0
  73. package/dist/client/react/TodayOptions.d.ts.map +1 -1
  74. package/dist/client/react/TodayOptions.js +11 -9
  75. package/dist/client/react/TodayOptions.js.map +1 -1
  76. package/dist/client/react/TodayPage.d.ts.map +1 -1
  77. package/dist/client/react/TodayPage.js +7 -4
  78. package/dist/client/react/TodayPage.js.map +1 -1
  79. package/dist/client/react/activeRead.js +1 -1
  80. package/dist/client/react/activeRead.js.map +1 -1
  81. package/dist/client/react/loadBoardPage.d.ts.map +1 -1
  82. package/dist/client/react/loadBoardPage.js +1 -1
  83. package/dist/client/react/loadBoardPage.js.map +1 -1
  84. package/dist/client/react/loadProjection.d.ts.map +1 -1
  85. package/dist/client/react/loadProjection.js +1 -1
  86. package/dist/client/react/loadProjection.js.map +1 -1
  87. package/dist/client/react/loadRemaining.d.ts +201 -201
  88. package/dist/client/react/loadRemaining.d.ts.map +1 -1
  89. package/dist/client/react/loadRemaining.js +1 -1
  90. package/dist/client/react/loadRemaining.js.map +1 -1
  91. package/dist/client/react/pageQueries.js +1 -1
  92. package/dist/client/react/pageQueries.js.map +1 -1
  93. package/dist/client/react/resolvedDocumentFailure.d.ts.map +1 -0
  94. package/dist/client/react/resolvedDocumentFailure.js.map +1 -0
  95. package/dist/client/react/routeQuery.d.ts.map +1 -0
  96. package/dist/client/react/routeQuery.js.map +1 -0
  97. package/dist/client/react/useResponseForm.d.ts.map +1 -1
  98. package/dist/client/react/useResponseForm.js +2 -2
  99. package/dist/client/react/useResponseForm.js.map +1 -1
  100. package/dist/client/responses/summary.d.ts +1 -0
  101. package/dist/client/responses/summary.d.ts.map +1 -1
  102. package/dist/client/responses/summary.js +12 -1
  103. package/dist/client/responses/summary.js.map +1 -1
  104. package/dist/rpc/contract.d.ts +33 -0
  105. package/dist/rpc/contract.d.ts.map +1 -1
  106. package/dist/server/attention/inbox.d.ts +13 -2
  107. package/dist/server/attention/inbox.d.ts.map +1 -1
  108. package/dist/server/attention/inbox.js +44 -27
  109. package/dist/server/attention/inbox.js.map +1 -1
  110. package/dist/server/attention/managedRequestReceipt.d.ts +10 -0
  111. package/dist/server/attention/managedRequestReceipt.d.ts.map +1 -1
  112. package/dist/server/attention/managedRequestReceipt.js +29 -10
  113. package/dist/server/attention/managedRequestReceipt.js.map +1 -1
  114. package/dist/server/attention/projection.d.ts.map +1 -1
  115. package/dist/server/attention/projection.js +2 -1
  116. package/dist/server/attention/projection.js.map +1 -1
  117. package/dist/server/attention/requestInbox.d.ts +3 -3
  118. package/dist/server/attention/requestInbox.js +2 -2
  119. package/dist/server/attention/requestInbox.js.map +1 -1
  120. package/dist/server/attention/requests.d.ts +1 -0
  121. package/dist/server/attention/requests.d.ts.map +1 -1
  122. package/dist/server/attention/requests.js +7 -3
  123. package/dist/server/attention/requests.js.map +1 -1
  124. package/dist/server/mcp/client.d.ts +874 -863
  125. package/dist/server/mcp/client.d.ts.map +1 -1
  126. package/dist/server/mcp/queries.d.ts +33 -0
  127. package/dist/server/mcp/queries.d.ts.map +1 -1
  128. package/dist/server/packageInfo.d.ts +1 -1
  129. package/dist/server/packageInfo.js +1 -1
  130. package/dist/server/views/projectionQueries.d.ts +11 -0
  131. package/dist/server/views/projectionQueries.d.ts.map +1 -1
  132. package/docs/delivery/README.md +2 -2
  133. package/package.json +4 -4
  134. package/src/browser/responses/cardContext.ts +15 -6
  135. package/src/browser/views/schema.ts +1 -0
  136. package/src/client/formStatus.ts +2 -2
  137. package/src/client/react/AnswerContext.tsx +9 -4
  138. package/src/client/react/AnswerForm.tsx +25 -6
  139. package/src/client/react/AnswerMarkdown.tsx +15 -0
  140. package/src/client/react/AnswerMore.tsx +58 -46
  141. package/src/client/react/AnswerPanel.tsx +14 -8
  142. package/src/client/react/AnswerPrompts.tsx +33 -18
  143. package/src/client/react/BoardShell.tsx +1 -1
  144. package/src/client/react/DocumentMain.tsx +1 -1
  145. package/src/client/react/GoalPage.tsx +1 -1
  146. package/src/client/react/GoalProgressHeader.tsx +1 -1
  147. package/src/client/react/LibraryMain.tsx +1 -1
  148. package/src/client/react/LibraryPage.tsx +1 -1
  149. package/src/client/react/ProjectionMain.tsx +1 -1
  150. package/src/client/react/PromptOption.tsx +39 -24
  151. package/src/client/react/RemainingMain.tsx +1 -1
  152. package/src/client/react/ResponseHistory.tsx +53 -14
  153. package/src/client/react/SystemMain.tsx +1 -1
  154. package/src/client/react/TodayNeeds.tsx +21 -6
  155. package/src/client/react/TodayOptionButton.tsx +37 -0
  156. package/src/client/react/TodayOptions.tsx +36 -28
  157. package/src/client/react/TodayPage.tsx +18 -3
  158. package/src/client/react/activeRead.ts +1 -1
  159. package/src/client/react/entry.css +0 -6
  160. package/src/client/react/loadBoardPage.ts +1 -1
  161. package/src/client/react/loadProjection.ts +1 -1
  162. package/src/client/react/loadRemaining.ts +1 -1
  163. package/src/client/react/pageQueries.ts +1 -1
  164. package/src/client/react/useResponseForm.ts +4 -2
  165. package/src/client/responses/summary.ts +13 -1
  166. package/src/server/attention/inbox.ts +51 -27
  167. package/src/server/attention/managedRequestReceipt.ts +41 -10
  168. package/src/server/attention/projection.ts +5 -2
  169. package/src/server/attention/requestInbox.ts +2 -2
  170. package/src/server/attention/requests.ts +7 -2
  171. package/src/server/packageInfo.ts +1 -1
  172. package/dist/client/page/resolvedDocumentFailure.d.ts.map +0 -1
  173. package/dist/client/page/resolvedDocumentFailure.js.map +0 -1
  174. package/dist/client/page/routeQuery.d.ts.map +0 -1
  175. package/dist/client/page/routeQuery.js.map +0 -1
  176. /package/dist/client/{page → react}/resolvedDocumentFailure.d.ts +0 -0
  177. /package/dist/client/{page → react}/resolvedDocumentFailure.js +0 -0
  178. /package/dist/client/{page → react}/routeQuery.d.ts +0 -0
  179. /package/dist/client/{page → react}/routeQuery.js +0 -0
  180. /package/src/client/{page → react}/resolvedDocumentFailure.ts +0 -0
  181. /package/src/client/{page → react}/routeQuery.ts +0 -0
@@ -1,3 +1,4 @@
1
+ import { optionText, promptHeading } from "#browser/responses/cardContext.ts";
1
2
  import type { Prompt } from "#browser/responses/Prompt.ts";
2
3
  import type { PromptAnswer } from "#browser/responses/schema.ts";
3
4
  import type { ResponseInput } from "./formSchema.ts";
@@ -14,7 +15,9 @@ export function responseSummary(values: ResponseInput, prompts: readonly Prompt[
14
15
  : [];
15
16
  return [
16
17
  values.author.trim() ? "" : "Add your local author label.",
17
- missing.length > 0 ? `Unanswered prompts: ${missing.map((prompt) => `Question ${prompts.indexOf(prompt) + 1} · ${prompt.id}`).join("; ")}.` : "",
18
+ missing.length > 0
19
+ ? `Unanswered: ${missing.map((prompt) => `“${promptHeading(prompt.source).title ?? `Question ${prompts.indexOf(prompt) + 1}`}”`).join(", ")}.`
20
+ : "",
18
21
  ]
19
22
  .filter(Boolean)
20
23
  .join(" ");
@@ -23,3 +26,12 @@ export function responseSummary(values: ResponseInput, prompts: readonly Prompt[
23
26
  export function responseFeedback(status: string, outcome: string | undefined, summary: string) {
24
27
  return outcome || status.startsWith("Draft cleared") ? status : summary || status;
25
28
  }
29
+
30
+ export function chosenLabels(prompts: readonly Prompt[], answers: readonly PromptAnswer[] | undefined) {
31
+ return prompts
32
+ .flatMap((prompt) => {
33
+ const selected = answers?.find((answer) => answer.prompt === prompt.id)?.selected ?? [];
34
+ return prompt.options.filter((option) => selected.includes(option.id)).map((option) => optionText(option.id, option.source, "").label);
35
+ })
36
+ .join(", ");
37
+ }
@@ -6,7 +6,7 @@ import type { Snapshot } from "#server/search/snapshot.ts";
6
6
  import { answeredQuestion } from "./questionState.ts";
7
7
  import { requestInbox } from "./requestInbox.ts";
8
8
  import { isMaintainerRequest } from "./requests.ts";
9
- import { closedItem } from "./status.ts";
9
+ import { closedItem, deferredItem } from "./status.ts";
10
10
 
11
11
  const automation = /^(?:codex|claude|fleet|orchestrator|agent|automation|bot|copilot)(?:$|[-_. /])/iu;
12
12
 
@@ -24,6 +24,10 @@ function addressedElsewhere(document: MetadataDocument, maintainer: string): boo
24
24
  }
25
25
 
26
26
  export function waitingReason(document: MetadataDocument, model: MetadataModel, maintainer = "maintainer"): string | undefined {
27
+ return deferredItem(document) ? undefined : attentionReason(document, model, maintainer);
28
+ }
29
+
30
+ function attentionReason(document: MetadataDocument, model: MetadataModel, maintainer: string): string | undefined {
27
31
  const fields = document.parsed.fields;
28
32
  if (!openItem(document) || fields.kind === "response" || fields.kind === "handoff" || fields.question) {
29
33
  return undefined;
@@ -64,39 +68,59 @@ function inboxTarget(document: MetadataDocument, problem: string | undefined): s
64
68
  return answer ? responseUrl(item, answer) : identityUrl(item);
65
69
  }
66
70
 
67
- export function inboxItems(snapshot: Snapshot) {
68
- if (snapshot.unavailable.length > 0) {
69
- return [];
70
- }
71
+ function directItems(snapshot: Snapshot, skipped: ReadonlySet<string>, reasonOf: (document: MetadataDocument) => string | undefined) {
71
72
  const titles = new Map(snapshot.entries.filter((entry) => entry.kind === "document").map((entry) => [entry.file, entry.title]));
72
- const requests = requestInbox(snapshot);
73
- const you = requests.items.filter((item) => item.responseFrom.includes(snapshot.maintainer ?? "maintainer"));
74
- const direct = snapshot.documents.flatMap((document) => {
75
- if (requests.files.has(document.file)) {
73
+ return snapshot.documents.flatMap((document) => {
74
+ const reason = skipped.has(document.file) ? undefined : reasonOf(document);
75
+ if (!reason) {
76
76
  return [];
77
77
  }
78
78
  const id = document.parsed.fields.id;
79
79
  const problem = identityProblem(document, snapshot.model);
80
- const reason = waitingReason(document, snapshot.model, snapshot.maintainer);
81
- return reason
82
- ? [
83
- {
84
- document,
85
- href: inboxTarget(document, problem),
86
- id: id ?? document.file,
87
- problem,
88
- reason,
89
- request: undefined,
90
- title: titles.get(document.file) ?? document.file,
91
- unblocks: [id ?? ""],
92
- },
93
- ]
94
- : [];
80
+ return [
81
+ {
82
+ document,
83
+ href: inboxTarget(document, problem),
84
+ id: id ?? document.file,
85
+ modified: snapshot.modified.get(document.file),
86
+ problem,
87
+ reason,
88
+ request: undefined,
89
+ title: titles.get(document.file) ?? document.file,
90
+ unblocks: [id ?? ""],
91
+ },
92
+ ];
95
93
  });
96
- const ordinary = direct
94
+ }
95
+
96
+ function byAge(
97
+ left: { readonly id: string; readonly modified: number | undefined },
98
+ right: { readonly id: string; readonly modified: number | undefined },
99
+ ) {
100
+ return (left.modified ?? 0) - (right.modified ?? 0) || left.id.localeCompare(right.id);
101
+ }
102
+
103
+ export function inboxItems(snapshot: Snapshot) {
104
+ if (snapshot.unavailable.length > 0) {
105
+ return [];
106
+ }
107
+ const requests = requestInbox(snapshot);
108
+ const you = requests.items.filter((item) => item.responseFrom.includes(snapshot.maintainer ?? "maintainer"));
109
+ const ordinary = directItems(snapshot, requests.files, (document) => waitingReason(document, snapshot.model, snapshot.maintainer))
97
110
  .filter((item) => item.problem || !you.some((ask) => ask.id === item.id))
98
- .map((item) => ({ ...item, earlierAsks: 0, modified: snapshot.modified.get(item.document.file) }));
99
- return [...ordinary, ...you].sort((left, right) => (left.modified ?? 0) - (right.modified ?? 0) || left.id.localeCompare(right.id));
111
+ .map((item) => ({ ...item, earlierAsks: 0 }));
112
+ return [...ordinary, ...you].sort(byAge);
113
+ }
114
+
115
+ export function laterItems(snapshot: Snapshot) {
116
+ if (snapshot.unavailable.length > 0) {
117
+ return [];
118
+ }
119
+ function parked(document: MetadataDocument) {
120
+ const reason = deferredItem(document) ? attentionReason(document, snapshot.model, snapshot.maintainer ?? "maintainer") : undefined;
121
+ return reason && (document.parsed.fields.nextAction ?? reason);
122
+ }
123
+ return directItems(snapshot, requestInbox(snapshot).files, parked).sort(byAge);
100
124
  }
101
125
 
102
126
  export function fleetRecords(model: MetadataModel): ReadonlySet<string> {
@@ -6,6 +6,13 @@ import { questionId, revisionOf } from "#server/responses/records.ts";
6
6
 
7
7
  type Request = NonNullable<Metadata["attention"]>[number];
8
8
 
9
+ export type ManagedRequestState =
10
+ | { readonly _tag: "Open" }
11
+ | { readonly _tag: "Settled"; readonly receipt: RequestReceipt }
12
+ | { readonly _tag: "Conflicting"; readonly receipts: readonly string[] };
13
+
14
+ const open: ManagedRequestState = { _tag: "Open" };
15
+
9
16
  function uniqueDocument(id: string, model: MetadataModel): MetadataDocument | undefined {
10
17
  const matches = model.ids.get(id);
11
18
  return matches?.length === 1 ? matches[0] : undefined;
@@ -38,7 +45,7 @@ function appliedAnswer(question: string, revision: string, responseId: string |
38
45
  return current.length === 1 && current[0]?.id === responseId;
39
46
  }
40
47
 
41
- export function managedRequestReceipt(document: MetadataDocument, request: Request, model: MetadataModel): RequestReceipt | undefined {
48
+ function registeredQuestion(document: MetadataDocument, request: Request, model: MetadataModel) {
42
49
  const item = document.parsed.fields.id;
43
50
  if (
44
51
  request.managed !== true
@@ -57,7 +64,6 @@ export function managedRequestReceipt(document: MetadataDocument, request: Reque
57
64
  const revision = revisionOf(source);
58
65
  const id = questionId(item, request.id, revision, document.file);
59
66
  const archived = uniqueDocument(id, model);
60
- const index = responseIndex(model);
61
67
  const question = registeredContext(archived, model);
62
68
  if (
63
69
  archived?.parsed.diagnostics.length !== 0
@@ -70,14 +76,13 @@ export function managedRequestReceipt(document: MetadataDocument, request: Reque
70
76
  ) {
71
77
  return undefined;
72
78
  }
73
- if (index.receiptProblems) {
74
- return undefined;
75
- }
76
- const receipts = index.receipts.get(id) ?? [];
77
- const saved = receipts.length === 1 ? receipts[0] : undefined;
78
- const receipt = saved?.parsed.fields.requestReceipt;
79
+ return { id, revision };
80
+ }
81
+
82
+ function qualified(saved: MetadataDocument, question: string, revision: string, model: MetadataModel): RequestReceipt | undefined {
83
+ const receipt = saved.parsed.fields.requestReceipt;
79
84
  if (
80
- !(saved && receipt)
85
+ !receipt
81
86
  || saved.parsed.fields.kind !== "result"
82
87
  || saved.parsed.diagnostics.length > 0
83
88
  || !saved.parsed.fields.id
@@ -89,5 +94,31 @@ export function managedRequestReceipt(document: MetadataDocument, request: Reque
89
94
  if (receipt.disposition === "superseded") {
90
95
  return receipt.response === undefined ? receipt : undefined;
91
96
  }
92
- return appliedAnswer(id, revision, receipt.response, model) ? receipt : undefined;
97
+ return appliedAnswer(question, revision, receipt.response, model) ? receipt : undefined;
98
+ }
99
+
100
+ function settling(receipts: readonly RequestReceipt[]): RequestReceipt | undefined {
101
+ return receipts.toSorted(
102
+ (left, right) => Number(right.disposition === "applied") - Number(left.disposition === "applied") || right.recordedAt - left.recordedAt,
103
+ )[0];
104
+ }
105
+
106
+ export function managedRequestState(document: MetadataDocument, request: Request, model: MetadataModel): ManagedRequestState {
107
+ const question = registeredQuestion(document, request, model);
108
+ const index = responseIndex(model);
109
+ if (!question || index.receiptProblems) {
110
+ return open;
111
+ }
112
+ const saved = index.receipts.get(question.id) ?? [];
113
+ const receipts = saved.flatMap((candidate) => qualified(candidate, question.id, question.revision, model) ?? []);
114
+ const receipt = receipts.length === saved.length ? settling(receipts) : undefined;
115
+ if (receipt) {
116
+ return { _tag: "Settled", receipt };
117
+ }
118
+ return receipts.length > 0 ? { _tag: "Conflicting", receipts: saved.map((candidate) => candidate.file) } : open;
119
+ }
120
+
121
+ export function managedRequestReceipt(document: MetadataDocument, request: Request, model: MetadataModel): RequestReceipt | undefined {
122
+ const state = managedRequestState(document, request, model);
123
+ return state._tag === "Settled" ? state.receipt : undefined;
93
124
  }
@@ -1,6 +1,6 @@
1
1
  import type { InboxProjection } from "#browser/views/schema.ts";
2
2
  import type { Snapshot } from "#server/search/snapshot.ts";
3
- import { inboxItems } from "./inbox.ts";
3
+ import { inboxItems, laterItems } from "./inbox.ts";
4
4
  import { requestInbox } from "./requestInbox.ts";
5
5
  import { attentionRequests } from "./requests.ts";
6
6
 
@@ -12,7 +12,9 @@ export function attentionProjection(snapshot: Snapshot): InboxProjection {
12
12
  return cached;
13
13
  }
14
14
  const requests = requestInbox(snapshot);
15
- function project({ document, request: _request, unblocks: _unblocks, ...item }: ReturnType<typeof inboxItems>[number]) {
15
+ function project<
16
+ TRow extends { readonly document: { readonly file: string }; readonly request: string | undefined; readonly unblocks: readonly string[] },
17
+ >({ document, request: _request, unblocks: _unblocks, ...item }: TRow) {
16
18
  return { ...item, file: document.file };
17
19
  }
18
20
  const you = inboxItems(snapshot).map(project);
@@ -22,6 +24,7 @@ export function attentionProjection(snapshot: Snapshot): InboxProjection {
22
24
  complete: snapshot.unavailable.length === 0,
23
25
  issues,
24
26
  items: you,
27
+ later: laterItems(snapshot).map(project),
25
28
  parked: requests.parked.map(project),
26
29
  resolved: requests.resolved.map(project),
27
30
  sourceIssues: issues.length > 0,
@@ -23,10 +23,10 @@ export function requestInbox(snapshot: Snapshot) {
23
23
  return {
24
24
  document: entry.document,
25
25
  earlierAsks: 0,
26
- href: responseUrl(entry.itemId, entry.request.id),
26
+ href: entry.problem === undefined ? responseUrl(entry.itemId, entry.request.id) : entry.href,
27
27
  id: target?.parsed.fields.id ?? entry.itemId,
28
28
  modified: snapshot.modified.get(entry.document.file),
29
- problem: undefined,
29
+ problem: entry.problem,
30
30
  reason: entry.request.managed ? `Managed decision: ${entry.request.reason}` : entry.request.reason,
31
31
  request: entry.request.id,
32
32
  responseFrom: entry.request.responseFrom,
@@ -1,5 +1,5 @@
1
1
  import type { Metadata } from "#metadata/schema.ts";
2
- import { managedRequestReceipt } from "#server/attention/managedRequestReceipt.ts";
2
+ import { managedRequestState } from "#server/attention/managedRequestReceipt.ts";
3
3
  import { identityUrl, referenceTarget } from "#server/metadata/links.ts";
4
4
  import type { MetadataDocument } from "#server/metadata/model.ts";
5
5
  import type { Snapshot } from "#server/search/snapshot.ts";
@@ -10,6 +10,7 @@ export interface AttentionEntry {
10
10
  readonly href: string;
11
11
  readonly itemId: string;
12
12
  readonly line: number;
13
+ readonly problem: string | undefined;
13
14
  readonly request: Request;
14
15
  readonly title: string;
15
16
  }
@@ -35,16 +36,20 @@ function requestsFor(document: MetadataDocument, snapshot: Snapshot, title: stri
35
36
  request.state !== "open"
36
37
  || requests.filter((other) => other.id === request.id).length !== 1
37
38
  || request.unblocks.some((target) => !referenceTarget(target, snapshot.model))
38
- || managedRequestReceipt(document, request, snapshot.model) !== undefined
39
39
  ) {
40
40
  return [];
41
41
  }
42
+ const receipts = managedRequestState(document, request, snapshot.model);
43
+ if (receipts._tag === "Settled") {
44
+ return [];
45
+ }
42
46
  return [
43
47
  {
44
48
  document,
45
49
  href: `${identityUrl(itemId)}#attention-request-${encodeURIComponent(request.id)}`,
46
50
  itemId,
47
51
  line: lines[`attention.${index}`] ?? lines.attention ?? 2,
52
+ problem: receipts._tag === "Conflicting" ? `Request receipts disagree: ${receipts.receipts.join(", ")}` : undefined,
48
53
  request,
49
54
  title,
50
55
  },
@@ -1,2 +1,2 @@
1
1
  export const NAME = "work-board";
2
- export const VERSION = "0.17.0";
2
+ export const VERSION = "0.17.1";
@@ -1 +0,0 @@
1
- {"version":3,"file":"resolvedDocumentFailure.d.ts","sourceRoot":"","sources":["../../../src/client/page/resolvedDocumentFailure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,QAAQ,CAAC;AAElD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,OAAO,CAG5E"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"resolvedDocumentFailure.js","sourceRoot":"","sources":["../../../src/client/page/resolvedDocumentFailure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAElD,MAAM,UAAU,uBAAuB,CAAC,KAA2B;IAClE,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,OAAO,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;AACvF,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routeQuery.d.ts","sourceRoot":"","sources":["../../../src/client/page/routeQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,UAAU,OAAO;IAChB,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;CACnE;AAED,eAAO,MAAM,iBAAiB;IAAK,UAAU;CAAU,CAAC;AAExD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6TAEtD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAA;CAAE;;;;;;;;;;;;+HAE9G"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routeQuery.js","sourceRoot":"","sources":["../../../src/client/page/routeQuery.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAExD,MAAM,UAAU,aAAa,CAAC,GAAY,EAAE,GAAW;IACtD,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAA+E;IAC9G,OAAO,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,iBAAiB,CAAC,CAAC;AACjE,CAAC"}
File without changes
File without changes
File without changes