@mrtdown/core 2.0.0-alpha.3 → 2.0.0-alpha.5

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 (140) hide show
  1. package/dist/cli/commands/create.d.ts +30 -0
  2. package/dist/cli/commands/create.js +189 -0
  3. package/dist/cli/commands/create.js.map +1 -0
  4. package/dist/cli/commands/list.d.ts +6 -0
  5. package/dist/cli/commands/list.js +106 -0
  6. package/dist/cli/commands/list.js.map +1 -0
  7. package/dist/cli/commands/show.d.ts +6 -0
  8. package/dist/cli/commands/show.js +156 -0
  9. package/dist/cli/commands/show.js.map +1 -0
  10. package/dist/cli/commands/validate.d.ts +6 -0
  11. package/dist/cli/commands/validate.js +19 -0
  12. package/dist/cli/commands/validate.js.map +1 -0
  13. package/dist/cli/index.d.ts +2 -0
  14. package/dist/cli/index.js +162 -0
  15. package/dist/cli/index.js.map +1 -0
  16. package/dist/helpers/keyForAffectedEntity.d.ts +1 -1
  17. package/dist/helpers/keyForAffectedEntity.js.map +1 -1
  18. package/dist/helpers/normalizeRecurringPeriod.d.ts +1 -1
  19. package/dist/helpers/normalizeRecurringPeriod.js +1 -1
  20. package/dist/helpers/normalizeRecurringPeriod.js.map +1 -1
  21. package/dist/helpers/normalizeRecurringPeriod.test.js.map +1 -1
  22. package/dist/helpers/resolvePeriods.d.ts +1 -1
  23. package/dist/helpers/resolvePeriods.js +1 -1
  24. package/dist/helpers/resolvePeriods.js.map +1 -1
  25. package/dist/helpers/resolvePeriods.test.js.map +1 -1
  26. package/dist/index.d.ts +25 -25
  27. package/dist/index.js +25 -25
  28. package/dist/index.js.map +1 -1
  29. package/dist/llm/client.d.ts +2 -0
  30. package/dist/llm/client.js +5 -0
  31. package/dist/llm/client.js.map +1 -0
  32. package/dist/llm/common/MemoryStore.d.ts +21 -0
  33. package/dist/llm/common/MemoryStore.js +100 -0
  34. package/dist/llm/common/MemoryStore.js.map +1 -0
  35. package/dist/llm/common/MemoryStore.test.d.ts +1 -0
  36. package/dist/llm/common/MemoryStore.test.js +225 -0
  37. package/dist/llm/common/MemoryStore.test.js.map +1 -0
  38. package/dist/llm/common/formatCurrentState.d.ts +10 -0
  39. package/dist/llm/common/formatCurrentState.js +342 -0
  40. package/dist/llm/common/formatCurrentState.js.map +1 -0
  41. package/dist/llm/common/tool.d.ts +32 -0
  42. package/dist/llm/common/tool.js +6 -0
  43. package/dist/llm/common/tool.js.map +1 -0
  44. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.d.ts +1 -0
  45. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.js +433 -0
  46. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.js.map +1 -0
  47. package/dist/llm/functions/extractClaimsFromNewEvidence/index.d.ts +18 -0
  48. package/dist/llm/functions/extractClaimsFromNewEvidence/index.js +153 -0
  49. package/dist/llm/functions/extractClaimsFromNewEvidence/index.js.map +1 -0
  50. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.d.ts +1 -0
  51. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.js +168 -0
  52. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.js.map +1 -0
  53. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.d.ts +19 -0
  54. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.js +65 -0
  55. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.js.map +1 -0
  56. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.d.ts +21 -0
  57. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.js +115 -0
  58. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.js.map +1 -0
  59. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.d.ts +24 -0
  60. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.js +110 -0
  61. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.js.map +1 -0
  62. package/dist/llm/functions/generateIssueTitleAndSlug/index.d.ts +14 -0
  63. package/dist/llm/functions/generateIssueTitleAndSlug/index.js +38 -0
  64. package/dist/llm/functions/generateIssueTitleAndSlug/index.js.map +1 -0
  65. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.d.ts +1 -0
  66. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.js +23 -0
  67. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.js.map +1 -0
  68. package/dist/llm/functions/translate/index.d.ts +1 -0
  69. package/dist/llm/functions/translate/index.js +59 -0
  70. package/dist/llm/functions/translate/index.js.map +1 -0
  71. package/dist/llm/functions/triageNewEvidence/eval.test.d.ts +1 -0
  72. package/dist/llm/functions/triageNewEvidence/eval.test.js +139 -0
  73. package/dist/llm/functions/triageNewEvidence/eval.test.js.map +1 -0
  74. package/dist/llm/functions/triageNewEvidence/index.d.ts +37 -0
  75. package/dist/llm/functions/triageNewEvidence/index.js +121 -0
  76. package/dist/llm/functions/triageNewEvidence/index.js.map +1 -0
  77. package/dist/llm/functions/triageNewEvidence/prompt.d.ts +1 -0
  78. package/dist/llm/functions/triageNewEvidence/prompt.js +60 -0
  79. package/dist/llm/functions/triageNewEvidence/prompt.js.map +1 -0
  80. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.d.ts +19 -0
  81. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.js +65 -0
  82. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.js.map +1 -0
  83. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.d.ts +19 -0
  84. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.js +37 -0
  85. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.js.map +1 -0
  86. package/dist/repo/issue/IssueRepository.d.ts +1 -1
  87. package/dist/repo/issue/IssueRepository.js +3 -3
  88. package/dist/repo/issue/IssueRepository.js.map +1 -1
  89. package/dist/repo/issue/helpers/deriveCurrentState.d.ts +6 -6
  90. package/dist/repo/issue/helpers/deriveCurrentState.js +1 -1
  91. package/dist/repo/issue/helpers/deriveCurrentState.js.map +1 -1
  92. package/dist/repo/issue/helpers/deriveCurrentState.test.js.map +1 -1
  93. package/dist/schema/issue/evidence.js +1 -1
  94. package/dist/schema/issue/evidence.js.map +1 -1
  95. package/dist/schema/issue/issue.js +1 -1
  96. package/dist/schema/issue/issue.js.map +1 -1
  97. package/dist/scripts/ingestViaWebhook.d.ts +1 -0
  98. package/dist/scripts/ingestViaWebhook.js +9 -0
  99. package/dist/scripts/ingestViaWebhook.js.map +1 -0
  100. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.d.ts +1 -1
  101. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.js +1 -1
  102. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.js.map +1 -1
  103. package/dist/util/ingestContent/index.js +9 -9
  104. package/dist/util/ingestContent/index.js.map +1 -1
  105. package/dist/validators/buildContext.d.ts +7 -0
  106. package/dist/validators/buildContext.js +164 -0
  107. package/dist/validators/buildContext.js.map +1 -0
  108. package/dist/validators/index.d.ts +17 -0
  109. package/dist/validators/index.js +58 -0
  110. package/dist/validators/index.js.map +1 -0
  111. package/dist/validators/issue.d.ts +13 -0
  112. package/dist/validators/issue.js +220 -0
  113. package/dist/validators/issue.js.map +1 -0
  114. package/dist/validators/landmark.d.ts +7 -0
  115. package/dist/validators/landmark.js +43 -0
  116. package/dist/validators/landmark.js.map +1 -0
  117. package/dist/validators/line.d.ts +8 -0
  118. package/dist/validators/line.js +87 -0
  119. package/dist/validators/line.js.map +1 -0
  120. package/dist/validators/operator.d.ts +7 -0
  121. package/dist/validators/operator.js +43 -0
  122. package/dist/validators/operator.js.map +1 -0
  123. package/dist/validators/service.d.ts +8 -0
  124. package/dist/validators/service.js +87 -0
  125. package/dist/validators/service.js.map +1 -0
  126. package/dist/validators/station.d.ts +8 -0
  127. package/dist/validators/station.js +93 -0
  128. package/dist/validators/station.js.map +1 -0
  129. package/dist/validators/town.d.ts +7 -0
  130. package/dist/validators/town.js +43 -0
  131. package/dist/validators/town.js.map +1 -0
  132. package/dist/validators/types.d.ts +19 -0
  133. package/dist/validators/types.js +2 -0
  134. package/dist/validators/types.js.map +1 -0
  135. package/dist/validators/utils.d.ts +2 -0
  136. package/dist/validators/utils.js +9 -0
  137. package/dist/validators/utils.js.map +1 -0
  138. package/dist/write/issue/IssueWriter.d.ts +3 -3
  139. package/dist/write/issue/IssueWriter.js.map +1 -1
  140. package/package.json +2 -7
@@ -0,0 +1,65 @@
1
+ import { gfmToMarkdown } from 'mdast-util-gfm';
2
+ import { toMarkdown } from 'mdast-util-to-markdown';
3
+ import z from 'zod';
4
+ import { Tool } from '../../../common/tool.js';
5
+ const FindIssuesToolParametersSchema = z.object({
6
+ query: z.string().describe('Plain text to search for issues.'),
7
+ });
8
+ export class FindIssuesTool extends Tool {
9
+ name = 'findIssues';
10
+ description = 'Find issues by query';
11
+ repo;
12
+ constructor(repo) {
13
+ super();
14
+ this.repo = repo;
15
+ }
16
+ get paramsSchema() {
17
+ return z.toJSONSchema(FindIssuesToolParametersSchema);
18
+ }
19
+ parseParams(params) {
20
+ return FindIssuesToolParametersSchema.parse(params);
21
+ }
22
+ async runner(params) {
23
+ console.log('[findIssues] Calling tool with parameters:', params);
24
+ const issues = this.repo.issues.searchByQuery(params.query);
25
+ const issueTable = {
26
+ type: 'table',
27
+ children: [
28
+ {
29
+ type: 'tableRow',
30
+ children: [
31
+ {
32
+ type: 'tableCell',
33
+ children: [{ type: 'text', value: 'Issue ID' }],
34
+ },
35
+ {
36
+ type: 'tableCell',
37
+ children: [{ type: 'text', value: 'Issue Title' }],
38
+ },
39
+ ],
40
+ },
41
+ ],
42
+ };
43
+ for (const issue of issues) {
44
+ issueTable.children.push({
45
+ type: 'tableRow',
46
+ children: [
47
+ {
48
+ type: 'tableCell',
49
+ children: [{ type: 'text', value: issue.issue.id }],
50
+ },
51
+ {
52
+ type: 'tableCell',
53
+ children: [{ type: 'text', value: issue.issue.title['en-SG'] }],
54
+ },
55
+ ],
56
+ });
57
+ }
58
+ const output = toMarkdown(issueTable, {
59
+ extensions: [gfmToMarkdown()],
60
+ });
61
+ console.log(`[findIssues] Response output:\n${output}`);
62
+ return output;
63
+ }
64
+ }
65
+ //# sourceMappingURL=FindIssuesTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FindIssuesTool.js","sourceRoot":"/","sources":["llm/functions/triageNewEvidence/tools/FindIssuesTool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAG/C,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;CAC/D,CAAC,CAAC;AAGH,MAAM,OAAO,cAAe,SAAQ,IAA8B;IACzD,IAAI,GAAG,YAAY,CAAC;IACpB,WAAW,GAAG,sBAAsB,CAAC;IAC3B,IAAI,CAAoB;IAEzC,YAAY,IAAuB;QACjC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAW,YAAY;QACrB,OAAO,CAAC,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC;IACxD,CAAC;IAEM,WAAW,CAAC,MAAe;QAChC,OAAO,8BAA8B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtD,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,MAAgC;QAClD,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,MAAM,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE5D,MAAM,UAAU,GAAU;YACxB,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,UAAU;oBAChB,QAAQ,EAAE;wBACR;4BACE,IAAI,EAAE,WAAW;4BACjB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;yBAChD;wBACD;4BACE,IAAI,EAAE,WAAW;4BACjB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;yBACnD;qBACF;iBACF;aACF;SACF,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACvB,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,WAAW;wBACjB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;qBACpD;oBACD;wBACE,IAAI,EAAE,WAAW;wBACjB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;qBAChE;iBACF;aACF,CAAC,CAAC;QACL,CAAC;QAED,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,EAAE;YACpC,UAAU,EAAE,CAAC,aAAa,EAAE,CAAC;SAC9B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,kCAAkC,MAAM,EAAE,CAAC,CAAC;QAExD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF","sourcesContent":["import type { Table } from 'mdast';\nimport { gfmToMarkdown } from 'mdast-util-gfm';\nimport { toMarkdown } from 'mdast-util-to-markdown';\nimport z from 'zod';\nimport { Tool } from '../../../common/tool.js';\nimport type { MRTDownRepository } from '../../../../repo/MRTDownRepository.js';\n\nconst FindIssuesToolParametersSchema = z.object({\n query: z.string().describe('Plain text to search for issues.'),\n});\ntype FindIssuesToolParameters = z.infer<typeof FindIssuesToolParametersSchema>;\n\nexport class FindIssuesTool extends Tool<FindIssuesToolParameters> {\n public name = 'findIssues';\n public description = 'Find issues by query';\n private readonly repo: MRTDownRepository;\n\n constructor(repo: MRTDownRepository) {\n super();\n this.repo = repo;\n }\n\n public get paramsSchema(): { [key: string]: unknown } {\n return z.toJSONSchema(FindIssuesToolParametersSchema);\n }\n\n public parseParams(params: unknown): FindIssuesToolParameters {\n return FindIssuesToolParametersSchema.parse(params);\n }\n\n public async runner(params: FindIssuesToolParameters): Promise<string> {\n console.log('[findIssues] Calling tool with parameters:', params);\n\n const issues = this.repo.issues.searchByQuery(params.query);\n\n const issueTable: Table = {\n type: 'table',\n children: [\n {\n type: 'tableRow',\n children: [\n {\n type: 'tableCell',\n children: [{ type: 'text', value: 'Issue ID' }],\n },\n {\n type: 'tableCell',\n children: [{ type: 'text', value: 'Issue Title' }],\n },\n ],\n },\n ],\n };\n\n for (const issue of issues) {\n issueTable.children.push({\n type: 'tableRow',\n children: [\n {\n type: 'tableCell',\n children: [{ type: 'text', value: issue.issue.id }],\n },\n {\n type: 'tableCell',\n children: [{ type: 'text', value: issue.issue.title['en-SG'] }],\n },\n ],\n });\n }\n\n const output = toMarkdown(issueTable, {\n extensions: [gfmToMarkdown()],\n });\n console.log(`[findIssues] Response output:\\n${output}`);\n\n return output;\n }\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import z from 'zod';
2
+ import type { MRTDownRepository } from '../../../../repo/MRTDownRepository.js';
3
+ import { Tool } from '../../../common/tool.js';
4
+ declare const GetIssueToolParametersSchema: z.ZodObject<{
5
+ issueId: z.ZodString;
6
+ }, z.z.core.$strip>;
7
+ type GetIssueToolParameters = z.infer<typeof GetIssueToolParametersSchema>;
8
+ export declare class GetIssueTool extends Tool<GetIssueToolParameters> {
9
+ name: string;
10
+ description: string;
11
+ private readonly repo;
12
+ constructor(repo: MRTDownRepository);
13
+ get paramsSchema(): {
14
+ [key: string]: unknown;
15
+ };
16
+ parseParams(params: unknown): GetIssueToolParameters;
17
+ runner(params: GetIssueToolParameters): Promise<string>;
18
+ }
19
+ export {};
@@ -0,0 +1,37 @@
1
+ import z from 'zod';
2
+ import { deriveCurrentState } from '../../../../repo/issue/helpers/deriveCurrentState.js';
3
+ import { formatCurrentState } from '../../../common/formatCurrentState.js';
4
+ import { Tool } from '../../../common/tool.js';
5
+ const GetIssueToolParametersSchema = z.object({
6
+ issueId: z.string(),
7
+ });
8
+ export class GetIssueTool extends Tool {
9
+ name = 'getIssue';
10
+ description = 'Get an issue by ID';
11
+ repo;
12
+ constructor(repo) {
13
+ super();
14
+ this.repo = repo;
15
+ }
16
+ get paramsSchema() {
17
+ return z.toJSONSchema(GetIssueToolParametersSchema);
18
+ }
19
+ parseParams(params) {
20
+ return GetIssueToolParametersSchema.parse(params);
21
+ }
22
+ async runner(params) {
23
+ console.log('[getIssue] Calling tool with parameters:', params);
24
+ const issueBundle = this.repo.issues.get(params.issueId);
25
+ if (issueBundle == null) {
26
+ return `Issue ${params.issueId} not found`;
27
+ }
28
+ const currentState = deriveCurrentState(issueBundle);
29
+ const output = formatCurrentState({
30
+ state: currentState,
31
+ evidence: issueBundle.evidence,
32
+ });
33
+ console.log(`[getIssue] Response output:\n${output}`);
34
+ return output;
35
+ }
36
+ }
37
+ //# sourceMappingURL=GetIssueTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GetIssueTool.js","sourceRoot":"/","sources":["llm/functions/triageNewEvidence/tools/GetIssueTool.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sDAAsD,CAAC;AAE1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAE/C,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAGH,MAAM,OAAO,YAAa,SAAQ,IAA4B;IACrD,IAAI,GAAG,UAAU,CAAC;IAClB,WAAW,GAAG,oBAAoB,CAAC;IACzB,IAAI,CAAoB;IAEzC,YAAY,IAAuB;QACjC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAW,YAAY;QACrB,OAAO,CAAC,CAAC,YAAY,CAAC,4BAA4B,CAAC,CAAC;IACtD,CAAC;IAEM,WAAW,CAAC,MAAe;QAChC,OAAO,4BAA4B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,MAA8B;QAChD,OAAO,CAAC,GAAG,CAAC,0CAA0C,EAAE,MAAM,CAAC,CAAC;QAEhE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;YACxB,OAAO,SAAS,MAAM,CAAC,OAAO,YAAY,CAAC;QAC7C,CAAC;QAED,MAAM,YAAY,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAErD,MAAM,MAAM,GAAG,kBAAkB,CAAC;YAChC,KAAK,EAAE,YAAY;YACnB,QAAQ,EAAE,WAAW,CAAC,QAAQ;SAC/B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,gCAAgC,MAAM,EAAE,CAAC,CAAC;QAEtD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF","sourcesContent":["import z from 'zod';\nimport { deriveCurrentState } from '../../../../repo/issue/helpers/deriveCurrentState.js';\nimport type { MRTDownRepository } from '../../../../repo/MRTDownRepository.js';\nimport { formatCurrentState } from '../../../common/formatCurrentState.js';\nimport { Tool } from '../../../common/tool.js';\n\nconst GetIssueToolParametersSchema = z.object({\n issueId: z.string(),\n});\ntype GetIssueToolParameters = z.infer<typeof GetIssueToolParametersSchema>;\n\nexport class GetIssueTool extends Tool<GetIssueToolParameters> {\n public name = 'getIssue';\n public description = 'Get an issue by ID';\n private readonly repo: MRTDownRepository;\n\n constructor(repo: MRTDownRepository) {\n super();\n this.repo = repo;\n }\n\n public get paramsSchema(): { [key: string]: unknown } {\n return z.toJSONSchema(GetIssueToolParametersSchema);\n }\n\n public parseParams(params: unknown): GetIssueToolParameters {\n return GetIssueToolParametersSchema.parse(params);\n }\n\n public async runner(params: GetIssueToolParameters): Promise<string> {\n console.log('[getIssue] Calling tool with parameters:', params);\n\n const issueBundle = this.repo.issues.get(params.issueId);\n if (issueBundle == null) {\n return `Issue ${params.issueId} not found`;\n }\n\n const currentState = deriveCurrentState(issueBundle);\n\n const output = formatCurrentState({\n state: currentState,\n evidence: issueBundle.evidence,\n });\n console.log(`[getIssue] Response output:\\n${output}`);\n\n return output;\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { IssueBundle } from '#schema/issue/bundle.js';
1
+ import type { IssueBundle } from '../../schema/issue/bundle.js';
2
2
  import type { IStore } from '../common/store.js';
3
3
  export declare class IssueRepository {
4
4
  private readonly store;
@@ -2,9 +2,9 @@ import { join } from 'node:path';
2
2
  import Fuse from 'fuse.js';
3
3
  import { NdJson } from 'json-nd';
4
4
  import z from 'zod';
5
- import { EvidenceSchema } from '#schema/issue/evidence.js';
6
- import { ImpactEventSchema } from '#schema/issue/impactEvent.js';
7
- import { IssueSchema } from '#schema/issue/issue.js';
5
+ import { EvidenceSchema } from '../../schema/issue/evidence.js';
6
+ import { ImpactEventSchema } from '../../schema/issue/impactEvent.js';
7
+ import { IssueSchema } from '../../schema/issue/issue.js';
8
8
  import { DIR_ISSUE } from '../../constants.js';
9
9
  export class IssueRepository {
10
10
  store;
@@ -1 +1 @@
1
- {"version":3,"file":"IssueRepository.js","sourceRoot":"/","sources":["repo/issue/IssueRepository.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from 'node:path';\nimport Fuse, { type Expression } from 'fuse.js';\nimport { NdJson } from 'json-nd';\nimport z from 'zod';\nimport type { IssueBundle } from '#schema/issue/bundle.js';\nimport { EvidenceSchema } from '#schema/issue/evidence.js';\nimport { ImpactEventSchema } from '#schema/issue/impactEvent.js';\nimport { IssueSchema } from '#schema/issue/issue.js';\nimport { DIR_ISSUE } from '../../constants.js';\nimport type { IStore } from '../common/store.js';\n\ntype IssueIndexEntry = {\n issueId: string;\n path: string; // e.g. data/issues/2026/01/01/<issueId>\n year: number;\n month: number;\n};\n\nexport class IssueRepository {\n private readonly store: IStore;\n\n constructor(store: IStore) {\n this.store = store;\n }\n\n // Index for fast lookup by issue ID.\n private byId = new Map<string, IssueIndexEntry>();\n private indexed = false;\n\n // Cache for issue bundles.\n private bundleCache = new Map<string, IssueBundle>();\n\n /**\n * Build the index of all issues.\n */\n private buildIndex() {\n if (this.indexed) {\n return;\n }\n\n const years = this.store.listDir(DIR_ISSUE);\n for (const year of years) {\n if (!/^\\d{4}$/.test(year)) {\n continue;\n }\n const months = this.store.listDir(join(DIR_ISSUE, year));\n for (const month of months) {\n if (!/^\\d{2}$/.test(month)) {\n continue;\n }\n const issues = this.store.listDir(join(DIR_ISSUE, year, month));\n for (const issueId of issues) {\n this.byId.set(issueId, {\n issueId: issueId,\n path: join(DIR_ISSUE, year, month, issueId),\n year: Number(year),\n month: Number(month),\n });\n }\n }\n }\n this.indexed = true;\n }\n\n /**\n * Return the relative folder path to the issue.\n * @param id\n * @returns\n */\n getPath(id: string): string | null {\n this.buildIndex();\n return this.byId.get(id)?.path ?? null;\n }\n\n get(id: string): IssueBundle | null {\n this.buildIndex();\n\n const isCached = this.bundleCache.has(id);\n if (isCached) {\n return this.bundleCache.get(id) ?? null;\n }\n\n const entry = this.byId.get(id);\n if (!entry) {\n return null;\n }\n\n const issue = IssueSchema.parse(\n this.store.readJson(join(entry.path, 'issue.json')),\n );\n\n const evidencePath = join(entry.path, 'evidence.ndjson');\n const evidenceRaw = this.store.exists(evidencePath)\n ? this.store.readText(evidencePath).trim()\n : '';\n const evidence = z\n .array(EvidenceSchema)\n .parse(evidenceRaw ? NdJson.parse(evidenceRaw) : []);\n\n const impactPath = join(entry.path, 'impact.ndjson');\n const impactRaw = this.store.exists(impactPath)\n ? this.store.readText(impactPath).trim()\n : '';\n const impact = z\n .array(ImpactEventSchema)\n .parse(impactRaw ? NdJson.parse(impactRaw) : []);\n\n const bundle: IssueBundle = {\n issue,\n evidence,\n impactEvents: impact,\n path: entry.path,\n };\n this.bundleCache.set(id, bundle);\n return bundle;\n }\n\n /**\n * List all issue IDs, sorted by year and month.\n * @returns\n */\n listIds(): string[] {\n this.buildIndex();\n const entries = Array.from(this.byId.values());\n entries.sort((a, b) => {\n if (a.year !== b.year) {\n return a.year - b.year;\n }\n if (a.month !== b.month) {\n return a.month - b.month;\n }\n return a.issueId.localeCompare(b.issueId);\n });\n return entries.map((entry) => entry.issueId);\n }\n\n /**\n * List all bundles, sorted by year and month.\n * @returns\n */\n list(): IssueBundle[] {\n this.buildIndex();\n const entries = Array.from(this.byId.values());\n entries.sort((a, b) => {\n if (a.year !== b.year) {\n return a.year - b.year;\n }\n if (a.month !== b.month) {\n return a.month - b.month;\n }\n return a.issueId.localeCompare(b.issueId);\n });\n const result: IssueBundle[] = [];\n for (const entry of entries) {\n const bundle = this.get(entry.issueId);\n if (bundle == null) {\n continue;\n }\n result.push(bundle);\n }\n return result;\n }\n\n /**\n * Search issues by query.\n * @param query\n * @returns\n */\n searchByQuery(query: string): IssueBundle[] {\n const fuse = new Fuse(this.list(), {\n keys: [\n 'issue.id',\n 'issue.title.en-SG',\n 'evidence.text',\n 'impact.scopeItems.serviceId',\n 'impact.scopeItems.stationId',\n 'impact.scopeItems.fromStationId',\n 'impact.scopeItems.toStationId',\n ],\n includeScore: true,\n threshold: 0.8,\n });\n const searchResults = fuse.search({\n $or: [\n { 'issue.id': query },\n { 'issue.title.en-SG': query },\n { 'evidence.text': query },\n { 'impact.scopeItems.serviceId': query },\n { 'impact.scopeItems.stationId': query },\n { 'impact.scopeItems.fromStationId': query },\n { 'impact.scopeItems.toStationId': query },\n ] as Expression[],\n });\n const results: IssueBundle[] = [];\n for (const result of searchResults) {\n const bundle = this.get(result.item.issue.id);\n if (bundle == null) {\n continue;\n }\n results.push(bundle);\n }\n return results;\n }\n}\n"]}
1
+ {"version":3,"file":"IssueRepository.js","sourceRoot":"/","sources":["repo/issue/IssueRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAyB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,CAAC,MAAM,KAAK,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAU/C,MAAM,OAAO,eAAe;IACT,KAAK,CAAS;IAE/B,YAAY,KAAa;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,qCAAqC;IAC7B,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC1C,OAAO,GAAG,KAAK,CAAC;IAExB,2BAA2B;IACnB,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;IAErD;;OAEG;IACK,UAAU;QAChB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;YACzD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC3B,SAAS;gBACX,CAAC;gBACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;gBAChE,KAAK,MAAM,OAAO,IAAI,MAAM,EAAE,CAAC;oBAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;wBACrB,OAAO,EAAE,OAAO;wBAChB,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC;wBAC3C,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;wBAClB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;qBACrB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,EAAU;QAChB,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC;IACzC,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,IAAI,CAAC,UAAU,EAAE,CAAC;QAElB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;QAC1C,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAC7B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CACpD,CAAC;QAEF,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QACzD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;YACjD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE;YAC1C,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,QAAQ,GAAG,CAAC;aACf,KAAK,CAAC,cAAc,CAAC;aACrB,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAEvD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC;YAC7C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE;YACxC,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,MAAM,GAAG,CAAC;aACb,KAAK,CAAC,iBAAiB,CAAC;aACxB,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAEnD,MAAM,MAAM,GAAgB;YAC1B,KAAK;YACL,QAAQ;YACR,YAAY,EAAE,MAAM;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,OAAO;QACL,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACpB,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBACtB,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;YACzB,CAAC;YACD,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;gBACxB,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;YAC3B,CAAC;YACD,OAAO,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,IAAI;QACF,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACpB,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBACtB,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;YACzB,CAAC;YACD,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;gBACxB,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;YAC3B,CAAC;YACD,OAAO,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAkB,EAAE,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,SAAS;YACX,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,aAAa,CAAC,KAAa;QACzB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE;YACjC,IAAI,EAAE;gBACJ,UAAU;gBACV,mBAAmB;gBACnB,eAAe;gBACf,6BAA6B;gBAC7B,6BAA6B;gBAC7B,iCAAiC;gBACjC,+BAA+B;aAChC;YACD,YAAY,EAAE,IAAI;YAClB,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;YAChC,GAAG,EAAE;gBACH,EAAE,UAAU,EAAE,KAAK,EAAE;gBACrB,EAAE,mBAAmB,EAAE,KAAK,EAAE;gBAC9B,EAAE,eAAe,EAAE,KAAK,EAAE;gBAC1B,EAAE,6BAA6B,EAAE,KAAK,EAAE;gBACxC,EAAE,6BAA6B,EAAE,KAAK,EAAE;gBACxC,EAAE,iCAAiC,EAAE,KAAK,EAAE;gBAC5C,EAAE,+BAA+B,EAAE,KAAK,EAAE;aAC3B;SAClB,CAAC,CAAC;QACH,MAAM,OAAO,GAAkB,EAAE,CAAC;QAClC,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC9C,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,SAAS;YACX,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF","sourcesContent":["import { join } from 'node:path';\nimport Fuse, { type Expression } from 'fuse.js';\nimport { NdJson } from 'json-nd';\nimport z from 'zod';\nimport type { IssueBundle } from '../../schema/issue/bundle.js';\nimport { EvidenceSchema } from '../../schema/issue/evidence.js';\nimport { ImpactEventSchema } from '../../schema/issue/impactEvent.js';\nimport { IssueSchema } from '../../schema/issue/issue.js';\nimport { DIR_ISSUE } from '../../constants.js';\nimport type { IStore } from '../common/store.js';\n\ntype IssueIndexEntry = {\n issueId: string;\n path: string; // e.g. data/issues/2026/01/01/<issueId>\n year: number;\n month: number;\n};\n\nexport class IssueRepository {\n private readonly store: IStore;\n\n constructor(store: IStore) {\n this.store = store;\n }\n\n // Index for fast lookup by issue ID.\n private byId = new Map<string, IssueIndexEntry>();\n private indexed = false;\n\n // Cache for issue bundles.\n private bundleCache = new Map<string, IssueBundle>();\n\n /**\n * Build the index of all issues.\n */\n private buildIndex() {\n if (this.indexed) {\n return;\n }\n\n const years = this.store.listDir(DIR_ISSUE);\n for (const year of years) {\n if (!/^\\d{4}$/.test(year)) {\n continue;\n }\n const months = this.store.listDir(join(DIR_ISSUE, year));\n for (const month of months) {\n if (!/^\\d{2}$/.test(month)) {\n continue;\n }\n const issues = this.store.listDir(join(DIR_ISSUE, year, month));\n for (const issueId of issues) {\n this.byId.set(issueId, {\n issueId: issueId,\n path: join(DIR_ISSUE, year, month, issueId),\n year: Number(year),\n month: Number(month),\n });\n }\n }\n }\n this.indexed = true;\n }\n\n /**\n * Return the relative folder path to the issue.\n * @param id\n * @returns\n */\n getPath(id: string): string | null {\n this.buildIndex();\n return this.byId.get(id)?.path ?? null;\n }\n\n get(id: string): IssueBundle | null {\n this.buildIndex();\n\n const isCached = this.bundleCache.has(id);\n if (isCached) {\n return this.bundleCache.get(id) ?? null;\n }\n\n const entry = this.byId.get(id);\n if (!entry) {\n return null;\n }\n\n const issue = IssueSchema.parse(\n this.store.readJson(join(entry.path, 'issue.json')),\n );\n\n const evidencePath = join(entry.path, 'evidence.ndjson');\n const evidenceRaw = this.store.exists(evidencePath)\n ? this.store.readText(evidencePath).trim()\n : '';\n const evidence = z\n .array(EvidenceSchema)\n .parse(evidenceRaw ? NdJson.parse(evidenceRaw) : []);\n\n const impactPath = join(entry.path, 'impact.ndjson');\n const impactRaw = this.store.exists(impactPath)\n ? this.store.readText(impactPath).trim()\n : '';\n const impact = z\n .array(ImpactEventSchema)\n .parse(impactRaw ? NdJson.parse(impactRaw) : []);\n\n const bundle: IssueBundle = {\n issue,\n evidence,\n impactEvents: impact,\n path: entry.path,\n };\n this.bundleCache.set(id, bundle);\n return bundle;\n }\n\n /**\n * List all issue IDs, sorted by year and month.\n * @returns\n */\n listIds(): string[] {\n this.buildIndex();\n const entries = Array.from(this.byId.values());\n entries.sort((a, b) => {\n if (a.year !== b.year) {\n return a.year - b.year;\n }\n if (a.month !== b.month) {\n return a.month - b.month;\n }\n return a.issueId.localeCompare(b.issueId);\n });\n return entries.map((entry) => entry.issueId);\n }\n\n /**\n * List all bundles, sorted by year and month.\n * @returns\n */\n list(): IssueBundle[] {\n this.buildIndex();\n const entries = Array.from(this.byId.values());\n entries.sort((a, b) => {\n if (a.year !== b.year) {\n return a.year - b.year;\n }\n if (a.month !== b.month) {\n return a.month - b.month;\n }\n return a.issueId.localeCompare(b.issueId);\n });\n const result: IssueBundle[] = [];\n for (const entry of entries) {\n const bundle = this.get(entry.issueId);\n if (bundle == null) {\n continue;\n }\n result.push(bundle);\n }\n return result;\n }\n\n /**\n * Search issues by query.\n * @param query\n * @returns\n */\n searchByQuery(query: string): IssueBundle[] {\n const fuse = new Fuse(this.list(), {\n keys: [\n 'issue.id',\n 'issue.title.en-SG',\n 'evidence.text',\n 'impact.scopeItems.serviceId',\n 'impact.scopeItems.stationId',\n 'impact.scopeItems.fromStationId',\n 'impact.scopeItems.toStationId',\n ],\n includeScore: true,\n threshold: 0.8,\n });\n const searchResults = fuse.search({\n $or: [\n { 'issue.id': query },\n { 'issue.title.en-SG': query },\n { 'evidence.text': query },\n { 'impact.scopeItems.serviceId': query },\n { 'impact.scopeItems.stationId': query },\n { 'impact.scopeItems.fromStationId': query },\n { 'impact.scopeItems.toStationId': query },\n ] as Expression[],\n });\n const results: IssueBundle[] = [];\n for (const result of searchResults) {\n const bundle = this.get(result.item.issue.id);\n if (bundle == null) {\n continue;\n }\n results.push(bundle);\n }\n return results;\n }\n}\n"]}
@@ -1,9 +1,9 @@
1
- import type { IssueBundle } from '#schema/issue/bundle.js';
2
- import type { CauseSubtype } from '#schema/issue/cause.js';
3
- import type { FacilityEffect } from '#schema/issue/facilityEffect.js';
4
- import type { Period } from '#schema/issue/period.js';
5
- import type { ServiceEffect } from '#schema/issue/serviceEffect.js';
6
- import type { ServiceScope } from '#schema/issue/serviceScope.js';
1
+ import type { IssueBundle } from '../../../schema/issue/bundle.js';
2
+ import type { CauseSubtype } from '../../../schema/issue/cause.js';
3
+ import type { FacilityEffect } from '../../../schema/issue/facilityEffect.js';
4
+ import type { Period } from '../../../schema/issue/period.js';
5
+ import type { ServiceEffect } from '../../../schema/issue/serviceEffect.js';
6
+ import type { ServiceScope } from '../../../schema/issue/serviceScope.js';
7
7
  type BasisRef = {
8
8
  evidenceId: string;
9
9
  };
@@ -1,4 +1,4 @@
1
- import { keyForAffectedEntity } from '#helpers/keyForAffectedEntity.js';
1
+ import { keyForAffectedEntity } from '../../../helpers/keyForAffectedEntity.js';
2
2
  /**
3
3
  * Derive the current state of an issue.
4
4
  * @param bundle
@@ -1 +1 @@
1
- {"version":3,"file":"deriveCurrentState.js","sourceRoot":"/","sources":["repo/issue/helpers/deriveCurrentState.ts"],"names":[],"mappings":"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","sourcesContent":["import { keyForAffectedEntity } from '#helpers/keyForAffectedEntity.js';\nimport type { IssueBundle } from '#schema/issue/bundle.js';\nimport type { CauseSubtype } from '#schema/issue/cause.js';\nimport type { FacilityEffect } from '#schema/issue/facilityEffect.js';\nimport type { Period } from '#schema/issue/period.js';\nimport type { ServiceEffect } from '#schema/issue/serviceEffect.js';\nimport type { ServiceScope } from '#schema/issue/serviceScope.js';\n\ntype BasisRef = {\n evidenceId: string;\n};\n\ntype ServiceProvenance = {\n effect?: BasisRef;\n scopes?: BasisRef;\n periods?: BasisRef;\n causes?: BasisRef;\n};\n\ntype ServiceState = {\n serviceId: string;\n effect: ServiceEffect | null;\n scopes: ServiceScope[];\n periods: Period[];\n causes: CauseSubtype[];\n};\n\ntype FacilityProvenance = {\n effect?: BasisRef;\n periods?: BasisRef;\n causes?: BasisRef;\n};\n\ntype FacilityState = {\n stationId: string;\n kind: 'lift' | 'escalator' | 'screen-door';\n effect: FacilityEffect | null;\n periods: Period[];\n causes: CauseSubtype[];\n};\n\nexport type IssueBundleState = {\n services: Record<string, ServiceState>;\n servicesProvenance: Record<string, ServiceProvenance>;\n facilities: Record<string, FacilityState>;\n facilitiesProvenance: Record<string, FacilityProvenance>;\n /**\n * The impact event ids that were used to derive the current state.\n */\n impactEventIds: string[];\n};\n\n/**\n * Derive the current state of an issue.\n * @param bundle\n * @returns\n */\nexport function deriveCurrentState(bundle: IssueBundle): IssueBundleState {\n const services: Record<string, ServiceState> = {};\n const servicesProvenance: Record<string, ServiceProvenance> = {};\n const facilities: Record<string, FacilityState> = {};\n const facilitiesProvenance: Record<string, FacilityProvenance> = {};\n const impactEventIds: {\n serviceEffect: string | null;\n serviceScopes: string | null;\n periods: string | null;\n causes: string | null;\n facilityEffect: string | null;\n } = {\n serviceEffect: null,\n serviceScopes: null,\n periods: null,\n causes: null,\n facilityEffect: null,\n };\n\n for (const impactEvent of bundle.impactEvents) {\n const key = keyForAffectedEntity(impactEvent.entity);\n\n switch (impactEvent.entity.type) {\n case 'service': {\n const currentState = services[key] ?? {\n serviceId: impactEvent.entity.serviceId,\n effect: null,\n scopes: [],\n periods: [],\n causes: [],\n };\n\n const currentProvenance = servicesProvenance[key] ?? {};\n\n switch (impactEvent.type) {\n case 'service_effects.set': {\n currentState.effect = impactEvent.effect;\n currentProvenance.effect = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.serviceEffect = impactEvent.id;\n break;\n }\n case 'periods.set': {\n currentState.periods = impactEvent.periods;\n currentProvenance.periods = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.periods = impactEvent.id;\n break;\n }\n case 'service_scopes.set': {\n currentState.scopes = impactEvent.serviceScopes;\n currentProvenance.scopes = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.serviceScopes = impactEvent.id;\n break;\n }\n case 'causes.set': {\n currentState.causes = impactEvent.causes;\n currentProvenance.causes = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.causes = impactEvent.id;\n break;\n }\n }\n\n services[key] = currentState;\n servicesProvenance[key] = currentProvenance;\n\n break;\n }\n case 'facility': {\n const currentState = facilities[key] ?? {\n stationId: impactEvent.entity.stationId,\n kind: impactEvent.entity.kind,\n effect: null,\n periods: [],\n };\n\n const currentProvenance = facilitiesProvenance[key] ?? {};\n\n switch (impactEvent.type) {\n case 'facility_effects.set': {\n currentState.effect = impactEvent.effect;\n currentProvenance.effect = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.facilityEffect = impactEvent.id;\n break;\n }\n case 'periods.set': {\n currentState.periods = impactEvent.periods;\n currentProvenance.periods = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.periods = impactEvent.id;\n break;\n }\n }\n\n facilities[key] = currentState;\n facilitiesProvenance[key] = currentProvenance;\n\n break;\n }\n default: {\n // @ts-expect-error fallback case\n throw new Error(`Unknown entity type: ${impactEvent.entity.type}`);\n }\n }\n }\n\n return {\n services,\n servicesProvenance,\n facilities,\n facilitiesProvenance,\n impactEventIds: Object.values(impactEventIds).filter(\n (id): id is string => id !== null,\n ),\n };\n}\n"]}
1
+ {"version":3,"file":"deriveCurrentState.js","sourceRoot":"/","sources":["repo/issue/helpers/deriveCurrentState.ts"],"names":[],"mappings":"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","sourcesContent":["import { keyForAffectedEntity } from '../../../helpers/keyForAffectedEntity.js';\nimport type { IssueBundle } from '../../../schema/issue/bundle.js';\nimport type { CauseSubtype } from '../../../schema/issue/cause.js';\nimport type { FacilityEffect } from '../../../schema/issue/facilityEffect.js';\nimport type { Period } from '../../../schema/issue/period.js';\nimport type { ServiceEffect } from '../../../schema/issue/serviceEffect.js';\nimport type { ServiceScope } from '../../../schema/issue/serviceScope.js';\n\ntype BasisRef = {\n evidenceId: string;\n};\n\ntype ServiceProvenance = {\n effect?: BasisRef;\n scopes?: BasisRef;\n periods?: BasisRef;\n causes?: BasisRef;\n};\n\ntype ServiceState = {\n serviceId: string;\n effect: ServiceEffect | null;\n scopes: ServiceScope[];\n periods: Period[];\n causes: CauseSubtype[];\n};\n\ntype FacilityProvenance = {\n effect?: BasisRef;\n periods?: BasisRef;\n causes?: BasisRef;\n};\n\ntype FacilityState = {\n stationId: string;\n kind: 'lift' | 'escalator' | 'screen-door';\n effect: FacilityEffect | null;\n periods: Period[];\n causes: CauseSubtype[];\n};\n\nexport type IssueBundleState = {\n services: Record<string, ServiceState>;\n servicesProvenance: Record<string, ServiceProvenance>;\n facilities: Record<string, FacilityState>;\n facilitiesProvenance: Record<string, FacilityProvenance>;\n /**\n * The impact event ids that were used to derive the current state.\n */\n impactEventIds: string[];\n};\n\n/**\n * Derive the current state of an issue.\n * @param bundle\n * @returns\n */\nexport function deriveCurrentState(bundle: IssueBundle): IssueBundleState {\n const services: Record<string, ServiceState> = {};\n const servicesProvenance: Record<string, ServiceProvenance> = {};\n const facilities: Record<string, FacilityState> = {};\n const facilitiesProvenance: Record<string, FacilityProvenance> = {};\n const impactEventIds: {\n serviceEffect: string | null;\n serviceScopes: string | null;\n periods: string | null;\n causes: string | null;\n facilityEffect: string | null;\n } = {\n serviceEffect: null,\n serviceScopes: null,\n periods: null,\n causes: null,\n facilityEffect: null,\n };\n\n for (const impactEvent of bundle.impactEvents) {\n const key = keyForAffectedEntity(impactEvent.entity);\n\n switch (impactEvent.entity.type) {\n case 'service': {\n const currentState = services[key] ?? {\n serviceId: impactEvent.entity.serviceId,\n effect: null,\n scopes: [],\n periods: [],\n causes: [],\n };\n\n const currentProvenance = servicesProvenance[key] ?? {};\n\n switch (impactEvent.type) {\n case 'service_effects.set': {\n currentState.effect = impactEvent.effect;\n currentProvenance.effect = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.serviceEffect = impactEvent.id;\n break;\n }\n case 'periods.set': {\n currentState.periods = impactEvent.periods;\n currentProvenance.periods = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.periods = impactEvent.id;\n break;\n }\n case 'service_scopes.set': {\n currentState.scopes = impactEvent.serviceScopes;\n currentProvenance.scopes = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.serviceScopes = impactEvent.id;\n break;\n }\n case 'causes.set': {\n currentState.causes = impactEvent.causes;\n currentProvenance.causes = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.causes = impactEvent.id;\n break;\n }\n }\n\n services[key] = currentState;\n servicesProvenance[key] = currentProvenance;\n\n break;\n }\n case 'facility': {\n const currentState = facilities[key] ?? {\n stationId: impactEvent.entity.stationId,\n kind: impactEvent.entity.kind,\n effect: null,\n periods: [],\n };\n\n const currentProvenance = facilitiesProvenance[key] ?? {};\n\n switch (impactEvent.type) {\n case 'facility_effects.set': {\n currentState.effect = impactEvent.effect;\n currentProvenance.effect = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.facilityEffect = impactEvent.id;\n break;\n }\n case 'periods.set': {\n currentState.periods = impactEvent.periods;\n currentProvenance.periods = {\n evidenceId: impactEvent.basis.evidenceId,\n };\n impactEventIds.periods = impactEvent.id;\n break;\n }\n }\n\n facilities[key] = currentState;\n facilitiesProvenance[key] = currentProvenance;\n\n break;\n }\n default: {\n // @ts-expect-error fallback case\n throw new Error(`Unknown entity type: ${impactEvent.entity.type}`);\n }\n }\n }\n\n return {\n services,\n servicesProvenance,\n facilities,\n facilitiesProvenance,\n impactEventIds: Object.values(impactEventIds).filter(\n (id): id is string => id !== null,\n ),\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"deriveCurrentState.test.js","sourceRoot":"/","sources":["repo/issue/helpers/deriveCurrentState.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, test } from 'vitest';\nimport type { IssueBundle } from '#schema/issue/bundle.js';\nimport type { Period } from '#schema/issue/period.js';\nimport type { ServiceEffect } from '#schema/issue/serviceEffect.js';\nimport type { ServiceScope } from '#schema/issue/serviceScope.js';\nimport { keyForAffectedEntity } from '../../../helpers/keyForAffectedEntity.js';\nimport { deriveCurrentState } from './deriveCurrentState.js';\n\nconst defaultTarget = { type: 'service' as const, serviceId: 'NSL' };\nconst nslKey = keyForAffectedEntity(defaultTarget);\n\ndescribe('deriveCurrentState', () => {\n const createMockIssue = () => ({\n id: '2025-01-01-test-issue',\n type: 'disruption' as const,\n title: {\n 'en-SG': 'Test Issue',\n 'zh-Hans': null,\n ms: null,\n ta: null,\n },\n titleMeta: {\n source: 'test',\n },\n });\n\n const createMockBundle = (\n impact: IssueBundle['impactEvents'],\n ): IssueBundle => ({\n issue: createMockIssue(),\n evidence: [],\n impactEvents: impact,\n path: 'test/path',\n });\n\n test('returns empty state for bundle with no impacts', () => {\n const bundle = createMockBundle([]);\n const result = deriveCurrentState(bundle);\n\n expect(result).toEqual({\n services: {},\n servicesProvenance: {},\n facilities: {},\n facilitiesProvenance: {},\n impactEventIds: [],\n });\n });\n\n test('handles service_effects.set impact', () => {\n const effect: ServiceEffect = { kind: 'delay', duration: null };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect,\n scopes: [],\n periods: [],\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n effect: { evidenceId: 'evidence-1' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles periods_set impact', () => {\n const periods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n {\n kind: 'fixed',\n startAt: '2025-01-01T14:00:00+08:00',\n endAt: null,\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n periods,\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: [],\n periods,\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n periods: { evidenceId: 'evidence-3' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles causes.set impact', () => {\n const causes = ['signal.fault', 'track.fault'] as const;\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_cause_001',\n type: 'causes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n causes: [...causes],\n basis: { evidenceId: 'evidence-cause' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: [],\n periods: [],\n causes,\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n causes: { evidenceId: 'evidence-cause' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_cause_001']);\n });\n\n test('handles service_scopes_set impact', () => {\n const serviceScopes: ServiceScope[] = [\n {\n type: 'service.whole',\n },\n {\n type: 'service.segment',\n fromStationId: 'station-1',\n toStationId: 'station-2',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n serviceScopes,\n basis: {\n evidenceId: 'evidence-5',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: serviceScopes,\n periods: [],\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n scopes: { evidenceId: 'evidence-5' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles multiple impacts - later impacts overwrite earlier ones', () => {\n const firstEffect: ServiceEffect = { kind: 'delay', duration: null };\n const secondEffect: ServiceEffect = { kind: 'no-service' };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: firstEffect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n effect: secondEffect,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(secondEffect);\n expect(result.servicesProvenance[nslKey].effect?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('handles mixed impact types', () => {\n const effect: ServiceEffect = { kind: 'delay', duration: null };\n const periods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ];\n const serviceScopes: ServiceScope[] = [\n {\n type: 'service.point',\n stationId: 'station-1',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n {\n id: 'ie_test_003',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T12:00:00Z',\n serviceScopes,\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(effect);\n expect(result.services[nslKey].periods).toEqual(periods);\n expect(result.services[nslKey].scopes).toEqual(serviceScopes);\n expect(result.servicesProvenance[nslKey].effect?.evidenceId).toBe(\n 'evidence-1',\n );\n expect(result.servicesProvenance[nslKey].periods?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.servicesProvenance[nslKey].scopes?.evidenceId).toBe(\n 'evidence-3',\n );\n expect(result.impactEventIds).toEqual([\n 'ie_test_001',\n 'ie_test_003',\n 'ie_test_002',\n ]);\n });\n\n test('handles all service effect kinds', () => {\n const effectKinds: ServiceEffect['kind'][] = [\n 'delay',\n 'no-service',\n 'reduced-service',\n 'service-hours-adjustment',\n ];\n\n for (const kind of effectKinds) {\n const effect: ServiceEffect =\n kind === 'delay' ? { kind: 'delay', duration: null } : { kind };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(effect);\n }\n });\n\n test('handles all scope types', () => {\n const allScopes: ServiceScope[] = [\n {\n type: 'service.whole',\n },\n {\n type: 'service.segment',\n fromStationId: 'station-1',\n toStationId: 'station-2',\n },\n {\n type: 'service.point',\n stationId: 'station-3',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n serviceScopes: allScopes,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].scopes).toEqual(allScopes);\n expect(result.services[nslKey].scopes).toHaveLength(3);\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles empty arrays in impacts', () => {\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'no-service' },\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods: [],\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n {\n id: 'ie_test_003',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T12:00:00Z',\n serviceScopes: [],\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual({ kind: 'no-service' });\n expect(result.services[nslKey].periods).toEqual([]);\n expect(result.services[nslKey].scopes).toEqual([]);\n expect(result.impactEventIds).toEqual([\n 'ie_test_001',\n 'ie_test_003',\n 'ie_test_002',\n ]);\n });\n\n test('preserves order of impacts when processing', () => {\n const firstPeriods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ];\n const secondPeriods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T14:00:00+08:00',\n endAt: null,\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n periods: firstPeriods,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods: secondPeriods,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].periods).toEqual(secondPeriods);\n expect(result.servicesProvenance[nslKey].periods?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('groups impacts by target - different targets produce separate entries', () => {\n const nslTarget = { type: 'service' as const, serviceId: 'NSL' };\n const ewlTarget = { type: 'service' as const, serviceId: 'EWL' };\n const nslKeyLocal = keyForAffectedEntity(nslTarget);\n const ewlKey = keyForAffectedEntity(ewlTarget);\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: nslTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'delay', duration: null },\n basis: { evidenceId: 'evidence-1' },\n },\n {\n id: 'ie_test_002',\n type: 'service_effects.set',\n entity: ewlTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'no-service' },\n basis: { evidenceId: 'evidence-2' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(Object.keys(result.services)).toHaveLength(2);\n expect(result.services[nslKeyLocal].effect).toEqual({\n kind: 'delay',\n duration: null,\n });\n expect(result.services[nslKeyLocal]).toMatchObject({ id: 'NSL' });\n expect(result.services[ewlKey].effect).toEqual({ kind: 'no-service' });\n expect(result.services[ewlKey]).toMatchObject({ id: 'EWL' });\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('handles facility impacts', () => {\n const facilityEntity = {\n type: 'facility' as const,\n stationId: 'JUR',\n kind: 'lift' as const,\n };\n const facilityKey = keyForAffectedEntity(facilityEntity);\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'facility_effects.set',\n entity: facilityEntity,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'facility-out-of-service' },\n basis: { evidenceId: 'evidence-1' },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: facilityEntity,\n ts: '2025-01-01T10:00:00Z',\n periods: [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ],\n basis: { evidenceId: 'evidence-2' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.facilities[facilityKey]).toMatchObject({\n stationId: 'JUR',\n kind: 'lift',\n effect: { kind: 'facility-out-of-service' },\n periods: [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ],\n });\n expect(result.facilitiesProvenance[facilityKey]).toEqual({\n effect: { evidenceId: 'evidence-1' },\n periods: { evidenceId: 'evidence-2' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_002', 'ie_test_001']);\n });\n});\n"]}
1
+ {"version":3,"file":"deriveCurrentState.test.js","sourceRoot":"/","sources":["repo/issue/helpers/deriveCurrentState.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, test } from 'vitest';\nimport type { IssueBundle } from '../../../schema/issue/bundle.js';\nimport type { Period } from '../../../schema/issue/period.js';\nimport type { ServiceEffect } from '../../../schema/issue/serviceEffect.js';\nimport type { ServiceScope } from '../../../schema/issue/serviceScope.js';\nimport { keyForAffectedEntity } from '../../../helpers/keyForAffectedEntity.js';\nimport { deriveCurrentState } from './deriveCurrentState.js';\n\nconst defaultTarget = { type: 'service' as const, serviceId: 'NSL' };\nconst nslKey = keyForAffectedEntity(defaultTarget);\n\ndescribe('deriveCurrentState', () => {\n const createMockIssue = () => ({\n id: '2025-01-01-test-issue',\n type: 'disruption' as const,\n title: {\n 'en-SG': 'Test Issue',\n 'zh-Hans': null,\n ms: null,\n ta: null,\n },\n titleMeta: {\n source: 'test',\n },\n });\n\n const createMockBundle = (\n impact: IssueBundle['impactEvents'],\n ): IssueBundle => ({\n issue: createMockIssue(),\n evidence: [],\n impactEvents: impact,\n path: 'test/path',\n });\n\n test('returns empty state for bundle with no impacts', () => {\n const bundle = createMockBundle([]);\n const result = deriveCurrentState(bundle);\n\n expect(result).toEqual({\n services: {},\n servicesProvenance: {},\n facilities: {},\n facilitiesProvenance: {},\n impactEventIds: [],\n });\n });\n\n test('handles service_effects.set impact', () => {\n const effect: ServiceEffect = { kind: 'delay', duration: null };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect,\n scopes: [],\n periods: [],\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n effect: { evidenceId: 'evidence-1' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles periods_set impact', () => {\n const periods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n {\n kind: 'fixed',\n startAt: '2025-01-01T14:00:00+08:00',\n endAt: null,\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n periods,\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: [],\n periods,\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n periods: { evidenceId: 'evidence-3' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles causes.set impact', () => {\n const causes = ['signal.fault', 'track.fault'] as const;\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_cause_001',\n type: 'causes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n causes: [...causes],\n basis: { evidenceId: 'evidence-cause' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: [],\n periods: [],\n causes,\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n causes: { evidenceId: 'evidence-cause' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_cause_001']);\n });\n\n test('handles service_scopes_set impact', () => {\n const serviceScopes: ServiceScope[] = [\n {\n type: 'service.whole',\n },\n {\n type: 'service.segment',\n fromStationId: 'station-1',\n toStationId: 'station-2',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n serviceScopes,\n basis: {\n evidenceId: 'evidence-5',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: serviceScopes,\n periods: [],\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n scopes: { evidenceId: 'evidence-5' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles multiple impacts - later impacts overwrite earlier ones', () => {\n const firstEffect: ServiceEffect = { kind: 'delay', duration: null };\n const secondEffect: ServiceEffect = { kind: 'no-service' };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: firstEffect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n effect: secondEffect,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(secondEffect);\n expect(result.servicesProvenance[nslKey].effect?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('handles mixed impact types', () => {\n const effect: ServiceEffect = { kind: 'delay', duration: null };\n const periods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ];\n const serviceScopes: ServiceScope[] = [\n {\n type: 'service.point',\n stationId: 'station-1',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n {\n id: 'ie_test_003',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T12:00:00Z',\n serviceScopes,\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(effect);\n expect(result.services[nslKey].periods).toEqual(periods);\n expect(result.services[nslKey].scopes).toEqual(serviceScopes);\n expect(result.servicesProvenance[nslKey].effect?.evidenceId).toBe(\n 'evidence-1',\n );\n expect(result.servicesProvenance[nslKey].periods?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.servicesProvenance[nslKey].scopes?.evidenceId).toBe(\n 'evidence-3',\n );\n expect(result.impactEventIds).toEqual([\n 'ie_test_001',\n 'ie_test_003',\n 'ie_test_002',\n ]);\n });\n\n test('handles all service effect kinds', () => {\n const effectKinds: ServiceEffect['kind'][] = [\n 'delay',\n 'no-service',\n 'reduced-service',\n 'service-hours-adjustment',\n ];\n\n for (const kind of effectKinds) {\n const effect: ServiceEffect =\n kind === 'delay' ? { kind: 'delay', duration: null } : { kind };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(effect);\n }\n });\n\n test('handles all scope types', () => {\n const allScopes: ServiceScope[] = [\n {\n type: 'service.whole',\n },\n {\n type: 'service.segment',\n fromStationId: 'station-1',\n toStationId: 'station-2',\n },\n {\n type: 'service.point',\n stationId: 'station-3',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n serviceScopes: allScopes,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].scopes).toEqual(allScopes);\n expect(result.services[nslKey].scopes).toHaveLength(3);\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles empty arrays in impacts', () => {\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'no-service' },\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods: [],\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n {\n id: 'ie_test_003',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T12:00:00Z',\n serviceScopes: [],\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual({ kind: 'no-service' });\n expect(result.services[nslKey].periods).toEqual([]);\n expect(result.services[nslKey].scopes).toEqual([]);\n expect(result.impactEventIds).toEqual([\n 'ie_test_001',\n 'ie_test_003',\n 'ie_test_002',\n ]);\n });\n\n test('preserves order of impacts when processing', () => {\n const firstPeriods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ];\n const secondPeriods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T14:00:00+08:00',\n endAt: null,\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n periods: firstPeriods,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods: secondPeriods,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].periods).toEqual(secondPeriods);\n expect(result.servicesProvenance[nslKey].periods?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('groups impacts by target - different targets produce separate entries', () => {\n const nslTarget = { type: 'service' as const, serviceId: 'NSL' };\n const ewlTarget = { type: 'service' as const, serviceId: 'EWL' };\n const nslKeyLocal = keyForAffectedEntity(nslTarget);\n const ewlKey = keyForAffectedEntity(ewlTarget);\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: nslTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'delay', duration: null },\n basis: { evidenceId: 'evidence-1' },\n },\n {\n id: 'ie_test_002',\n type: 'service_effects.set',\n entity: ewlTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'no-service' },\n basis: { evidenceId: 'evidence-2' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(Object.keys(result.services)).toHaveLength(2);\n expect(result.services[nslKeyLocal].effect).toEqual({\n kind: 'delay',\n duration: null,\n });\n expect(result.services[nslKeyLocal]).toMatchObject({ id: 'NSL' });\n expect(result.services[ewlKey].effect).toEqual({ kind: 'no-service' });\n expect(result.services[ewlKey]).toMatchObject({ id: 'EWL' });\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('handles facility impacts', () => {\n const facilityEntity = {\n type: 'facility' as const,\n stationId: 'JUR',\n kind: 'lift' as const,\n };\n const facilityKey = keyForAffectedEntity(facilityEntity);\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'facility_effects.set',\n entity: facilityEntity,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'facility-out-of-service' },\n basis: { evidenceId: 'evidence-1' },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: facilityEntity,\n ts: '2025-01-01T10:00:00Z',\n periods: [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ],\n basis: { evidenceId: 'evidence-2' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.facilities[facilityKey]).toMatchObject({\n stationId: 'JUR',\n kind: 'lift',\n effect: { kind: 'facility-out-of-service' },\n periods: [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ],\n });\n expect(result.facilitiesProvenance[facilityKey]).toEqual({\n effect: { evidenceId: 'evidence-1' },\n periods: { evidenceId: 'evidence-2' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_002', 'ie_test_001']);\n });\n});\n"]}
@@ -1,5 +1,5 @@
1
1
  import z from 'zod';
2
- import { TranslationsSchema } from '#schema/common.js';
2
+ import { TranslationsSchema } from '../common.js';
3
3
  export const EvidenceRenderSchema = z.object({
4
4
  text: TranslationsSchema,
5
5
  source: z.string(),
@@ -1 +1 @@
1
- {"version":3,"file":"evidence.js","sourceRoot":"/","sources":["schema/issue/evidence.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,+BAA+B,GAAG,kBAAkB,CAAC,MAAM,CAAC;IACvE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAKH,MAAM,CAAC,MAAM,0BAA0B,GAAG,kBAAkB,CAAC,MAAM,CAAC;IAClE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,yBAAyB,GAAG,kBAAkB,CAAC,MAAM,CAAC;IACjE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;IAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACzD,+BAA+B;IAC/B,0BAA0B;IAC1B,yBAAyB;CAC1B,CAAC,CAAC","sourcesContent":["import z from 'zod';\nimport { TranslationsSchema } from '#schema/common.js';\n\nexport const EvidenceRenderSchema = z.object({\n text: TranslationsSchema,\n source: z.string(),\n});\nexport type EvidenceRender = z.infer<typeof EvidenceRenderSchema>;\n\nexport const EvidenceBaseSchema = z.object({\n id: z.string(),\n ts: z.string(),\n text: z.string(),\n render: EvidenceRenderSchema.nullable(),\n});\nexport type EvidenceBase = z.infer<typeof EvidenceBaseSchema>;\n\nexport const EvidenceOfficialStatementSchema = EvidenceBaseSchema.extend({\n type: z.literal('official-statement'),\n sourceUrl: z.string(),\n});\nexport type EvidenceOfficialStatement = z.infer<\n typeof EvidenceOfficialStatementSchema\n>;\n\nexport const EvidencePublicReportSchema = EvidenceBaseSchema.extend({\n type: z.literal('public.report'),\n sourceUrl: z.string(),\n});\nexport type EvidencePublicReport = z.infer<typeof EvidencePublicReportSchema>;\n\nexport const EvidenceMediaReportSchema = EvidenceBaseSchema.extend({\n type: z.literal('media.report'),\n sourceUrl: z.string(),\n});\nexport type EvidenceMediaReport = z.infer<typeof EvidenceMediaReportSchema>;\n\nexport const EvidenceSchema = z.discriminatedUnion('type', [\n EvidenceOfficialStatementSchema,\n EvidencePublicReportSchema,\n EvidenceMediaReportSchema,\n]);\nexport type Evidence = z.infer<typeof EvidenceSchema>;\n"]}
1
+ {"version":3,"file":"evidence.js","sourceRoot":"/","sources":["schema/issue/evidence.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,+BAA+B,GAAG,kBAAkB,CAAC,MAAM,CAAC;IACvE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAKH,MAAM,CAAC,MAAM,0BAA0B,GAAG,kBAAkB,CAAC,MAAM,CAAC;IAClE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,yBAAyB,GAAG,kBAAkB,CAAC,MAAM,CAAC;IACjE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;IAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACzD,+BAA+B;IAC/B,0BAA0B;IAC1B,yBAAyB;CAC1B,CAAC,CAAC","sourcesContent":["import z from 'zod';\nimport { TranslationsSchema } from '../common.js';\n\nexport const EvidenceRenderSchema = z.object({\n text: TranslationsSchema,\n source: z.string(),\n});\nexport type EvidenceRender = z.infer<typeof EvidenceRenderSchema>;\n\nexport const EvidenceBaseSchema = z.object({\n id: z.string(),\n ts: z.string(),\n text: z.string(),\n render: EvidenceRenderSchema.nullable(),\n});\nexport type EvidenceBase = z.infer<typeof EvidenceBaseSchema>;\n\nexport const EvidenceOfficialStatementSchema = EvidenceBaseSchema.extend({\n type: z.literal('official-statement'),\n sourceUrl: z.string(),\n});\nexport type EvidenceOfficialStatement = z.infer<\n typeof EvidenceOfficialStatementSchema\n>;\n\nexport const EvidencePublicReportSchema = EvidenceBaseSchema.extend({\n type: z.literal('public.report'),\n sourceUrl: z.string(),\n});\nexport type EvidencePublicReport = z.infer<typeof EvidencePublicReportSchema>;\n\nexport const EvidenceMediaReportSchema = EvidenceBaseSchema.extend({\n type: z.literal('media.report'),\n sourceUrl: z.string(),\n});\nexport type EvidenceMediaReport = z.infer<typeof EvidenceMediaReportSchema>;\n\nexport const EvidenceSchema = z.discriminatedUnion('type', [\n EvidenceOfficialStatementSchema,\n EvidencePublicReportSchema,\n EvidenceMediaReportSchema,\n]);\nexport type Evidence = z.infer<typeof EvidenceSchema>;\n"]}
@@ -1,5 +1,5 @@
1
1
  import z from 'zod';
2
- import { TranslationsSchema } from '#schema/common.js';
2
+ import { TranslationsSchema } from '../common.js';
3
3
  import { IssueIdSchema } from './id.js';
4
4
  import { IssueTypeSchema } from './issueType.js';
5
5
  export const IssueSchema = z.object({
@@ -1 +1 @@
1
- {"version":3,"file":"issue.js","sourceRoot":"/","sources":["schema/issue/issue.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,kBAAkB;IACzB,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;QAClB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;KACnB,CAAC;CACH,CAAC,CAAC","sourcesContent":["import z from 'zod';\nimport { TranslationsSchema } from '#schema/common.js';\nimport { IssueIdSchema } from './id.js';\nimport { IssueTypeSchema } from './issueType.js';\n\nexport const IssueSchema = z.object({\n id: IssueIdSchema,\n type: IssueTypeSchema,\n title: TranslationsSchema,\n titleMeta: z.object({\n source: z.string(),\n }),\n});\nexport type Issue = z.infer<typeof IssueSchema>;\n"]}
1
+ {"version":3,"file":"issue.js","sourceRoot":"/","sources":["schema/issue/issue.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,kBAAkB;IACzB,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;QAClB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;KACnB,CAAC;CACH,CAAC,CAAC","sourcesContent":["import z from 'zod';\nimport { TranslationsSchema } from '../common.js';\nimport { IssueIdSchema } from './id.js';\nimport { IssueTypeSchema } from './issueType.js';\n\nexport const IssueSchema = z.object({\n id: IssueIdSchema,\n type: IssueTypeSchema,\n title: TranslationsSchema,\n titleMeta: z.object({\n source: z.string(),\n }),\n});\nexport type Issue = z.infer<typeof IssueSchema>;\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { assert } from '../util/assert.js';
2
+ import { ingestContent } from '../util/ingestContent/index.js';
3
+ const { MESSAGE } = process.env;
4
+ assert(MESSAGE != null, 'Expected MESSAGE env var');
5
+ const message = JSON.parse(MESSAGE);
6
+ for (const content of message.content) {
7
+ await ingestContent(content);
8
+ }
9
+ //# sourceMappingURL=ingestViaWebhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingestViaWebhook.js","sourceRoot":"/","sources":["scripts/ingestViaWebhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAChC,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,0BAA0B,CAAC,CAAC;AAEpD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAEjC,CAAC;AACF,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACtC,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["import { assert } from '../util/assert.js';\nimport { ingestContent } from '../util/ingestContent/index.js';\nimport type { IngestContent } from '../util/ingestContent/types.js';\n\nconst { MESSAGE } = process.env;\nassert(MESSAGE != null, 'Expected MESSAGE env var');\n\nconst message = JSON.parse(MESSAGE) as {\n content: IngestContent[];\n};\nfor (const content of message.content) {\n await ingestContent(content);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { Claim } from '#schema/issue/claim.js';
1
+ import type { Claim } from '../../../schema/issue/claim.js';
2
2
  /**
3
3
  * Get the slug date time from the claims.
4
4
  * @param claims - The claims.
@@ -1,4 +1,4 @@
1
- import { assert } from '#util/assert.js';
1
+ import { assert } from '../../assert.js';
2
2
  /**
3
3
  * Get the slug date time from the claims.
4
4
  * @param claims - The claims.
@@ -1 +1 @@
1
- {"version":3,"file":"getSlugDateTimeFromClaims.js","sourceRoot":"/","sources":["util/ingestContent/helpers/getSlugDateTimeFromClaims.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAe;IACvD,MAAM,SAAS,GAAG,MAAM;SACrB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC;SAC1C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEnC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,qBAAqB,CAAC,CAAC;QACpD,QAAQ,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1B,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9B,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { Claim } from '#schema/issue/claim.js';\nimport { assert } from '#util/assert.js';\n\n/**\n * Get the slug date time from the claims.\n * @param claims - The claims.\n * @returns The slug date time or null if no time hints are found.\n */\nexport function getSlugDateTimeFromClaims(claims: Claim[]): string | null {\n const timeHints = claims\n .filter((claim) => claim.timeHints != null)\n .map((claim) => claim.timeHints);\n\n if (timeHints.length > 0) {\n assert(timeHints[0] != null, 'Expected time hints');\n switch (timeHints[0].kind) {\n case 'fixed': {\n return timeHints[0].startAt;\n }\n case 'recurring': {\n return timeHints[0].startAt;\n }\n }\n }\n\n return null;\n}\n"]}
1
+ {"version":3,"file":"getSlugDateTimeFromClaims.js","sourceRoot":"/","sources":["util/ingestContent/helpers/getSlugDateTimeFromClaims.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAe;IACvD,MAAM,SAAS,GAAG,MAAM;SACrB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC;SAC1C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEnC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,qBAAqB,CAAC,CAAC;QACpD,QAAQ,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1B,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9B,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { Claim } from '../../../schema/issue/claim.js';\nimport { assert } from '../../assert.js';\n\n/**\n * Get the slug date time from the claims.\n * @param claims - The claims.\n * @returns The slug date time or null if no time hints are found.\n */\nexport function getSlugDateTimeFromClaims(claims: Claim[]): string | null {\n const timeHints = claims\n .filter((claim) => claim.timeHints != null)\n .map((claim) => claim.timeHints);\n\n if (timeHints.length > 0) {\n assert(timeHints[0] != null, 'Expected time hints');\n switch (timeHints[0].kind) {\n case 'fixed': {\n return timeHints[0].startAt;\n }\n case 'recurring': {\n return timeHints[0].startAt;\n }\n }\n }\n\n return null;\n}\n"]}
@@ -1,15 +1,15 @@
1
1
  import { resolve } from 'node:path';
2
2
  import { DateTime } from 'luxon';
3
3
  import { ulid } from 'ulid';
4
- import { computeImpactFromEvidenceClaims } from '#helpers/computeImpactFromEvidenceClaims.js';
5
- import { extractClaimsFromNewEvidence } from '#llm/functions/extractClaimsFromNewEvidence/index.js';
6
- import { generateIssueTitleAndSlug } from '#llm/functions/generateIssueTitleAndSlug/index.js';
7
- import { translate } from '#llm/functions/translate/index.js';
8
- import { triageNewEvidence } from '#llm/functions/triageNewEvidence/index.js';
9
- import { FileStore } from '#repo/common/FileStore.js';
10
- import { MRTDownRepository } from '#repo/MRTDownRepository.js';
11
- import { FileWriteStore } from '#write/common/FileWriteStore.js';
12
- import { MRTDownWriter } from '#write/MRTDownWriter.js';
4
+ import { computeImpactFromEvidenceClaims } from '../../helpers/computeImpactFromEvidenceClaims.js';
5
+ import { extractClaimsFromNewEvidence } from '../../llm/functions/extractClaimsFromNewEvidence/index.js';
6
+ import { generateIssueTitleAndSlug } from '../../llm/functions/generateIssueTitleAndSlug/index.js';
7
+ import { translate } from '../../llm/functions/translate/index.js';
8
+ import { triageNewEvidence } from '../../llm/functions/triageNewEvidence/index.js';
9
+ import { FileStore } from '../../repo/common/FileStore.js';
10
+ import { MRTDownRepository } from '../../repo/MRTDownRepository.js';
11
+ import { FileWriteStore } from '../../write/common/FileWriteStore.js';
12
+ import { MRTDownWriter } from '../../write/MRTDownWriter.js';
13
13
  import { assert } from '../assert.js';
14
14
  import { getSlugDateTimeFromClaims } from './helpers/getSlugDateTimeFromClaims.js';
15
15
  const DATA_DIR = resolve(import.meta.dirname, '../../../data');