agentplane 0.3.10 → 0.3.11

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 (228) hide show
  1. package/assets/policy/governance.md +3 -4
  2. package/assets/policy/incidents.md +19 -88
  3. package/assets/policy/workflow.branch_pr.md +1 -1
  4. package/assets/policy/workflow.direct.md +2 -2
  5. package/bin/agentplane.js +56 -1
  6. package/bin/runtime-watch.js +1 -0
  7. package/bin/stale-dist-policy.d.ts +1 -1
  8. package/bin/stale-dist-policy.js +13 -0
  9. package/dist/.build-manifest.json +219 -154
  10. package/dist/cli/bootstrap-guide.d.ts.map +1 -1
  11. package/dist/cli/bootstrap-guide.js +3 -2
  12. package/dist/cli/command-guide.d.ts.map +1 -1
  13. package/dist/cli/command-guide.js +2 -1
  14. package/dist/cli/command-invocations.d.ts.map +1 -1
  15. package/dist/cli/command-invocations.js +4 -1
  16. package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
  17. package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
  18. package/dist/cli/run-cli/command-catalog/project.js +3 -1
  19. package/dist/cli/run-cli/command-catalog/task.d.ts +1 -1
  20. package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -1
  21. package/dist/cli/run-cli/command-catalog/task.js +10 -0
  22. package/dist/cli/run-cli/command-catalog.d.ts +1 -1
  23. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  24. package/dist/cli/run-cli/commands/core/preflight.d.ts.map +1 -1
  25. package/dist/cli/run-cli/commands/core/preflight.js +44 -1
  26. package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
  27. package/dist/cli/run-cli.test-helpers.js +12 -0
  28. package/dist/commands/branch/cleanup-merged.d.ts +2 -0
  29. package/dist/commands/branch/cleanup-merged.d.ts.map +1 -1
  30. package/dist/commands/branch/cleanup-merged.js +132 -28
  31. package/dist/commands/branch/work-start.d.ts.map +1 -1
  32. package/dist/commands/branch/work-start.js +60 -1
  33. package/dist/commands/cleanup/merged.command.d.ts +2 -0
  34. package/dist/commands/cleanup/merged.command.d.ts.map +1 -1
  35. package/dist/commands/cleanup/merged.command.js +24 -0
  36. package/dist/commands/doctor/branch-pr.d.ts +4 -0
  37. package/dist/commands/doctor/branch-pr.d.ts.map +1 -0
  38. package/dist/commands/doctor/branch-pr.js +96 -0
  39. package/dist/commands/doctor/fixes.d.ts +5 -0
  40. package/dist/commands/doctor/fixes.d.ts.map +1 -1
  41. package/dist/commands/doctor/fixes.js +70 -0
  42. package/dist/commands/doctor.run.d.ts.map +1 -1
  43. package/dist/commands/doctor.run.js +6 -1
  44. package/dist/commands/finish.run.d.ts.map +1 -1
  45. package/dist/commands/finish.run.js +11 -0
  46. package/dist/commands/finish.spec.d.ts +11 -0
  47. package/dist/commands/finish.spec.d.ts.map +1 -1
  48. package/dist/commands/finish.spec.js +51 -0
  49. package/dist/commands/guard/impl/close-message.d.ts.map +1 -1
  50. package/dist/commands/guard/impl/close-message.js +23 -6
  51. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  52. package/dist/commands/guard/impl/commands.js +24 -2
  53. package/dist/commands/guard/impl/env.d.ts +1 -0
  54. package/dist/commands/guard/impl/env.d.ts.map +1 -1
  55. package/dist/commands/guard/impl/env.js +1 -0
  56. package/dist/commands/hooks/index.d.ts.map +1 -1
  57. package/dist/commands/hooks/index.js +98 -1
  58. package/dist/commands/incidents/collect.command.d.ts.map +1 -1
  59. package/dist/commands/incidents/collect.command.js +12 -7
  60. package/dist/commands/incidents/incidents.command.js +1 -1
  61. package/dist/commands/incidents/shared.d.ts +34 -0
  62. package/dist/commands/incidents/shared.d.ts.map +1 -1
  63. package/dist/commands/incidents/shared.js +166 -12
  64. package/dist/commands/pr/check.d.ts.map +1 -1
  65. package/dist/commands/pr/check.js +238 -135
  66. package/dist/commands/pr/close-superseded.d.ts +9 -0
  67. package/dist/commands/pr/close-superseded.d.ts.map +1 -0
  68. package/dist/commands/pr/close-superseded.js +129 -0
  69. package/dist/commands/pr/close.d.ts +11 -0
  70. package/dist/commands/pr/close.d.ts.map +1 -0
  71. package/dist/commands/pr/close.js +116 -0
  72. package/dist/commands/pr/index.d.ts +2 -0
  73. package/dist/commands/pr/index.d.ts.map +1 -1
  74. package/dist/commands/pr/index.js +2 -0
  75. package/dist/commands/pr/integrate/artifacts.d.ts +7 -0
  76. package/dist/commands/pr/integrate/artifacts.d.ts.map +1 -1
  77. package/dist/commands/pr/integrate/artifacts.js +66 -1
  78. package/dist/commands/pr/integrate/cmd.d.ts.map +1 -1
  79. package/dist/commands/pr/integrate/cmd.js +16 -0
  80. package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts +8 -0
  81. package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts.map +1 -0
  82. package/dist/commands/pr/integrate/internal/bootstrap-guidance.js +59 -0
  83. package/dist/commands/pr/integrate/internal/finalize.d.ts.map +1 -1
  84. package/dist/commands/pr/integrate/internal/finalize.js +40 -12
  85. package/dist/commands/pr/integrate/internal/merge.d.ts.map +1 -1
  86. package/dist/commands/pr/integrate/internal/merge.js +36 -13
  87. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts +13 -0
  88. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts.map +1 -0
  89. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.js +25 -0
  90. package/dist/commands/pr/integrate/internal/prepare.d.ts +3 -2
  91. package/dist/commands/pr/integrate/internal/prepare.d.ts.map +1 -1
  92. package/dist/commands/pr/integrate/internal/prepare.js +101 -38
  93. package/dist/commands/pr/internal/freshness.d.ts +20 -0
  94. package/dist/commands/pr/internal/freshness.d.ts.map +1 -0
  95. package/dist/commands/pr/internal/freshness.js +50 -0
  96. package/dist/commands/pr/internal/gh-api.d.ts +6 -0
  97. package/dist/commands/pr/internal/gh-api.d.ts.map +1 -0
  98. package/dist/commands/pr/internal/gh-api.js +80 -0
  99. package/dist/commands/pr/internal/pr-paths.d.ts +10 -0
  100. package/dist/commands/pr/internal/pr-paths.d.ts.map +1 -1
  101. package/dist/commands/pr/internal/pr-paths.js +10 -0
  102. package/dist/commands/pr/internal/review-template.d.ts.map +1 -1
  103. package/dist/commands/pr/internal/review-template.js +37 -4
  104. package/dist/commands/pr/internal/sync.d.ts +9 -0
  105. package/dist/commands/pr/internal/sync.d.ts.map +1 -1
  106. package/dist/commands/pr/internal/sync.js +462 -122
  107. package/dist/commands/pr/open.d.ts +1 -0
  108. package/dist/commands/pr/open.d.ts.map +1 -1
  109. package/dist/commands/pr/open.js +13 -2
  110. package/dist/commands/pr/pr.command.d.ts +15 -0
  111. package/dist/commands/pr/pr.command.d.ts.map +1 -1
  112. package/dist/commands/pr/pr.command.js +118 -2
  113. package/dist/commands/pr/update.d.ts.map +1 -1
  114. package/dist/commands/pr/update.js +59 -1
  115. package/dist/commands/release/apply.command.d.ts.map +1 -1
  116. package/dist/commands/release/apply.command.js +3 -17
  117. package/dist/commands/release/apply.preflight.d.ts.map +1 -1
  118. package/dist/commands/release/apply.preflight.js +1 -1
  119. package/dist/commands/shared/gh-transport.d.ts +16 -0
  120. package/dist/commands/shared/gh-transport.d.ts.map +1 -0
  121. package/dist/commands/shared/gh-transport.js +71 -0
  122. package/dist/commands/shared/git-diff.d.ts +3 -1
  123. package/dist/commands/shared/git-diff.d.ts.map +1 -1
  124. package/dist/commands/shared/git-diff.js +10 -2
  125. package/dist/commands/shared/git-ops.d.ts +1 -0
  126. package/dist/commands/shared/git-ops.d.ts.map +1 -1
  127. package/dist/commands/shared/git-ops.js +15 -0
  128. package/dist/commands/shared/git-worktree.d.ts +2 -0
  129. package/dist/commands/shared/git-worktree.d.ts.map +1 -1
  130. package/dist/commands/shared/git-worktree.js +22 -2
  131. package/dist/commands/shared/post-commit-pr-artifacts.d.ts +9 -0
  132. package/dist/commands/shared/post-commit-pr-artifacts.d.ts.map +1 -0
  133. package/dist/commands/shared/post-commit-pr-artifacts.js +22 -0
  134. package/dist/commands/shared/pr-meta.d.ts +20 -0
  135. package/dist/commands/shared/pr-meta.d.ts.map +1 -1
  136. package/dist/commands/shared/pr-meta.js +125 -0
  137. package/dist/commands/shared/task-backend.d.ts +7 -0
  138. package/dist/commands/shared/task-backend.d.ts.map +1 -1
  139. package/dist/commands/shared/task-backend.js +34 -22
  140. package/dist/commands/task/close-duplicate.d.ts.map +1 -1
  141. package/dist/commands/task/close-duplicate.js +34 -1
  142. package/dist/commands/task/derive.js +1 -1
  143. package/dist/commands/task/doc-template.d.ts.map +1 -1
  144. package/dist/commands/task/doc-template.js +7 -11
  145. package/dist/commands/task/findings-add.command.d.ts +20 -0
  146. package/dist/commands/task/findings-add.command.d.ts.map +1 -0
  147. package/dist/commands/task/findings-add.command.js +165 -0
  148. package/dist/commands/task/findings.command.d.ts +7 -0
  149. package/dist/commands/task/findings.command.d.ts.map +1 -0
  150. package/dist/commands/task/findings.command.js +20 -0
  151. package/dist/commands/task/findings.d.ts +63 -0
  152. package/dist/commands/task/findings.d.ts.map +1 -0
  153. package/dist/commands/task/findings.js +188 -0
  154. package/dist/commands/task/finish-shared.d.ts +1 -0
  155. package/dist/commands/task/finish-shared.d.ts.map +1 -1
  156. package/dist/commands/task/finish-shared.js +55 -1
  157. package/dist/commands/task/finish.d.ts +10 -0
  158. package/dist/commands/task/finish.d.ts.map +1 -1
  159. package/dist/commands/task/finish.js +125 -6
  160. package/dist/commands/task/hosted-close-pr.command.d.ts +11 -0
  161. package/dist/commands/task/hosted-close-pr.command.d.ts.map +1 -0
  162. package/dist/commands/task/hosted-close-pr.command.js +414 -0
  163. package/dist/commands/task/hosted-close.command.d.ts.map +1 -1
  164. package/dist/commands/task/hosted-close.command.js +49 -1
  165. package/dist/commands/task/hosted-merge-sync.d.ts +38 -0
  166. package/dist/commands/task/hosted-merge-sync.d.ts.map +1 -1
  167. package/dist/commands/task/hosted-merge-sync.js +249 -17
  168. package/dist/commands/task/index.d.ts +1 -0
  169. package/dist/commands/task/index.d.ts.map +1 -1
  170. package/dist/commands/task/index.js +1 -0
  171. package/dist/commands/task/new.d.ts +1 -0
  172. package/dist/commands/task/new.d.ts.map +1 -1
  173. package/dist/commands/task/new.js +71 -1
  174. package/dist/commands/task/new.spec.d.ts.map +1 -1
  175. package/dist/commands/task/new.spec.js +7 -0
  176. package/dist/commands/task/normalize.command.d.ts +2 -0
  177. package/dist/commands/task/normalize.command.d.ts.map +1 -1
  178. package/dist/commands/task/normalize.command.js +45 -0
  179. package/dist/commands/task/normalize.d.ts +2 -0
  180. package/dist/commands/task/normalize.d.ts.map +1 -1
  181. package/dist/commands/task/normalize.js +85 -8
  182. package/dist/commands/task/plan.d.ts.map +1 -1
  183. package/dist/commands/task/plan.js +7 -10
  184. package/dist/commands/task/shared/docs.d.ts +6 -0
  185. package/dist/commands/task/shared/docs.d.ts.map +1 -1
  186. package/dist/commands/task/shared/docs.js +14 -0
  187. package/dist/commands/task/shared/transitions.d.ts.map +1 -1
  188. package/dist/commands/task/shared/transitions.js +11 -1
  189. package/dist/commands/task/shared.d.ts +1 -1
  190. package/dist/commands/task/shared.d.ts.map +1 -1
  191. package/dist/commands/task/shared.js +1 -1
  192. package/dist/commands/task/start-ready.d.ts.map +1 -1
  193. package/dist/commands/task/start-ready.js +86 -0
  194. package/dist/commands/task/start.d.ts.map +1 -1
  195. package/dist/commands/task/start.js +7 -10
  196. package/dist/commands/task/task.command.d.ts.map +1 -1
  197. package/dist/commands/task/task.command.js +4 -0
  198. package/dist/commands/task/verify-command-shared.d.ts +19 -0
  199. package/dist/commands/task/verify-command-shared.d.ts.map +1 -1
  200. package/dist/commands/task/verify-command-shared.js +152 -1
  201. package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
  202. package/dist/commands/task/verify-ok.command.js +15 -2
  203. package/dist/commands/task/verify-record.d.ts +36 -0
  204. package/dist/commands/task/verify-record.d.ts.map +1 -1
  205. package/dist/commands/task/verify-record.js +166 -11
  206. package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
  207. package/dist/commands/task/verify-rework.command.js +15 -2
  208. package/dist/commands/task/verify-show.command.d.ts +1 -1
  209. package/dist/commands/task/verify-show.command.d.ts.map +1 -1
  210. package/dist/commands/task/verify-show.command.js +28 -1
  211. package/dist/commands/verify.run.d.ts.map +1 -1
  212. package/dist/commands/verify.run.js +12 -0
  213. package/dist/commands/verify.spec.d.ts +2 -6
  214. package/dist/commands/verify.spec.d.ts.map +1 -1
  215. package/dist/commands/verify.spec.js +30 -3
  216. package/dist/runtime/incidents/index.d.ts +1 -1
  217. package/dist/runtime/incidents/index.d.ts.map +1 -1
  218. package/dist/runtime/incidents/resolve.d.ts.map +1 -1
  219. package/dist/runtime/incidents/resolve.js +319 -73
  220. package/dist/runtime/incidents/types.d.ts +14 -2
  221. package/dist/runtime/incidents/types.d.ts.map +1 -1
  222. package/dist/shared/env.d.ts +1 -0
  223. package/dist/shared/env.d.ts.map +1 -1
  224. package/dist/shared/env.js +22 -1
  225. package/dist/shared/protected-paths.d.ts +1 -1
  226. package/dist/shared/protected-paths.d.ts.map +1 -1
  227. package/dist/shared/protected-paths.js +4 -0
  228. package/package.json +2 -2
@@ -1,8 +1,12 @@
1
- const INCIDENTS_HEADER = [
1
+ const STRUCTURED_INCIDENTS_HEADER = [
2
2
  "# Policy Incidents Log",
3
3
  "",
4
4
  "This is the single file for incident-derived and situational policy rules.",
5
5
  ].join("\n");
6
+ const COMPACT_INCIDENTS_HEADER = [
7
+ "# Policy Incidents Log",
8
+ "- Append-only. Required fields: `id`, `date`, `scope`, `failure`, `rule`, `evidence`, `enforcement`, `state`; optional: `tags`, `match`, `advice`, `source_task`, `fixability`.",
9
+ ].join("\n");
6
10
  function normalizeLines(text) {
7
11
  return text.replaceAll("\r\n", "\n").split("\n");
8
12
  }
@@ -50,12 +54,26 @@ function parseCsvList(value) {
50
54
  .map((item) => item.trim())
51
55
  .filter(Boolean));
52
56
  }
57
+ function incidentField(key, value) {
58
+ return [key, value];
59
+ }
53
60
  function parseBoolean(value) {
54
61
  const normalized = String(value ?? "")
55
62
  .trim()
56
63
  .toLowerCase();
57
64
  return normalized === "true" || normalized === "yes" || normalized === "y" || normalized === "1";
58
65
  }
66
+ function parseFixability(value) {
67
+ const normalized = String(value ?? "")
68
+ .trim()
69
+ .toLowerCase()
70
+ .replaceAll(/[\s_-]+/g, "");
71
+ if (normalized === "external")
72
+ return "external";
73
+ if (normalized === "repofixable" || normalized === "internal")
74
+ return "repo-fixable";
75
+ return null;
76
+ }
59
77
  function parseEntryState(value) {
60
78
  return value === "open" || value === "promoted" ? value : "stabilized";
61
79
  }
@@ -66,21 +84,94 @@ function appendFieldValue(record, key, value, joiner = " ") {
66
84
  }
67
85
  record[key] = `${record[key]}${joiner}${value.trim()}`.trim();
68
86
  }
69
- function buildIncidentFingerprint(entry) {
87
+ function deriveSourceTask(explicitSourceTask, evidence) {
88
+ const direct = String(explicitSourceTask ?? "").trim();
89
+ if (direct)
90
+ return direct;
91
+ const match = /\btasks?\s+([A-Za-z0-9-]+)/iu.exec(String(evidence ?? ""));
92
+ return match?.[1]?.trim() ?? null;
93
+ }
94
+ function buildIncidentSignature(entry) {
70
95
  return [
71
- entry.sourceTask ?? "",
72
96
  normalizeSearchText(entry.scope),
73
97
  normalizeSearchText(entry.failure),
74
98
  normalizeSearchText(entry.rule),
75
99
  ].join("|");
76
100
  }
101
+ function buildIncidentFingerprint(entry) {
102
+ return [entry.sourceTask ?? "", buildIncidentSignature(entry)].join("|");
103
+ }
77
104
  function buildMatchTerms(opts) {
78
105
  const scopeTokens = tokenize(opts.scope);
79
- return dedupeCaseInsensitive([...opts.explicitMatch, ...opts.tags, ...scopeTokens]).slice(0, 12);
106
+ const extraTokens = (opts.extraText ?? []).flatMap((value) => tokenize(value));
107
+ return dedupeCaseInsensitive([
108
+ ...opts.explicitMatch,
109
+ ...opts.tags,
110
+ ...scopeTokens,
111
+ ...extraTokens,
112
+ ]).slice(0, 16);
113
+ }
114
+ function parseDateOnly(value) {
115
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
116
+ return null;
117
+ const parsed = Date.parse(`${value}T00:00:00.000Z`);
118
+ return Number.isFinite(parsed) ? parsed : null;
119
+ }
120
+ function occursWithinDays(date, now, days) {
121
+ const timestamp = parseDateOnly(date);
122
+ if (timestamp === null)
123
+ return false;
124
+ const delta = now.getTime() - timestamp;
125
+ if (delta < 0)
126
+ return false;
127
+ return delta <= days * 24 * 60 * 60 * 1000;
128
+ }
129
+ function entryStateRank(state) {
130
+ if (state === "promoted")
131
+ return 2;
132
+ if (state === "stabilized")
133
+ return 1;
134
+ return 0;
135
+ }
136
+ function compareIncidentAdviceMatch(left, right) {
137
+ if (right.score !== left.score)
138
+ return right.score - left.score;
139
+ const rightState = entryStateRank(right.entry.state);
140
+ const leftState = entryStateRank(left.entry.state);
141
+ if (rightState !== leftState)
142
+ return rightState - leftState;
143
+ return right.entry.date.localeCompare(left.entry.date);
144
+ }
145
+ function summarizeTaskScope(scope, title) {
146
+ const lines = normalizeLines(scope ?? "");
147
+ for (const line of lines) {
148
+ const trimmed = line.trim();
149
+ if (!trimmed)
150
+ continue;
151
+ let candidate = trimmed.replace(/^-+\s*/, "");
152
+ candidate = candidate.replace(/^in scope:\s*/i, "").trim();
153
+ if (!candidate || /^out of scope:/i.test(candidate))
154
+ continue;
155
+ return candidate;
156
+ }
157
+ return title.trim();
158
+ }
159
+ function buildDerivedIncidentRule(scope) {
160
+ return `Analogous ${scope} work MUST review and apply the recorded external incident advice before retrying.`;
161
+ }
162
+ function resolveIncidentState(opts) {
163
+ const signature = buildIncidentSignature(opts.entry);
164
+ const similarEntries = opts.registry.entries.filter((candidate) => buildIncidentSignature(candidate) === signature);
165
+ if (similarEntries.some((candidate) => candidate.state === "promoted" ||
166
+ candidate.state === "stabilized" ||
167
+ occursWithinDays(candidate.date, opts.now, 30))) {
168
+ return "stabilized";
169
+ }
170
+ return "open";
80
171
  }
81
172
  export function createIncidentRegistrySkeleton() {
82
173
  return [
83
- INCIDENTS_HEADER,
174
+ STRUCTURED_INCIDENTS_HEADER,
84
175
  "",
85
176
  "## Entry contract",
86
177
  "",
@@ -88,7 +179,9 @@ export function createIncidentRegistrySkeleton() {
88
179
  "- Every entry MUST include: `id`, `date`, `scope`, `failure`, `rule`, `evidence`, `enforcement`, `state`.",
89
180
  "- New machine-matched entries SHOULD also include: `tags`, `match`, `advice`, `source_task`, `fixability`.",
90
181
  "- `rule` MUST be concrete and testable (`MUST` / `MUST NOT`).",
91
- "- `fixability: external` means the issue cannot be removed by changing only repository code and should instead stay as reusable operational advice.",
182
+ "- `fixability: external` means the issue cannot be removed by changing only repository code and should stay as reusable operational advice.",
183
+ "- `fixability: repo-fixable` means the issue can be removed by repository code changes and should still be captured as reusable incident advice when explicitly marked.",
184
+ "- First auto-promoted reusable incidents normally enter as `open` and still participate in targeted advice lookup; recurring equivalent incidents can append later `stabilized` entries.",
92
185
  "- `state` values: `open`, `stabilized`, `promoted`.",
93
186
  "",
94
187
  "## Entry template",
@@ -104,7 +197,7 @@ export function createIncidentRegistrySkeleton() {
104
197
  "- evidence: `<task ids / logs / links>`",
105
198
  "- enforcement: `<CI|test|lint|script|manual>`",
106
199
  "- source_task: `<task id>`",
107
- "- fixability: `<external>`",
200
+ "- fixability: `<external|repo-fixable>`",
108
201
  "- state: `<open|stabilized|promoted>`",
109
202
  "",
110
203
  "## Entries",
@@ -114,7 +207,6 @@ export function createIncidentRegistrySkeleton() {
114
207
  export function parseIncidentRegistry(text) {
115
208
  const lines = normalizeLines(text);
116
209
  const entries = [];
117
- let inEntries = false;
118
210
  let currentFields = null;
119
211
  let currentLine = 0;
120
212
  let currentKey = null;
@@ -122,7 +214,7 @@ export function parseIncidentRegistry(text) {
122
214
  if (!currentFields)
123
215
  return;
124
216
  const id = currentFields.id?.trim();
125
- if (!id) {
217
+ if (!id || !/^INC-\d{8}-\d+$/u.test(id)) {
126
218
  currentFields = null;
127
219
  currentKey = null;
128
220
  currentLine = 0;
@@ -133,6 +225,7 @@ export function parseIncidentRegistry(text) {
133
225
  const rule = currentFields.rule?.trim() ?? "";
134
226
  const evidence = currentFields.evidence?.trim() ?? "";
135
227
  const enforcement = currentFields.enforcement?.trim() ?? "manual";
228
+ const sourceTask = deriveSourceTask(currentFields.source_task, evidence);
136
229
  entries.push({
137
230
  id,
138
231
  date: currentFields.date?.trim() ?? "",
@@ -145,8 +238,8 @@ export function parseIncidentRegistry(text) {
145
238
  tags: parseCsvList(currentFields.tags),
146
239
  match: parseCsvList(currentFields.match),
147
240
  advice: currentFields.advice?.trim() || null,
148
- sourceTask: currentFields.source_task?.trim() || null,
149
- fixability: currentFields.fixability?.trim().toLowerCase() === "external" ? "external" : null,
241
+ sourceTask,
242
+ fixability: parseFixability(currentFields.fixability),
150
243
  rawFields: { ...currentFields },
151
244
  line: currentLine,
152
245
  });
@@ -156,23 +249,21 @@ export function parseIncidentRegistry(text) {
156
249
  };
157
250
  for (const [index, line] of lines.entries()) {
158
251
  const trimmed = line.trim();
159
- if (!inEntries) {
160
- if (trimmed === "## Entries")
161
- inEntries = true;
162
- continue;
163
- }
164
- if (/^##\s+/.test(trimmed))
165
- break;
166
- const idMatch = /^- id:\s*(.+?)\s*$/.exec(trimmed);
167
- if (idMatch) {
252
+ const inlineFields = parseInlineIncidentEntry(trimmed);
253
+ if (inlineFields) {
168
254
  flush();
169
- currentFields = { id: idMatch[1] ?? "" };
170
- currentKey = "id";
255
+ currentFields = { ...inlineFields };
256
+ const keys = Object.keys(inlineFields);
257
+ currentKey = keys.at(-1) ?? "id";
171
258
  currentLine = index + 1;
172
259
  continue;
173
260
  }
174
261
  if (!currentFields)
175
262
  continue;
263
+ if (/^##\s+/.test(trimmed)) {
264
+ flush();
265
+ continue;
266
+ }
176
267
  const fieldMatch = /^\s{2}([a-z_]+):\s*(.*?)\s*$/.exec(line);
177
268
  if (fieldMatch) {
178
269
  currentKey = String(fieldMatch[1] ?? "").trim();
@@ -191,32 +282,151 @@ export function parseIncidentRegistry(text) {
191
282
  return { entries };
192
283
  }
193
284
  export function formatIncidentRegistryEntry(entry) {
285
+ return formatIncidentRegistryEntryForStyle(entry, "structured");
286
+ }
287
+ function parseInlineIncidentEntry(trimmedLine) {
288
+ if (!trimmedLine.startsWith("- "))
289
+ return null;
290
+ const body = trimmedLine.slice(2).trim();
291
+ if (!body)
292
+ return null;
293
+ const segments = body.split(/\s+\|\s+(?=[a-z_]+:\s*)/u);
294
+ const fields = {};
295
+ for (const segment of segments) {
296
+ const match = /^([a-z_]+):\s*(.*?)\s*$/.exec(segment.trim());
297
+ if (!match)
298
+ return null;
299
+ const key = String(match[1] ?? "").trim();
300
+ if (!key)
301
+ return null;
302
+ fields[key] = match[2] ?? "";
303
+ }
304
+ return fields.id ? fields : null;
305
+ }
306
+ function formatIncidentRegistryEntryForStyle(entry, style) {
307
+ const compactFields = [
308
+ incidentField("id", entry.id),
309
+ incidentField("date", entry.date),
310
+ incidentField("scope", entry.scope),
311
+ ...(entry.tags.length > 0 ? [incidentField("tags", entry.tags.join(", "))] : []),
312
+ ...(entry.match.length > 0 ? [incidentField("match", entry.match.join(", "))] : []),
313
+ incidentField("failure", entry.failure),
314
+ ...(entry.advice ? [incidentField("advice", entry.advice)] : []),
315
+ incidentField("rule", entry.rule),
316
+ incidentField("evidence", entry.evidence),
317
+ incidentField("enforcement", entry.enforcement),
318
+ ...(entry.fixability ? [incidentField("fixability", entry.fixability)] : []),
319
+ incidentField("state", entry.state),
320
+ ];
321
+ if (style === "compact") {
322
+ return `- ${compactFields.map(([key, value]) => `${key}: ${value}`).join(" | ")}`;
323
+ }
324
+ const structuredFields = [
325
+ incidentField("id", entry.id),
326
+ incidentField("date", entry.date),
327
+ incidentField("scope", entry.scope),
328
+ ...(entry.tags.length > 0 ? [incidentField("tags", entry.tags.join(", "))] : []),
329
+ ...(entry.match.length > 0 ? [incidentField("match", entry.match.join(", "))] : []),
330
+ incidentField("failure", entry.failure),
331
+ ...(entry.advice ? [incidentField("advice", entry.advice)] : []),
332
+ incidentField("rule", entry.rule),
333
+ incidentField("evidence", entry.evidence),
334
+ incidentField("enforcement", entry.enforcement),
335
+ ...(entry.sourceTask ? [incidentField("source_task", entry.sourceTask)] : []),
336
+ ...(entry.fixability ? [incidentField("fixability", entry.fixability)] : []),
337
+ incidentField("state", entry.state),
338
+ ];
194
339
  return [
195
- `- id: ${entry.id}`,
196
- ` date: ${entry.date}`,
197
- ` scope: ${entry.scope}`,
198
- ...(entry.tags.length > 0 ? [` tags: ${entry.tags.join(", ")}`] : []),
199
- ...(entry.match.length > 0 ? [` match: ${entry.match.join(", ")}`] : []),
200
- ` failure: ${entry.failure}`,
201
- ...(entry.advice ? [` advice: ${entry.advice}`] : []),
202
- ` rule: ${entry.rule}`,
203
- ` evidence: ${entry.evidence}`,
204
- ` enforcement: ${entry.enforcement}`,
205
- ...(entry.sourceTask ? [` source_task: ${entry.sourceTask}`] : []),
206
- ...(entry.fixability ? [` fixability: ${entry.fixability}`] : []),
207
- ` state: ${entry.state}`,
340
+ `- ${structuredFields[0]?.[0]}: ${structuredFields[0]?.[1] ?? ""}`,
341
+ ...structuredFields.slice(1).map(([key, value]) => ` ${key}: ${value}`),
208
342
  ].join("\n");
209
343
  }
344
+ function detectRegistryStyle(text) {
345
+ return /(^|\n)## Entries\s*$/mu.test(text) || /(^|\n)## Entry contract\s*$/mu.test(text)
346
+ ? "structured"
347
+ : "compact";
348
+ }
349
+ function entryRichness(entry) {
350
+ return [
351
+ entry.sourceTask ? 4 : 0,
352
+ entry.advice ? 3 : 0,
353
+ entry.tags.length,
354
+ entry.match.length,
355
+ entry.fixability ? 1 : 0,
356
+ entry.evidence.length > 0 ? 1 : 0,
357
+ ].reduce((sum, item) => sum + item, 0);
358
+ }
359
+ function nextIncidentIdForDate(dateStamp, usedIds, nextByDate) {
360
+ let next = nextByDate.get(dateStamp) ?? 0;
361
+ do {
362
+ next += 1;
363
+ } while (usedIds.has(`INC-${dateStamp}-${String(next).padStart(2, "0")}`));
364
+ nextByDate.set(dateStamp, next);
365
+ return `INC-${dateStamp}-${String(next).padStart(2, "0")}`;
366
+ }
367
+ function normalizeIncidentRegistryEntries(entries) {
368
+ const byFingerprint = new Map();
369
+ const orderedFingerprints = [];
370
+ for (const entry of entries) {
371
+ const fingerprint = buildIncidentFingerprint(entry);
372
+ const existing = byFingerprint.get(fingerprint);
373
+ if (!existing) {
374
+ byFingerprint.set(fingerprint, { ...entry });
375
+ orderedFingerprints.push(fingerprint);
376
+ continue;
377
+ }
378
+ if (entryRichness(entry) >= entryRichness(existing)) {
379
+ byFingerprint.set(fingerprint, { ...entry });
380
+ }
381
+ }
382
+ const normalized = orderedFingerprints.map((fingerprint) => byFingerprint.get(fingerprint));
383
+ const usedIds = new Set();
384
+ const nextByDate = new Map();
385
+ for (const entry of normalized) {
386
+ const match = /^INC-(\d{8})-(\d+)$/u.exec(entry.id);
387
+ if (!match)
388
+ continue;
389
+ const [, dateStamp, seqRaw] = match;
390
+ const seq = Number.parseInt(seqRaw ?? "", 10);
391
+ if (!Number.isInteger(seq))
392
+ continue;
393
+ const existing = nextByDate.get(dateStamp) ?? 0;
394
+ if (seq > existing)
395
+ nextByDate.set(dateStamp, seq);
396
+ }
397
+ return normalized.map((entry) => {
398
+ const dateStamp = /^\d{4}-\d{2}-\d{2}$/u.test(entry.date)
399
+ ? entry.date.replaceAll("-", "")
400
+ : "00000000";
401
+ const nextId = usedIds.has(entry.id)
402
+ ? nextIncidentIdForDate(dateStamp, usedIds, nextByDate)
403
+ : entry.id;
404
+ usedIds.add(nextId);
405
+ return nextId === entry.id ? entry : { ...entry, id: nextId };
406
+ });
407
+ }
408
+ function renderIncidentRegistryDocument(entries, style) {
409
+ const header = style === "structured" ? createIncidentRegistrySkeleton().trimEnd() : COMPACT_INCIDENTS_HEADER;
410
+ if (entries.length === 0)
411
+ return `${header}\n`;
412
+ const separator = style === "structured" ? "\n\n" : "\n";
413
+ return `${header}\n${entries.map((entry) => formatIncidentRegistryEntryForStyle(entry, style)).join(separator)}\n`;
414
+ }
210
415
  export function appendIncidentRegistryEntries(currentText, entries) {
211
416
  if (entries.length === 0)
212
417
  return currentText;
213
- const base = currentText.trim().length > 0
214
- ? currentText.trimEnd()
215
- : createIncidentRegistrySkeleton().trimEnd();
216
- const suffix = entries.map((entry) => formatIncidentRegistryEntry(entry)).join("\n\n");
217
- return `${base}\n\n${suffix}\n`;
418
+ const baseText = currentText.trim().length > 0 ? currentText : createIncidentRegistrySkeleton();
419
+ const style = detectRegistryStyle(baseText);
420
+ const existing = parseIncidentRegistry(baseText);
421
+ const merged = normalizeIncidentRegistryEntries([...existing.entries, ...entries]);
422
+ return renderIncidentRegistryDocument(merged, style);
218
423
  }
219
424
  export function extractIncidentCandidatesFromFindings(findings) {
425
+ return parseIncidentFindingBlocks(findings)
426
+ .filter((candidate) => candidate.shouldPromote)
427
+ .map(({ shouldPromote: _shouldPromote, ...candidate }) => candidate);
428
+ }
429
+ function parseIncidentFindingBlocks(findings) {
220
430
  const lines = normalizeLines(findings);
221
431
  const candidates = [];
222
432
  let currentFields = null;
@@ -225,13 +435,11 @@ export function extractIncidentCandidatesFromFindings(findings) {
225
435
  const flush = () => {
226
436
  if (!currentFields)
227
437
  return;
228
- const promotion = currentFields.promotion?.trim() ?? "";
229
- if (promotion.toLowerCase() !== "incident-candidate") {
230
- currentFields = null;
231
- currentKey = null;
232
- currentLine = 0;
233
- return;
234
- }
438
+ const promotion = currentFields.promotion?.trim() || null;
439
+ const fixability = parseFixability(currentFields.fixability);
440
+ const incidentExternal = parseBoolean(currentFields.incidentexternal) || fixability === "external";
441
+ const incidentInternal = parseBoolean(currentFields.incidentinternal) || fixability === "repo-fixable";
442
+ const shouldPromote = promotion?.toLowerCase() === "incident-candidate" || incidentExternal || incidentInternal;
235
443
  const observation = currentFields.observation?.trim() ?? "";
236
444
  if (!observation) {
237
445
  currentFields = null;
@@ -249,7 +457,10 @@ export function extractIncidentCandidatesFromFindings(findings) {
249
457
  incidentAdvice: currentFields.incidentadvice?.trim() || null,
250
458
  incidentTags: parseCsvList(currentFields.incidenttags),
251
459
  incidentMatch: parseCsvList(currentFields.incidentmatch),
252
- incidentExternal: parseBoolean(currentFields.incidentexternal),
460
+ incidentExternal,
461
+ incidentInternal,
462
+ fixability,
463
+ shouldPromote,
253
464
  line: currentLine,
254
465
  rawFields: { ...currentFields },
255
466
  });
@@ -313,47 +524,69 @@ function nextIncidentId(entries, now) {
313
524
  }
314
525
  function buildPromotionIssues(candidate) {
315
526
  const missingFields = [];
316
- if (!candidate.incidentExternal)
317
- missingFields.push("IncidentExternal: true");
318
- if (!candidate.incidentScope)
319
- missingFields.push("IncidentScope");
320
- if (!candidate.incidentRule)
321
- missingFields.push("IncidentRule");
322
- if (!candidate.incidentAdvice)
323
- missingFields.push("IncidentAdvice");
527
+ if (!candidate.incidentExternal && !candidate.incidentInternal && candidate.fixability === null) {
528
+ missingFields.push("Fixability: external or IncidentExternal: true");
529
+ }
530
+ if (!candidate.incidentAdvice && !candidate.resolution) {
531
+ missingFields.push("Resolution or IncidentAdvice");
532
+ }
324
533
  return missingFields.length > 0 ? { candidate, missingFields } : null;
325
534
  }
326
535
  function buildIncidentRegistryEntry(opts) {
327
536
  const date = opts.now.toISOString().slice(0, 10);
537
+ const scope = opts.candidate.incidentScope ?? summarizeTaskScope(opts.task.scope, opts.task.title);
328
538
  const tags = dedupeCaseInsensitive([
329
539
  ...opts.candidate.incidentTags,
330
540
  ...opts.task.tags.map((tag) => tag.trim()),
331
541
  ]);
542
+ const advice = opts.candidate.incidentAdvice ?? opts.candidate.resolution ?? opts.candidate.observation;
543
+ const rule = opts.candidate.incidentRule ?? buildDerivedIncidentRule(scope);
544
+ const state = resolveIncidentState({
545
+ registry: opts.registry,
546
+ entry: {
547
+ scope,
548
+ failure: opts.candidate.observation,
549
+ rule,
550
+ },
551
+ now: opts.now,
552
+ });
332
553
  const match = buildMatchTerms({
333
- scope: opts.candidate.incidentScope ?? opts.task.title,
554
+ scope,
334
555
  tags,
335
556
  explicitMatch: opts.candidate.incidentMatch,
557
+ extraText: [opts.task.title, opts.task.description, advice],
336
558
  });
337
559
  return {
338
- id: nextIncidentId(opts.existingEntries, opts.now),
560
+ id: nextIncidentId(opts.registry.entries, opts.now),
339
561
  date,
340
- scope: opts.candidate.incidentScope ?? opts.task.title,
562
+ scope,
341
563
  failure: opts.candidate.observation,
342
- rule: opts.candidate.incidentRule ?? "",
564
+ rule,
343
565
  evidence: `task ${opts.task.id}${opts.task.commitHash ? `; commit ${opts.task.commitHash.slice(0, 12)}` : ""}`,
344
566
  enforcement: "manual",
345
- state: "stabilized",
567
+ state,
346
568
  tags,
347
569
  match,
348
- advice: opts.candidate.incidentAdvice,
570
+ advice,
349
571
  sourceTask: opts.task.id,
350
- fixability: "external",
572
+ fixability: opts.candidate.fixability ?? (opts.candidate.incidentInternal ? "repo-fixable" : "external"),
351
573
  rawFields: {},
352
574
  line: 0,
353
575
  };
354
576
  }
355
577
  export function planIncidentCollection(opts) {
356
- const candidates = extractIncidentCandidatesFromFindings(opts.findings);
578
+ const parsed = parseIncidentFindingBlocks(opts.findings);
579
+ const candidates = parsed
580
+ .filter((candidate) => candidate.shouldPromote)
581
+ .map(({ shouldPromote: _shouldPromote, ...candidate }) => candidate);
582
+ const skipped = parsed
583
+ .filter((candidate) => !candidate.shouldPromote)
584
+ .map(({ observation, line, rawFields }) => ({
585
+ observation,
586
+ line,
587
+ reason: "not_marked_external_or_promotable",
588
+ rawFields,
589
+ }));
357
590
  const issues = [];
358
591
  const promotable = [];
359
592
  const duplicates = [];
@@ -369,7 +602,10 @@ export function planIncidentCollection(opts) {
369
602
  task: opts.task,
370
603
  candidate,
371
604
  now,
372
- existingEntries: [...opts.registry.entries, ...promotable.map((item) => item.entry)],
605
+ registry: parseIncidentRegistry(appendIncidentRegistryEntries(createIncidentRegistrySkeleton(), [
606
+ ...opts.registry.entries,
607
+ ...promotable.map((item) => item.entry),
608
+ ])),
373
609
  });
374
610
  const fingerprint = buildIncidentFingerprint(entry);
375
611
  const draft = { candidate, entry, fingerprint };
@@ -380,7 +616,15 @@ export function planIncidentCollection(opts) {
380
616
  seenFingerprints.add(fingerprint);
381
617
  promotable.push(draft);
382
618
  }
383
- return { candidates, promotable, duplicates, issues };
619
+ return {
620
+ candidates,
621
+ skipped,
622
+ promotable,
623
+ duplicates,
624
+ issues,
625
+ findingsTextPresent: opts.findings.trim().length > 0,
626
+ structuredFindingCount: parsed.length,
627
+ };
384
628
  }
385
629
  export function buildIncidentAdviceQueryFromTask(opts) {
386
630
  return {
@@ -397,10 +641,8 @@ export function resolveIncidentAdviceMatches(opts) {
397
641
  const haystack = [opts.query.title, opts.query.description, opts.query.scope ?? ""].join(" ");
398
642
  const normalizedHaystack = normalizeSearchText(haystack);
399
643
  const queryTokens = new Set([...tokenize(haystack), ...tagSet]);
400
- const matches = [];
644
+ const matchesBySignature = new Map();
401
645
  for (const entry of opts.registry.entries) {
402
- if (entry.state === "open")
403
- continue;
404
646
  const matchedTags = entry.tags.filter((tag) => tagSet.has(tag.trim().toLowerCase()));
405
647
  const matchedTerms = entry.match.filter((term) => queryTokens.has(term.trim().toLowerCase()) ||
406
648
  normalizedHaystack.includes(normalizeSearchText(term)));
@@ -409,12 +651,16 @@ export function resolveIncidentAdviceMatches(opts) {
409
651
  const score = matchedTags.length * 5 + matchedTerms.length * 2 + (scopeMatched ? 3 : 0);
410
652
  if (score <= 0)
411
653
  continue;
412
- matches.push({ entry, score, matchedTags, matchedTerms, scopeMatched });
654
+ const match = { entry, score, matchedTags, matchedTerms, scopeMatched };
655
+ const signature = buildIncidentSignature(entry);
656
+ const existing = matchesBySignature.get(signature);
657
+ if (!existing || compareIncidentAdviceMatch(match, existing) < 0) {
658
+ matchesBySignature.set(signature, match);
659
+ }
413
660
  }
661
+ const matches = [...matchesBySignature.values()];
414
662
  matches.sort((left, right) => {
415
- if (right.score !== left.score)
416
- return right.score - left.score;
417
- return right.entry.date.localeCompare(left.entry.date);
663
+ return compareIncidentAdviceMatch(left, right);
418
664
  });
419
665
  return matches.slice(0, limit);
420
666
  }
@@ -12,7 +12,7 @@ export type IncidentRegistryEntry = {
12
12
  match: string[];
13
13
  advice: string | null;
14
14
  sourceTask: string | null;
15
- fixability: "external" | null;
15
+ fixability: "external" | "repo-fixable" | null;
16
16
  rawFields: Record<string, string>;
17
17
  line: number;
18
18
  };
@@ -23,20 +23,29 @@ export type IncidentFindingCandidate = {
23
23
  observation: string;
24
24
  impact: string | null;
25
25
  resolution: string | null;
26
- promotion: string;
26
+ promotion: string | null;
27
27
  incidentScope: string | null;
28
28
  incidentRule: string | null;
29
29
  incidentAdvice: string | null;
30
30
  incidentTags: string[];
31
31
  incidentMatch: string[];
32
32
  incidentExternal: boolean;
33
+ incidentInternal: boolean;
34
+ fixability: "external" | "repo-fixable" | null;
33
35
  line: number;
34
36
  rawFields: Record<string, string>;
35
37
  };
38
+ export type IncidentSkippedFinding = {
39
+ observation: string;
40
+ line: number;
41
+ reason: "not_marked_external_or_promotable";
42
+ rawFields: Record<string, string>;
43
+ };
36
44
  export type IncidentPromotionTaskContext = {
37
45
  id: string;
38
46
  title: string;
39
47
  description: string;
48
+ scope?: string | null;
40
49
  tags: string[];
41
50
  commitHash?: string | null;
42
51
  };
@@ -51,9 +60,12 @@ export type IncidentPromotionIssue = {
51
60
  };
52
61
  export type IncidentCollectionPlan = {
53
62
  candidates: IncidentFindingCandidate[];
63
+ skipped: IncidentSkippedFinding[];
54
64
  promotable: IncidentPromotionDraft[];
55
65
  duplicates: IncidentPromotionDraft[];
56
66
  issues: IncidentPromotionIssue[];
67
+ findingsTextPresent: boolean;
68
+ structuredFindingCount: number;
57
69
  };
58
70
  export type IncidentAdviceQuery = {
59
71
  taskId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/runtime/incidents/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,0BAA0B,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,CAAC;AAE5E,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,0BAA0B,CAAC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,wBAAwB,CAAC;IACpC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,wBAAwB,CAAC;IACpC,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,wBAAwB,EAAE,CAAC;IACvC,UAAU,EAAE,sBAAsB,EAAE,CAAC;IACrC,UAAU,EAAE,sBAAsB,EAAE,CAAC;IACrC,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/runtime/incidents/types.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export declare function parseDotEnv(text: string): Record<string, string>;
2
+ export declare function isDotEnvLoadedKey(key: string, env?: NodeJS.ProcessEnv): boolean;
2
3
  export declare function loadDotEnv(rootDir: string): Promise<void>;
3
4
  //# sourceMappingURL=env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/shared/env.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4BhE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAc/D"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/shared/env.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4BhE;AAmBD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE5F;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB/D"}