@cat-factory/orchestration 0.140.0 → 0.141.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 (29) hide show
  1. package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
  2. package/dist/modules/execution/ExecutionService.js +2 -0
  3. package/dist/modules/execution/ExecutionService.js.map +1 -1
  4. package/dist/modules/execution/ReviewGateController.d.ts +43 -1
  5. package/dist/modules/execution/ReviewGateController.d.ts.map +1 -1
  6. package/dist/modules/execution/ReviewGateController.js +55 -4
  7. package/dist/modules/execution/ReviewGateController.js.map +1 -1
  8. package/dist/modules/execution/gate-window-controllers.d.ts +4 -0
  9. package/dist/modules/execution/gate-window-controllers.d.ts.map +1 -1
  10. package/dist/modules/execution/gate-window-controllers.js +3 -1
  11. package/dist/modules/execution/gate-window-controllers.js.map +1 -1
  12. package/dist/modules/execution/prReport.logic.d.ts.map +1 -1
  13. package/dist/modules/execution/prReport.logic.js +22 -21
  14. package/dist/modules/execution/prReport.logic.js.map +1 -1
  15. package/dist/modules/execution/review-kinds.d.ts.map +1 -1
  16. package/dist/modules/execution/review-kinds.js +4 -0
  17. package/dist/modules/execution/review-kinds.js.map +1 -1
  18. package/dist/modules/execution/reviewQuestionWriteback.logic.d.ts +30 -0
  19. package/dist/modules/execution/reviewQuestionWriteback.logic.d.ts.map +1 -0
  20. package/dist/modules/execution/reviewQuestionWriteback.logic.js +50 -0
  21. package/dist/modules/execution/reviewQuestionWriteback.logic.js.map +1 -0
  22. package/dist/modules/recurring/TrackerSettingsService.d.ts.map +1 -1
  23. package/dist/modules/recurring/TrackerSettingsService.js +4 -0
  24. package/dist/modules/recurring/TrackerSettingsService.js.map +1 -1
  25. package/package.json +11 -11
  26. package/dist/modules/execution/prReportText.logic.d.ts +0 -46
  27. package/dist/modules/execution/prReportText.logic.d.ts.map +0 -1
  28. package/dist/modules/execution/prReportText.logic.js +0 -188
  29. package/dist/modules/execution/prReportText.logic.js.map +0 -1
@@ -1,188 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // The PR verification report's TEXT BOUNDARY.
3
- //
4
- // A pull-request description is NOT an inert string sink. The host parses it: `#123` becomes
5
- // an issue link, `@name` notifies a real person, a closing keyword in front of an issue
6
- // reference CLOSES that issue when the PR merges, a newline ends a markdown table row, and an
7
- // unbalanced code fence swallows everything after it — including the machine-readable JSON
8
- // block external tooling ingests.
9
- //
10
- // Almost everything the report interpolates is written by an agent or a human (a task title,
11
- // a tester summary, a merge rationale, a provisioner's stderr), so all of those are live
12
- // hazards rather than theoretical ones: "This closes #42" is idiomatic prose for a merge
13
- // rationale to emit, and it must not close issue 42.
14
- //
15
- // This module is the single place that turns untrusted text into something safe to splice
16
- // into a PR body. It is deliberately separate from the composer (which decides WHAT to say)
17
- // and from the marker splice in kernel (which decides WHERE it goes).
18
- // ---------------------------------------------------------------------------
19
- /** Free-text prose (a tester summary, a merge rationale) is capped at this many characters. */
20
- export const MAX_PROSE_CHARS = 4_000;
21
- /** A single markdown table cell is capped at this many characters. */
22
- export const MAX_CELL_CHARS = 300;
23
- /** Any rendered list/table in the report is capped at this many rows. */
24
- export const MAX_LIST_ITEMS = 50;
25
- /**
26
- * Hard ceiling for the whole rendered section. GitHub rejects a PR body over 65,536
27
- * characters with a 422, and the body also has to hold the agent's own description, so the
28
- * managed region keeps well clear of the limit. With the per-field caps above this is
29
- * unreachable for realistic runs; it exists so that pathological data degrades visibly
30
- * instead of making every publish fail silently forever.
31
- */
32
- export const MAX_SECTION_CHARS = 50_000;
33
- /** Marks where a value was cut, so a reader never mistakes a truncation for the whole story. */
34
- const TRUNCATION_NOTE = '… (truncated)';
35
- /**
36
- * The host's closing keywords. A PR body carrying one of these in front of an issue reference
37
- * closes that issue on merge — a side effect the engine must never trigger on the agent's
38
- * behalf. Same list on GitHub and GitLab.
39
- */
40
- const CLOSING_KEYWORDS = 'close[sd]?|closing|fix|fixe[sd]|fixing|resolve[sd]?|resolving|implement(?:s|ed)?|implementing';
41
- /** An issue/MR URL on either host, in the form a closing keyword can reference. */
42
- const ISSUE_URL = String.raw `https?://\S+?/(?:issues|-/issues|merge_requests|pull)/\d+`;
43
- /**
44
- * Every auto-linking trigger, in ONE alternation.
45
- *
46
- * Deliberately a single pass rather than chained `.replace()` calls: each escape EMITS a `#`,
47
- * so a later rule would re-escape the output of an earlier one (`@` → `@` → `@`).
48
- * One regex means the replacement text is never rescanned.
49
- */
50
- const AUTO_LINK_TRIGGERS = new RegExp([
51
- // A closing keyword in front of an issue/MR URL. The URL form survives the character
52
- // escapes below (nothing in it is a trigger), so the KEYWORD is what gets defused.
53
- String.raw `(?<keyword>\b(?:${CLOSING_KEYWORDS}))(?=\s*:?\s+${ISSUE_URL})`,
54
- // `@name` / `@org/team` — a mention notifies a real account.
55
- String.raw `(?<at>@(?=[A-Za-z0-9]))`,
56
- // `#123` and `owner/repo#123` — an issue/PR cross-reference.
57
- String.raw `(?<hash>#(?=\d))`,
58
- // `!123` — GitLab's merge-request reference.
59
- String.raw `(?<bang>!(?=\d))`,
60
- ].join('|'), 'gi');
61
- /**
62
- * Neutralise the host's auto-linking triggers in ONE line of untrusted text, leaving inline
63
- * code spans alone (the host does not auto-link inside them, so escaping there would only
64
- * show the reader a literal `&#35;`).
65
- *
66
- * The escapes are numeric HTML entities, which render as the original character but are
67
- * invisible to the reference parser — so the reader sees exactly what the agent wrote while
68
- * the mention/close side effects are defused.
69
- */
70
- function inertLine(line) {
71
- return mapOutsideCodeSpans(line, (text) => text.replace(AUTO_LINK_TRIGGERS, (match, ...args) => {
72
- const groups = args[args.length - 1];
73
- // Entity-escaping the FIRST character is enough to break the parser's match while
74
- // rendering identically — which matters most for the keyword, whose remaining letters
75
- // are ordinary prose the reader should still see.
76
- return `&#${match.charCodeAt(0)};${groups.keyword ? match.slice(1) : ''}`;
77
- }));
78
- }
79
- /**
80
- * Apply `fn` to the parts of `line` that are NOT inline code spans. Code spans are matched by
81
- * a backtick run and its matching closer, which is CommonMark's rule and — more to the point
82
- * — the rule the host renderer applies when deciding where to auto-link.
83
- */
84
- function mapOutsideCodeSpans(line, fn) {
85
- const out = [];
86
- let index = 0;
87
- const span = /(`+)[\s\S]*?\1/g;
88
- let match;
89
- while ((match = span.exec(line)) !== null) {
90
- out.push(fn(line.slice(index, match.index)), match[0]);
91
- index = match.index + match[0].length;
92
- }
93
- return out.join('') + fn(line.slice(index));
94
- }
95
- /** A line that opens or closes a fenced code block, with the fence it uses. */
96
- function fenceAt(line) {
97
- const match = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
98
- if (!match)
99
- return null;
100
- const fence = match[1];
101
- // A ``` fence's info string may not contain a backtick (CommonMark), which is what stops an
102
- // inline span from being read as a fence.
103
- if (fence.startsWith('`') && match[2].includes('`'))
104
- return null;
105
- return { char: fence[0], length: fence.length, info: match[2].trim().length > 0 };
106
- }
107
- /**
108
- * Walk `lines`, tracking fenced-code state, and hand each line to `visit` together with
109
- * whether it sits INSIDE a fenced block. Returns the fence still open at the end, if any.
110
- *
111
- * One shared walker so the two things that care about fences — leaving code untouched, and
112
- * closing what the text left open — can never disagree about where a block starts and ends.
113
- */
114
- function walkFences(lines, visit) {
115
- let open = null;
116
- for (const line of lines) {
117
- const fence = fenceAt(line);
118
- // The fence line itself belongs to the code block, so it is never rewritten.
119
- visit(line, open !== null || fence !== null);
120
- if (!fence)
121
- continue;
122
- if (!open)
123
- open = { char: fence.char, length: fence.length };
124
- else if (fence.char === open.char && fence.length >= open.length && !fence.info)
125
- open = null;
126
- }
127
- return open;
128
- }
129
- /**
130
- * Close any code fence the text leaves open.
131
- *
132
- * An unbalanced fence in agent prose — an interrupted transcript, a truncated tool dump — would
133
- * otherwise swallow every section rendered after it, including the fenced JSON block that is
134
- * the report's machine-readable contract. Balancing preserves the agent's own formatting
135
- * (unlike escaping the fences) while guaranteeing the enclosing document stays well-formed.
136
- */
137
- export function balanceFences(text) {
138
- const open = walkFences(text.split('\n'), () => { });
139
- return open ? `${text}\n${open.char.repeat(open.length)}` : text;
140
- }
141
- /** Cut `value` to `max` characters, marking the cut. Prefers a line boundary when one is near. */
142
- function truncate(value, max) {
143
- if (value.length <= max)
144
- return value;
145
- const head = value.slice(0, max);
146
- const lastNewline = head.lastIndexOf('\n');
147
- const body = lastNewline > max * 0.6 ? head.slice(0, lastNewline) : head;
148
- return `${body.trimEnd()}\n\n${TRUNCATION_NOTE}`;
149
- }
150
- /**
151
- * Render untrusted multi-line prose as a safe markdown block: auto-link triggers defused,
152
- * length capped, and any code fence the value leaves open closed again.
153
- */
154
- export function prose(value) {
155
- const capped = truncate(value.replace(/\r\n?/g, '\n'), MAX_PROSE_CHARS);
156
- const rewritten = [];
157
- const open = walkFences(capped.split('\n'), (line, insideFence) => {
158
- rewritten.push(insideFence ? line : inertLine(line));
159
- });
160
- const text = rewritten.join('\n');
161
- return open ? `${text}\n${open.char.repeat(open.length)}` : text;
162
- }
163
- /**
164
- * Render untrusted text as ONE markdown table cell: newlines folded to `<br>` (a raw newline
165
- * ends the row and spills the rest of the value into the document as loose prose), pipes
166
- * escaped so a value cannot open a new column, auto-link triggers defused, and the whole thing
167
- * capped so a stack trace cannot dominate the table.
168
- */
169
- export function cell(value) {
170
- const flattened = truncate(value.replace(/\r\n?/g, '\n'), MAX_CELL_CHARS)
171
- .replaceAll('|', '\\|')
172
- .replace(/\n+/g, '<br>');
173
- return inertLine(flattened);
174
- }
175
- /**
176
- * Render untrusted text INLINE (a title, a label — not a table cell, so pipes are harmless).
177
- * Newlines are folded to spaces because the surrounding line has its own meaning.
178
- */
179
- export function inline(value) {
180
- return inertLine(truncate(value.replace(/\s+/g, ' '), MAX_CELL_CHARS));
181
- }
182
- /** Cap a list at {@link MAX_LIST_ITEMS}, returning the kept rows plus how many were dropped. */
183
- export function capList(items) {
184
- if (items.length <= MAX_LIST_ITEMS)
185
- return { items: [...items], dropped: 0 };
186
- return { items: items.slice(0, MAX_LIST_ITEMS), dropped: items.length - MAX_LIST_ITEMS };
187
- }
188
- //# sourceMappingURL=prReportText.logic.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prReportText.logic.js","sourceRoot":"","sources":["../../../src/modules/execution/prReportText.logic.ts"],"names":[],"mappings":"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"}