@cat-factory/integrations 0.101.3 → 0.102.0

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 (52) hide show
  1. package/dist/index.d.ts +5 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +5 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/modules/environments/EnvironmentHandlerSeeder.js +0 -0
  6. package/dist/modules/environments/EnvironmentHandlerSeeder.js.map +1 -1
  7. package/dist/modules/environments/EnvironmentProvisioningService.js +1 -1
  8. package/dist/modules/environments/EnvironmentProvisioningService.js.map +1 -1
  9. package/dist/modules/tasks/GitHubIssuesProvider.d.ts +6 -0
  10. package/dist/modules/tasks/GitHubIssuesProvider.d.ts.map +1 -1
  11. package/dist/modules/tasks/GitHubIssuesProvider.js +7 -0
  12. package/dist/modules/tasks/GitHubIssuesProvider.js.map +1 -1
  13. package/dist/modules/tasks/JiraProvider.d.ts +6 -0
  14. package/dist/modules/tasks/JiraProvider.d.ts.map +1 -1
  15. package/dist/modules/tasks/JiraProvider.js +7 -0
  16. package/dist/modules/tasks/JiraProvider.js.map +1 -1
  17. package/dist/modules/tasks/LinearTaskProvider.d.ts +6 -0
  18. package/dist/modules/tasks/LinearTaskProvider.d.ts.map +1 -1
  19. package/dist/modules/tasks/LinearTaskProvider.js +7 -0
  20. package/dist/modules/tasks/LinearTaskProvider.js.map +1 -1
  21. package/dist/modules/tasks/TaskConnectionService.d.ts +63 -1
  22. package/dist/modules/tasks/TaskConnectionService.d.ts.map +1 -1
  23. package/dist/modules/tasks/TaskConnectionService.js +156 -2
  24. package/dist/modules/tasks/TaskConnectionService.js.map +1 -1
  25. package/dist/modules/tasks/TrackerWebhookService.d.ts +102 -0
  26. package/dist/modules/tasks/TrackerWebhookService.d.ts.map +1 -0
  27. package/dist/modules/tasks/TrackerWebhookService.js +245 -0
  28. package/dist/modules/tasks/TrackerWebhookService.js.map +1 -0
  29. package/dist/modules/tasks/intakeMatch.logic.d.ts +21 -0
  30. package/dist/modules/tasks/intakeMatch.logic.d.ts.map +1 -0
  31. package/dist/modules/tasks/intakeMatch.logic.js +43 -0
  32. package/dist/modules/tasks/intakeMatch.logic.js.map +1 -0
  33. package/dist/modules/tasks/webhook/adapters.d.ts +31 -0
  34. package/dist/modules/tasks/webhook/adapters.d.ts.map +1 -0
  35. package/dist/modules/tasks/webhook/adapters.js +259 -0
  36. package/dist/modules/tasks/webhook/adapters.js.map +1 -0
  37. package/dist/modules/tasks/webhook/hmac.d.ts +34 -0
  38. package/dist/modules/tasks/webhook/hmac.d.ts.map +1 -0
  39. package/dist/modules/tasks/webhook/hmac.js +98 -0
  40. package/dist/modules/tasks/webhook/hmac.js.map +1 -0
  41. package/dist/modules/writeback/IssueWritebackService.d.ts +17 -1
  42. package/dist/modules/writeback/IssueWritebackService.d.ts.map +1 -1
  43. package/dist/modules/writeback/IssueWritebackService.js +21 -1
  44. package/dist/modules/writeback/IssueWritebackService.js.map +1 -1
  45. package/dist/modules/writeback/reviewQuestions.logic.d.ts.map +1 -1
  46. package/dist/modules/writeback/reviewQuestions.logic.js +6 -1
  47. package/dist/modules/writeback/reviewQuestions.logic.js.map +1 -1
  48. package/dist/modules/writeback/reviewReplies.logic.d.ts +90 -0
  49. package/dist/modules/writeback/reviewReplies.logic.d.ts.map +1 -0
  50. package/dist/modules/writeback/reviewReplies.logic.js +262 -0
  51. package/dist/modules/writeback/reviewReplies.logic.js.map +1 -0
  52. package/package.json +4 -4
@@ -0,0 +1,262 @@
1
+ import { hostMarkdown, redactSecrets } from '@cat-factory/kernel';
2
+ // The ticket-reply half of the clarification loop: parse a tracker comment into review commands,
3
+ // and render the acknowledgement that goes back onto the same issue.
4
+ //
5
+ // Kept pure and separate from `TrackerWebhookService` for the same reason `reviewQuestions.logic.ts`
6
+ // is separate from `IssueWritebackService` — the grammar and the comment body are the parts a human
7
+ // actually interacts with, so they must be unit-testable without a tracker. They are DELIBERATELY
8
+ // siblings in this directory: the ids this parser matches are exactly the ids
9
+ // `renderReviewQuestionsComment` renders, and splitting them across packages is how the two halves
10
+ // would silently desync.
11
+ //
12
+ // Everything here treats the comment as UNTRUSTED third-party text — on a public repo anyone can
13
+ // write one. Three properties are load-bearing:
14
+ //
15
+ // 1. **Only explicit commands are interpreted.** A line counts only when its first non-space token
16
+ // is the trigger. Prose in the same comment is ignored, so a human can answer and discuss in
17
+ // one message, and no amount of natural-language phrasing can be mistaken for an instruction.
18
+ // 2. **The grammar cannot reach outside the review.** There is no verb for a model, a pipeline, a
19
+ // repo write, or a scope change — the most a comment can do is answer/dismiss a finding it
20
+ // names, or pick one of the three choices the SPA offers at the iteration cap.
21
+ // 3. **Nothing is echoed back raw.** The ack renders through kernel's `hostMarkdown` +
22
+ // `redactSecrets`, exactly like the question comment, because a tracker issue is a host-parsed
23
+ // and frequently PUBLIC surface.
24
+ /** The command trigger. Case-insensitive; must be the first token on the line. */
25
+ const TRIGGER = '@cat-factory';
26
+ /**
27
+ * The prefix every comment the PLATFORM writes onto a tracker issue opens with — the question
28
+ * echo and the reply acknowledgement alike. Exported so both renderers use the one constant and
29
+ * {@link isPlatformAuthoredComment} can never drift from what they emit.
30
+ */
31
+ export const PLATFORM_COMMENT_MARKER = '🤖 ';
32
+ /**
33
+ * Whether a comment body is one WE wrote.
34
+ *
35
+ * The identity checks in {@link isAllowedReplyAuthor} are the first line of defence, but they are
36
+ * not complete by construction: Linear flags no bots on a comment author (`bot: false`, honestly
37
+ * reported) and the default allow-list admits any author, so on Linear the platform's own
38
+ * acknowledgement is an ALLOWED author commenting on an issue it is linked to. Today no loop
39
+ * results, but only because no line of an ack happens to begin with the trigger — an invariant
40
+ * spread across two renderers, enforced by nothing, and one edit away from an unbounded
41
+ * comment loop (each ack carries a fresh comment id, so the ingest claim cannot stop it).
42
+ *
43
+ * So the guard is STRUCTURAL rather than incidental: a body whose first non-blank line opens with
44
+ * the marker is ours, and is never ingested. It costs one string comparison and removes the whole
45
+ * class of failure, on every vendor, whatever a future renderer says.
46
+ */
47
+ export function isPlatformAuthoredComment(body) {
48
+ const first = body.split(/\r?\n/).find((line) => line.trim().length > 0) ?? '';
49
+ return first.trimStart().startsWith(PLATFORM_COMMENT_MARKER.trimEnd());
50
+ }
51
+ /**
52
+ * Longest answer text accepted from one command. An answer becomes `item.reply`, which is fed to
53
+ * the incorporation model as delimited untrusted input — so this is a prompt-budget bound, not a
54
+ * storage one. Generous enough for a real paragraph-scale answer; a reporter with more to say has
55
+ * the run's own surfaces.
56
+ */
57
+ const MAX_ANSWER_CHARS = 4_000;
58
+ /** Longest comment scanned. Beyond this a comment is prose, not a command sheet. */
59
+ const MAX_COMMENT_CHARS = 64_000;
60
+ /** Most commands honoured from one comment, so a pathological paste cannot fan out. */
61
+ const MAX_COMMANDS = 50;
62
+ /**
63
+ * Parse a tracker comment into review commands.
64
+ *
65
+ * Returns an EMPTY array for a comment with no trigger line — which the caller treats as "ignore
66
+ * this comment entirely", never as an error and never as something to acknowledge. That silence is
67
+ * deliberate: most comments on a linked issue are ordinary human discussion, and acking them would
68
+ * turn every thread into a bot conversation. A BARE mention (`@cat-factory` with no verb after it)
69
+ * counts as discussion for the same reason and yields nothing.
70
+ *
71
+ * An `answer`'s text continues onto following lines until the next trigger line or the end of the
72
+ * comment, so a multi-paragraph answer needs no escaping.
73
+ *
74
+ * An unrecognised verb yields `{ verb: 'unknown' }` rather than being dropped: D4 requires it to be
75
+ * REPORTED in the follow-up, because a reporter who typed `@cat-factory reply CF-2 …` and heard
76
+ * nothing back would reasonably conclude the whole mechanism is broken. That is a near-MISS at a
77
+ * command and stays reported; the bare mention above is not an attempt at one at all, which is the
78
+ * line between the two.
79
+ */
80
+ export function parseReviewReplyCommands(comment) {
81
+ const lines = comment.slice(0, MAX_COMMENT_CHARS).split(/\r?\n/);
82
+ const commands = [];
83
+ let open = null;
84
+ const flush = () => {
85
+ if (!open)
86
+ return;
87
+ commands.push({ ...open, text: open.text.trim().slice(0, MAX_ANSWER_CHARS) });
88
+ open = null;
89
+ };
90
+ for (const raw of lines) {
91
+ if (!isTriggerLine(raw)) {
92
+ // A continuation line, but only while an `answer` is open — otherwise it is ordinary prose.
93
+ if (open)
94
+ open.text += `\n${raw}`;
95
+ continue;
96
+ }
97
+ flush();
98
+ if (commands.length >= MAX_COMMANDS)
99
+ break;
100
+ const rest = raw.trim().slice(TRIGGER.length).trim();
101
+ const [verb = '', ...tail] = rest.split(/\s+/);
102
+ const line = raw.trim();
103
+ // A BARE mention (`@cat-factory`, or the trigger followed only by prose) is not a malformed
104
+ // command — it is someone tagging us in discussion. Reporting it as `unknown` would be worse
105
+ // than useless: a non-empty command list drives the whole ingest (projection read, review
106
+ // read, a consumed claim) and ends in a follow-up comment telling a human who asked a question
107
+ // that their "command" was unrecognised. Skipping it keeps the parser's own promise that a
108
+ // comment with no commands is ignored ENTIRELY.
109
+ if (!verb)
110
+ continue;
111
+ switch (verb.toLowerCase()) {
112
+ case 'answer': {
113
+ const itemId = tail[0];
114
+ if (!itemId) {
115
+ commands.push({ verb: 'unknown', line });
116
+ break;
117
+ }
118
+ // Re-slice from the ORIGINAL line rather than re-joining the split tokens, so the answer
119
+ // keeps the reporter's own spacing instead of being silently normalised.
120
+ //
121
+ // Slice past the VERB first. Searching the whole remainder for the id would find its first
122
+ // occurrence anywhere — including inside the verb itself, so `answer a …` would locate the
123
+ // `a` of `answer` and take the rest of the WORD as the answer text.
124
+ const afterVerb = rest.slice(verb.length);
125
+ const text = afterVerb.slice(afterVerb.indexOf(itemId) + itemId.length).trim();
126
+ open = { verb: 'answer', itemId, text, line };
127
+ break;
128
+ }
129
+ case 'dismiss': {
130
+ const itemId = tail[0];
131
+ if (!itemId)
132
+ commands.push({ verb: 'unknown', line });
133
+ else
134
+ commands.push({ verb: 'dismiss', itemId, line });
135
+ break;
136
+ }
137
+ case 'proceed':
138
+ commands.push({ verb: 'proceed', line });
139
+ break;
140
+ case 'stop':
141
+ commands.push({ verb: 'stop', line });
142
+ break;
143
+ // Both spellings: the question comment renders the hyphenated form, but a reporter typing it
144
+ // from memory reaches for the underscore about as often, and rejecting that would be a
145
+ // pointless round-trip.
146
+ case 'extra-round':
147
+ case 'extra_round':
148
+ commands.push({ verb: 'extra-round', line });
149
+ break;
150
+ default:
151
+ commands.push({ verb: 'unknown', line });
152
+ }
153
+ }
154
+ flush();
155
+ return commands.slice(0, MAX_COMMANDS);
156
+ }
157
+ /** Whether a line's first non-space token is the trigger (case-insensitive). */
158
+ function isTriggerLine(line) {
159
+ const trimmed = line.trimStart();
160
+ if (!trimmed.toLowerCase().startsWith(TRIGGER))
161
+ return false;
162
+ // Require a boundary so `@cat-factory-bot` is not read as a command for `@cat-factory`.
163
+ const next = trimmed.charAt(TRIGGER.length);
164
+ return next === '' || /\s/.test(next);
165
+ }
166
+ /**
167
+ * Whether an author may drive a parked review from a ticket comment.
168
+ *
169
+ * Two layers, in order:
170
+ *
171
+ * - **Bots are never allowed.** The platform's own writeback comments come back as deliveries, so
172
+ * without this the ack would feed itself. This is checked FIRST so it cannot be defeated by an
173
+ * allow-list entry that happens to match a bot's display name.
174
+ * - **The connection's allow-list, when configured.** A comma-separated list of handles, emails or
175
+ * vendor ids, matched case-insensitively against any of the three. Empty ⇒ any non-bot author,
176
+ * which is the right default for a private tracker and the wrong one for a public repo — hence
177
+ * the knob rather than a hard-coded policy.
178
+ */
179
+ export function isAllowedReplyAuthor(author, allowList) {
180
+ if (author.bot)
181
+ return false;
182
+ const allowed = allowList
183
+ .split(',')
184
+ .map((entry) => entry.trim().toLowerCase())
185
+ .filter((entry) => entry.length > 0);
186
+ if (allowed.length === 0)
187
+ return true;
188
+ const identities = [author.handle, author.email, author.id]
189
+ .filter((v) => v != null)
190
+ .map((v) => v.toLowerCase());
191
+ return identities.some((identity) => allowed.includes(identity));
192
+ }
193
+ const MAX_TITLE_CHARS = 200;
194
+ const MAX_LINE_CHARS = 300;
195
+ const MAX_OUTSTANDING = 25;
196
+ /**
197
+ * Render the follow-up comment that closes a ticket reply.
198
+ *
199
+ * Its job is to tell the reporter the ONE thing they cannot see from the tracker: what the run did.
200
+ * So the outcome leads, the still-open findings follow (with their ids, so the next reply can name
201
+ * them), and anything rejected is stated explicitly — a silently ignored command reads exactly like
202
+ * a broken integration.
203
+ */
204
+ export function renderReviewReplyAck(ack) {
205
+ const lines = [PLATFORM_COMMENT_MARKER + outcomeLine(ack)];
206
+ const applied = [];
207
+ if (ack.answered.length > 0)
208
+ applied.push(`answered ${idList(ack.answered)}`);
209
+ if (ack.dismissed.length > 0)
210
+ applied.push(`dismissed ${idList(ack.dismissed)}`);
211
+ if (applied.length > 0)
212
+ lines.push('', `Applied: ${applied.join('; ')}.`);
213
+ if (ack.outstanding.length > 0) {
214
+ const shown = ack.outstanding.slice(0, MAX_OUTSTANDING);
215
+ const omitted = ack.outstanding.length - shown.length;
216
+ lines.push('', 'Still open:');
217
+ for (const finding of shown) {
218
+ lines.push(`- **\`${finding.id}\`** — ${safeInline(finding.title, MAX_TITLE_CHARS)}`);
219
+ }
220
+ if (omitted > 0) {
221
+ lines.push(`- _${omitted} more — open run \`${ack.runId}\` to see them all._`);
222
+ }
223
+ lines.push('', 'Reply with `@cat-factory answer <id> <your answer>` (or `@cat-factory dismiss <id>`) ' +
224
+ 'on its own line for each.');
225
+ }
226
+ if (ack.rejected.length > 0) {
227
+ lines.push('', 'Not applied:');
228
+ for (const rejection of ack.rejected) {
229
+ lines.push(`- \`${safeInline(rejection.command, MAX_LINE_CHARS)}\` — ${rejection.reason}`);
230
+ }
231
+ }
232
+ if (ack.outcome === 'exceeded') {
233
+ lines.push('', 'This review has used its full iteration budget. Reply `@cat-factory proceed` to go ahead ' +
234
+ 'with the requirements as they stand, `@cat-factory extra-round` for one more pass, or ' +
235
+ '`@cat-factory stop` to park the task for reworking.');
236
+ }
237
+ return lines.join('\n');
238
+ }
239
+ /** The headline: what the RUN is doing now, in the reporter's terms. */
240
+ function outcomeLine(ack) {
241
+ switch (ack.outcome) {
242
+ case 'incorporating':
243
+ return 'Thanks — that answers everything outstanding. The requirements are being folded in and re-reviewed; the run will continue on its own.';
244
+ case 'awaiting':
245
+ return 'Thanks — your answers were recorded. The run is still waiting on the questions below.';
246
+ case 'exceeded':
247
+ return 'Your answers were recorded, but this review has reached its iteration cap and needs a decision.';
248
+ case 'resolved':
249
+ return 'Done — the run has been moved on as requested.';
250
+ case 'settled':
251
+ return 'This review has already moved on, so nothing was applied. The run is no longer waiting on these questions.';
252
+ }
253
+ }
254
+ /** Ids are platform-minted, so they are the one thing rendered verbatim (in code spans). */
255
+ function idList(ids) {
256
+ return ids.map((id) => `\`${id}\``).join(', ');
257
+ }
258
+ /** Scrub secrets, THEN hand to the host boundary — the order `reviewQuestions.logic.ts` fixes. */
259
+ function safeInline(value, max) {
260
+ return hostMarkdown.inline(redactSecrets(value) ?? '', max);
261
+ }
262
+ //# sourceMappingURL=reviewReplies.logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewReplies.logic.js","sourceRoot":"","sources":["../../../src/modules/writeback/reviewReplies.logic.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/integrations",
3
- "version": "0.101.3",
3
+ "version": "0.102.0",
4
4
  "description": "External-system integration domain logic for the Agent Architecture Board (GitHub, documents, tasks, environments, runners).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,15 +27,15 @@
27
27
  "ai": "^7.0.37",
28
28
  "p-map": "^7.0.6",
29
29
  "yaml": "^2.9.0",
30
- "@cat-factory/contracts": "0.171.0",
31
- "@cat-factory/kernel": "0.165.0"
30
+ "@cat-factory/contracts": "0.172.0",
31
+ "@cat-factory/kernel": "0.166.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "typescript": "7.0.2",
35
35
  "undici": "^8.9.0",
36
36
  "valibot": "^1.4.2",
37
37
  "vitest": "^4.1.10",
38
- "@cat-factory/caching": "0.10.48"
38
+ "@cat-factory/caching": "0.10.50"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b tsconfig.build.json",