@arii/boomtick-mcp 0.3.5 → 0.3.7

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.
@@ -82,6 +82,10 @@
82
82
  "state": {
83
83
  "anyOf": [
84
84
  {
85
+ "enum": [
86
+ "open",
87
+ "closed"
88
+ ],
85
89
  "type": "string"
86
90
  },
87
91
  {
@@ -89,7 +93,7 @@
89
93
  }
90
94
  ],
91
95
  "default": null,
92
- "description": "The state to set the issue to (open or closed).",
96
+ "description": "The state to set the issue to.",
93
97
  "title": "State"
94
98
  }
95
99
  },
@@ -2,13 +2,20 @@
2
2
  "properties": {
3
3
  "state": {
4
4
  "default": "open",
5
- "description": "The state of the PRs to search for (open, closed, all).",
5
+ "description": "The state of the PRs to search for.",
6
+ "enum": [
7
+ "open",
8
+ "closed",
9
+ "all"
10
+ ],
6
11
  "title": "State",
7
12
  "type": "string"
8
13
  },
9
14
  "limit": {
10
15
  "default": 100,
11
16
  "description": "The maximum number of PRs to return (default: 100, range: 1-100).",
17
+ "maximum": 100,
18
+ "minimum": 1,
12
19
  "title": "Limit",
13
20
  "type": "integer"
14
21
  },
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.7](https://github.com/arii/boomtick/compare/mcp-v0.3.6...mcp-v0.3.7) (2026-08-17)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **ci:** remove submodule-pinned action refs from impact-analysis ([#723](https://github.com/arii/boomtick/issues/723)) ([d6e0494](https://github.com/arii/boomtick/commit/d6e0494fe8ac781777fb1546bb3c0f0102074a5c))
9
+ * ensure impact analysis posts PR comments and sends Jules messages ([#724](https://github.com/arii/boomtick/issues/724)) ([a52cc8e](https://github.com/arii/boomtick/commit/a52cc8e220def8bf2057b4da1b596e80fc0eed1f))
10
+ * resolve script fallback paths in mcp impact-analysis action ([#716](https://github.com/arii/boomtick/issues/716)) ([b29dd06](https://github.com/arii/boomtick/commit/b29dd067da2b45fc8410ca26e34a8c74626fe937))
11
+
12
+ ## [0.3.6](https://github.com/arii/boomtick/compare/mcp-v0.3.5...mcp-v0.3.6) (2026-08-13)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **ai:** add gemini fallback logic to AIClient ([5cc87cc](https://github.com/arii/boomtick/commit/5cc87cc79e65df79db98bc27e679d14ffdd2d18d))
18
+ * **ai:** add gemini fallback logic to AIClient ([3ba37ec](https://github.com/arii/boomtick/commit/3ba37ec50a7447a9517e9f0029ff05ee01adf4d8))
19
+ * resolve td-cli not found in impact-analysis CI action ([#508](https://github.com/arii/boomtick/issues/508)) ([702643f](https://github.com/arii/boomtick/commit/702643f9d0d2447ae7baf20d22d553a7dfbae777))
20
+
3
21
  ## [0.3.5](https://github.com/arii/boomtick/compare/mcp-v0.3.4...mcp-v0.3.5) (2026-08-05)
4
22
 
5
23
 
@@ -7,7 +7,7 @@ inputs:
7
7
  runs:
8
8
  using: composite
9
9
  steps:
10
- - uses: ./mcp/actions/setup
10
+ - uses: arii/boomtick/mcp/actions/setup@main
11
11
  - name: AI review
12
12
  env:
13
13
  PR_NUMBER: ${{ inputs.pr_number }}
@@ -16,5 +16,5 @@ runs:
16
16
  echo "::error::Invalid PR_NUMBER: must be numeric."
17
17
  exit 1
18
18
  fi
19
- td-cli gh audit-pr "$PR_NUMBER" --fetch --audit
19
+ td-cli gh audit-pr "$PR_NUMBER" --fetch --audit --submit --execute
20
20
  shell: bash
@@ -7,7 +7,7 @@ inputs:
7
7
  runs:
8
8
  using: composite
9
9
  steps:
10
- - uses: ./mcp/actions/setup
10
+ - uses: arii/boomtick/mcp/actions/setup@main
11
11
 
12
12
  - name: Install dependencies
13
13
  run: pnpm install --frozen-lockfile --prefer-offline
@@ -3,7 +3,7 @@ description: Runs pre-submit checks via td-cli CLI
3
3
  runs:
4
4
  using: composite
5
5
  steps:
6
- - uses: ./mcp/actions/setup
6
+ - uses: arii/boomtick/mcp/actions/setup@main
7
7
  - name: Pre-submit gate
8
8
  run: td-cli gh pre-submit
9
9
  shell: bash
@@ -16,16 +16,17 @@ inputs:
16
16
  runs:
17
17
  using: composite
18
18
  steps:
19
- - uses: ./mcp/actions/setup
20
-
21
- - name: pnpm install
22
- run: pnpm install --frozen-lockfile --prefer-offline
19
+ - name: Configure Git Safe Directory
20
+ run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
23
21
  shell: bash
24
22
 
25
23
  - name: Validate PR Number
26
24
  env:
27
25
  PR_NUMBER: ${{ inputs.pr_number }}
28
26
  run: |
27
+ if [[ -z "$PR_NUMBER" ]]; then
28
+ exit 0
29
+ fi
29
30
  if [[ ! "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
30
31
  echo "::error::Invalid PR_NUMBER: must be numeric."
31
32
  exit 1
@@ -170,8 +171,13 @@ runs:
170
171
  echo "Executing check-visual-changes.ts at: $RESOLVED_PATH"
171
172
  pnpm exec tsx "$RESOLVED_PATH" >> "$GITHUB_OUTPUT"
172
173
  else
173
- echo "⚠️ Skipping: check-visual-changes.ts script not found. Defaulting changed_routes=0"
174
- echo "changed_routes=0" >> "$GITHUB_OUTPUT"
174
+ if [ -f "scripts/check-visual-changes.ts" ]; then
175
+ echo "Executing check-visual-changes.ts from current workspace."
176
+ pnpm exec tsx scripts/check-visual-changes.ts >> "$GITHUB_OUTPUT"
177
+ else
178
+ echo "⚠️ Skipping: check-visual-changes.ts script not found. Defaulting changed_routes=0"
179
+ echo "changed_routes=0" >> "$GITHUB_OUTPUT"
180
+ fi
175
181
  fi
176
182
  shell: bash
177
183
 
@@ -191,21 +197,6 @@ runs:
191
197
  fi
192
198
  shell: bash
193
199
 
194
- - name: Visual review github models agent
195
- if: always() && steps.check_visuals.outputs.changed_routes != '0' && steps.check_visuals.outputs.changed_routes != ''
196
- env:
197
- GITHUB_TOKEN: ${{ inputs.github_token }}
198
- PR_NUMBER: ${{ inputs.pr_number }}
199
- JULES_API_KEY: ${{ inputs.jules_api_key }}
200
- GITHUB_REPOSITORY: ${{ github.repository }}
201
- run: |
202
- if node -e "const pkg = require('./package.json'); if (!pkg.scripts || !pkg.scripts['impact:github-models-review']) process.exit(1)" 2>/dev/null; then
203
- pnpm run impact:github-models-review
204
- else
205
- echo "⚠️ Skipping: impact:github-models-review script not found"
206
- fi
207
- shell: bash
208
-
209
200
  - name: Report Summary
210
201
  if: always()
211
202
  run: |
@@ -238,26 +229,20 @@ runs:
238
229
  if [ -f artifacts/gemini-review.md ]; then
239
230
  { echo ""; cat artifacts/gemini-review.md; } >> "$GITHUB_STEP_SUMMARY"
240
231
  fi
241
- if [ -f artifacts/github-models-review.md ]; then
242
- { echo ""; cat artifacts/github-models-review.md; } >> "$GITHUB_STEP_SUMMARY"
243
- fi
244
232
  if [ -f artifacts/gemini-code-review.md ]; then
245
233
  { echo ""; cat artifacts/gemini-code-review.md; } >> "$GITHUB_STEP_SUMMARY"
246
234
  fi
247
- if [ -f artifacts/github-models-code-review.md ]; then
248
- { echo ""; cat artifacts/github-models-code-review.md; } >> "$GITHUB_STEP_SUMMARY"
249
- fi
250
235
 
251
236
  FAILED=0
252
- # Expected verdicts: gemini-code-review, github-models-code-review
237
+ # Expected verdicts: gemini-code-review
253
238
  # Visual reviews are expected only if visual changes exist
254
239
  EXPECTED_REVIEWS=""
255
240
  if [ "${{ steps.impact_analysis.outputs.has_impact }}" == "true" ]; then
256
241
  if [ "${{ github.event_name }}" == "pull_request" ]; then
257
- EXPECTED_REVIEWS="gemini-code-review github-models-code-review"
242
+ EXPECTED_REVIEWS="gemini-code-review"
258
243
  fi
259
244
  if [ "${{ steps.check_visuals.outputs.changed_routes }}" != "0" ] && [ "${{ steps.check_visuals.outputs.changed_routes }}" != "" ]; then
260
- EXPECTED_REVIEWS="$EXPECTED_REVIEWS gemini-review github-models-review"
245
+ EXPECTED_REVIEWS="$EXPECTED_REVIEWS gemini-review"
261
246
  fi
262
247
  fi
263
248
 
@@ -275,7 +260,7 @@ runs:
275
260
 
276
261
  if [[ "$VERDICT" == "warn" ]]; then
277
262
  # Only allow specific safe-skip reasons for warnings to pass CI
278
- IS_TRUNCATED=$(jq -r '.isTruncated // .truncated // "false"' "$f" 2>/dev/null)
263
+ IS_TRUNCATED=$(jq -r '.isTruncated // "false"' "$f" 2>/dev/null)
279
264
  SKIP_REASON=$(jq -r '.skipReason // "NONE"' "$f" 2>/dev/null)
280
265
 
281
266
  if [[ "$IS_TRUNCATED" == "true" || "$SKIP_REASON" == *"MISSING_API_KEY"* || "$SKIP_REASON" == *"RATE_LIMIT"* || "$SKIP_REASON" == *"UNHANDLED_ERROR"* || "$SKIP_REASON" == *"TRUNCATED"* || "$SKIP_REASON" == *"PARSE_ERROR"* || "$SKIP_REASON" == "NONE" ]]; then
@@ -325,19 +310,100 @@ runs:
325
310
  if [ -f "$TARGET_PATH" ]; then
326
311
  RESOLVED_PATH=$(realpath "$TARGET_PATH")
327
312
  echo "Executing send-jules-impact.py at: $RESOLVED_PATH"
313
+ export PYTHONPATH="$(realpath "${{ github.action_path }}/../../../cli"):$PYTHONPATH"
328
314
  python3 "$RESOLVED_PATH"
329
315
  else
330
- echo "⚠️ Skipping: send-jules-impact.py script not found."
316
+ # Fallback check for docker run execution or direct python script in checkout workspace
317
+ # Inside container execution, scripts/send-jules-impact.py should exist in workspace
318
+ if [ -f "scripts/send-jules-impact.py" ]; then
319
+ echo "Executing send-jules-impact.py from current workspace."
320
+ export PYTHONPATH="cli:$PYTHONPATH"
321
+ python3 scripts/send-jules-impact.py
322
+ else
323
+ echo "⚠️ Skipping: send-jules-impact.py script not found."
324
+ fi
331
325
  fi
332
326
  shell: bash
333
327
 
334
328
  - name: Update Impact Analysis Feedback (Final Result)
335
329
  if: always()
336
- uses: ./mcp/actions/update-pr-comment
330
+ uses: actions/github-script@v8 # nosemgrep: yaml.github-actions.security.github-actions-mutable-action-tag.github-actions-mutable-action-tag
331
+ env:
332
+ INPUT_STATUS_LINE: '✅ **Impact Analysis Complete**'
333
+ INPUT_IMPACT_BODY: ${{ env.IMPACT_BODY }}
337
334
  with:
338
- github_token: ${{ inputs.github_token }}
339
- status_line: '✅ **Impact Analysis Complete**'
340
- impact_body: ${{ env.IMPACT_BODY }}
335
+ github-token: ${{ inputs.github_token }}
336
+ script: |
337
+ const owner = context.repo.owner;
338
+ const repo = context.repo.repo;
339
+ const branchName = context.ref.replace('refs/heads/', '');
340
+
341
+ const pstTime = new Date().toLocaleString('en-US', {
342
+ timeZone: 'America/Los_Angeles',
343
+ dateStyle: 'medium',
344
+ timeStyle: 'short'
345
+ });
346
+
347
+ if (branchName === 'main') return;
348
+
349
+ const pullRequests = await github.paginate(github.rest.pulls.list, {
350
+ owner,
351
+ repo,
352
+ state: 'open'
353
+ });
354
+ const matchingPRs = pullRequests.filter(pr => pr.head.ref === branchName);
355
+
356
+ const statusLine = process.env.INPUT_STATUS_LINE;
357
+ let impactBodyText = (process.env.INPUT_IMPACT_BODY || '')
358
+ .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '[REMOVED SCRIPT]');
359
+
360
+ for (const pr of matchingPRs) {
361
+ const commentTag = `<!-- impact-analysis-comment-${branchName} -->`;
362
+ let bodyParts = [
363
+ `🚀 **Impact Analysis Details** (Last updated: ${pstTime} PST)`,
364
+ '',
365
+ statusLine,
366
+ `- **Commit SHA:** \`${process.env.GITHUB_SHA.slice(0, 7)}\``,
367
+ `- [Link to artifacts](https://github.com/${owner}/${repo}/actions/runs/${context.runId})`,
368
+ ''
369
+ ];
370
+
371
+ if (impactBodyText) {
372
+ bodyParts.push(impactBodyText, '');
373
+ }
374
+
375
+ const MAX_LENGTH = 65536;
376
+ const truncationNotice = '\n\n... (truncated due to GitHub comment size limits)\n';
377
+ let currentContent = bodyParts.join('\n');
378
+ let projectedLength = currentContent.length + commentTag.length + 1;
379
+
380
+ if (projectedLength > MAX_LENGTH) {
381
+ const availableLength = MAX_LENGTH - commentTag.length - truncationNotice.length - 2;
382
+ let safeContent = currentContent.slice(0, availableLength);
383
+ let lastNewline = safeContent.lastIndexOf('\n');
384
+ if (lastNewline > availableLength * 0.9) {
385
+ safeContent = safeContent.slice(0, lastNewline);
386
+ }
387
+ bodyParts = [safeContent, truncationNotice];
388
+ }
389
+
390
+ bodyParts.push(commentTag);
391
+ const body = bodyParts.join('\n');
392
+
393
+ const comments = await github.paginate(github.rest.issues.listComments, {
394
+ owner,
395
+ repo,
396
+ issue_number: pr.number,
397
+ });
398
+
399
+ const existingComment = comments.find(c => c.body.includes(commentTag));
400
+
401
+ if (existingComment) {
402
+ await github.rest.issues.updateComment({ owner, repo, comment_id: existingComment.id, body });
403
+ } else {
404
+ await github.rest.issues.createComment({ issue_number: pr.number, owner, repo, body });
405
+ }
406
+ }
341
407
 
342
408
  - name: Merge AI Logs into Artifacts
343
409
  if: always()
@@ -372,6 +438,10 @@ runs:
372
438
  env:
373
439
  GITHUB_TOKEN: ${{ inputs.github_token }}
374
440
  run: |
441
+ # Inject custom CLI path for td-cli resolution
442
+ PYTHON_SCRIPTS_PATH=$(python3 -c "import sysconfig; print(sysconfig.get_path('scripts'))")
443
+ export PATH="$PYTHON_SCRIPTS_PATH:$HOME/.local/bin:/github/home/.local/bin:$PATH"
444
+
375
445
  # Resolve CLI dir for PYTHONPATH
376
446
  if [ -d "cli" ]; then
377
447
  export PYTHONPATH="cli:$PYTHONPATH"
@@ -10,10 +10,10 @@ inputs:
10
10
  runs:
11
11
  using: composite
12
12
  steps:
13
- - uses: ./mcp/actions/setup
13
+ - uses: arii/boomtick/mcp/actions/setup@main
14
14
 
15
15
  - name: Run Project Gate
16
- uses: ./mcp/actions/run-project-gate
16
+ uses: arii/boomtick/mcp/actions/run-project-gate@main
17
17
  with:
18
18
  target: ${{ inputs.target }}
19
19
  github_token: ${{ inputs.github_token }}
@@ -8,7 +8,7 @@ runs:
8
8
  shell: bash
9
9
 
10
10
  - name: Setup Workspace
11
- uses: ./.github/actions/setup-workspace
11
+ uses: arii/boomtick/.github/actions/setup-workspace@main
12
12
 
13
13
  - name: Verify setup
14
14
  run: td-cli doctor
@@ -11,7 +11,7 @@ inputs:
11
11
  runs:
12
12
  using: composite
13
13
  steps:
14
- - uses: ./mcp/actions/setup
14
+ - uses: arii/boomtick/mcp/actions/setup@main
15
15
 
16
16
  - name: pnpm install
17
17
  run: pnpm install --frozen-lockfile --prefer-offline
@@ -1,4 +1,31 @@
1
1
  import { runCommand } from "../lib/shell.js";
2
+ import { execSync } from "child_process";
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+ export const loadStandaloneAgentContext = (repoRoot = process.cwd()) => {
6
+ const configPath = path.join(repoRoot, "project_config.json");
7
+ let config = {};
8
+ if (fs.existsSync(configPath)) {
9
+ try {
10
+ config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
11
+ }
12
+ catch (e) {
13
+ console.warn(`[MCP Warning] Failed to parse ${configPath}:`, e);
14
+ }
15
+ }
16
+ let gitCommit = "unknown";
17
+ try {
18
+ gitCommit = execSync("git rev-parse HEAD", { cwd: repoRoot, encoding: "utf-8" }).trim();
19
+ }
20
+ catch {
21
+ // Fallback if git is unavailable (e.g. Docker container without git)
22
+ }
23
+ return {
24
+ packageName: config.packageName ?? "boomtick",
25
+ gitCommit,
26
+ config,
27
+ };
28
+ };
2
29
  function tryParseJson(text) {
3
30
  try {
4
31
  return JSON.parse(text);