@clearlydev/nx-archweave 0.2.1 → 0.2.2

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.
@@ -272,13 +272,14 @@ function renderConcurrencyBlock() {
272
272
  " cancel-in-progress: false"
273
273
  ].join("\n");
274
274
  }
275
- function renderPermissionsBlock() {
276
- return ["permissions:", " contents: read", " pull-requests: write", " id-token: write"].join("\n");
275
+ var REVIEW_GATE_CONDITION = "steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'";
276
+ function renderReviewPermissions(idToken) {
277
+ return ["permissions:", " contents: read", " pull-requests: write", ...idToken ? [" id-token: write"] : []].join("\n");
277
278
  }
278
279
  function renderCheckoutStep(gateCondition, extraWith = []) {
279
280
  return [
280
281
  "- name: Checkout repository",
281
- ` if: ${gateCondition}`,
282
+ ...gateCondition === void 0 ? [] : [` if: ${gateCondition}`],
282
283
  ` uses: ${pinnedUses("actions/checkout")}`,
283
284
  " with:",
284
285
  ...extraWith.map((line) => ` ${line}`),
@@ -320,10 +321,46 @@ function renderRoundGateStep(maxRounds) {
320
321
  " fi"
321
322
  ].join("\n");
322
323
  }
324
+ var JUDGE_CONDITION = "steps.ai-review-result.outputs.run == 'true'";
325
+ function renderAiReviewResultStep() {
326
+ return [
327
+ "- name: Check the AI review result",
328
+ " id: ai-review-result",
329
+ " env:",
330
+ " AI_REVIEW_RESULT: ${{ needs.ai-review.result }}",
331
+ " REVIEW_ENABLED: ${{ needs.ai-review.outputs.enabled }}",
332
+ " REVIEW_ALLOWED: ${{ needs.ai-review.outputs.allowed }}",
333
+ " LAST_COMMENT_ID: ${{ needs.ai-review.outputs.last-comment-id }}",
334
+ " run: |",
335
+ ' if [ "$AI_REVIEW_RESULT" != success ]; then',
336
+ ` echo "::error title=AI review did not succeed::The AI review job ended with '$AI_REVIEW_RESULT'."`,
337
+ " exit 1",
338
+ " fi",
339
+ ' case "$REVIEW_ENABLED/$REVIEW_ALLOWED" in',
340
+ " false/* | true/false)",
341
+ ' echo "The AI review did not run (no secret, or the round limit) - nothing to judge."',
342
+ ' echo "run=false" >> "$GITHUB_OUTPUT"',
343
+ " exit 0",
344
+ " ;;",
345
+ " true/true)",
346
+ ' case "$LAST_COMMENT_ID" in',
347
+ " '' | *[!0-9]*) ;;",
348
+ " *)",
349
+ ' echo "run=true" >> "$GITHUB_OUTPUT"',
350
+ " exit 0",
351
+ " ;;",
352
+ " esac",
353
+ " ;;",
354
+ " esac",
355
+ ` echo "::error title=Review verdict not computed::The AI review job's results did not reach this job, so no verdict can be computed. Re-run all jobs."`,
356
+ " exit 1"
357
+ ].join("\n");
358
+ }
323
359
  function renderVerdictGateStep(maxRounds, locale) {
324
360
  return [
325
361
  "- name: Compute review verdict",
326
- " if: steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'",
362
+ " id: verdict",
363
+ ` if: ${JUDGE_CONDITION}`,
327
364
  " env:",
328
365
  " GH_TOKEN: ${{ github.token }}",
329
366
  " GITHUB_REPOSITORY: ${{ github.repository }}",
@@ -331,7 +368,8 @@ function renderVerdictGateStep(maxRounds, locale) {
331
368
  ` ARCHWEAVE_MAX_ROUNDS: '${maxRounds}'`,
332
369
  ` ARCHWEAVE_LOCALE: '${locale}'`,
333
370
  " ARCHWEAVE_HEAD_SHA: ${{ github.event.pull_request.head.sha }}",
334
- " ARCHWEAVE_ROUND_AFTER_ID: ${{ steps.round-gate.outputs.last-comment-id }}",
371
+ " ARCHWEAVE_ROUND_AFTER_ID: ${{ needs.ai-review.outputs.last-comment-id }}",
372
+ " ARCHWEAVE_VERDICT_OUTPUT: 'github-output'",
335
373
  " run: |",
336
374
  " if [ -x node_modules/.bin/archweave-review-verdict ]; then",
337
375
  " node_modules/.bin/archweave-review-verdict",
@@ -340,16 +378,46 @@ function renderVerdictGateStep(maxRounds, locale) {
340
378
  " fi"
341
379
  ].join("\n");
342
380
  }
381
+ function renderBlockStep() {
382
+ return [
383
+ "- name: Fail on a blocking verdict",
384
+ " if: steps.verdict.outputs.blocked == 'true'",
385
+ " run: |",
386
+ ' echo "The review verdict is BLOCK - see the verdict comment on this pull request."',
387
+ " exit 1"
388
+ ].join("\n");
389
+ }
390
+ function renderVerdictCommentStep() {
391
+ return [
392
+ "- name: Post review verdict",
393
+ " env:",
394
+ " GH_TOKEN: ${{ github.token }}",
395
+ " REPOSITORY: ${{ github.repository }}",
396
+ " PR_NUMBER: ${{ github.event.pull_request.number }}",
397
+ " VERDICT_BODY: ${{ needs.review.outputs.comment-body }}",
398
+ " PREVIOUS_ID: ${{ needs.review.outputs.previous-comment-id }}",
399
+ " run: |",
400
+ ` payload=$(jq -n --arg body "$VERDICT_BODY" '{body: $body}')`,
401
+ ' case "$PREVIOUS_ID" in',
402
+ " ''|*[!0-9]*) PREVIOUS_ID= ;;",
403
+ " esac",
404
+ ` if [ -n "$PREVIOUS_ID" ] && printf '%s' "$payload" | gh api -X PATCH "repos/$REPOSITORY/issues/comments/$PREVIOUS_ID" --input - > /dev/null; then`,
405
+ " exit 0",
406
+ " fi",
407
+ ` printf '%s' "$payload" | gh api -X POST "repos/$REPOSITORY/issues/$PR_NUMBER/comments" --input - > /dev/null \\`,
408
+ ' || echo "Could not post the verdict comment (continuing)."'
409
+ ].join("\n");
410
+ }
343
411
  var SETUP_NODE_VERSION = "22";
344
412
  var FALLBACK_PNPM_VERSION = "10";
345
413
  var INSTALL_LINES = {
346
- pnpm: [" pnpm install --frozen-lockfile"],
347
- npm: [" npm ci"],
414
+ pnpm: [" pnpm install --frozen-lockfile --ignore-scripts"],
415
+ npm: [" npm ci --ignore-scripts"],
348
416
  yarn: [
349
417
  " corepack enable yarn",
350
- ' if [ "$(yarn --version | cut -d. -f1)" -ge 2 ]; then yarn install --immutable; else yarn install --frozen-lockfile; fi'
418
+ ' if [ "$(yarn --version | cut -d. -f1)" -ge 2 ]; then YARN_ENABLE_SCRIPTS=false yarn install --immutable --mode=skip-build; else yarn install --frozen-lockfile --ignore-scripts; fi'
351
419
  ],
352
- bun: [" bun install --frozen-lockfile"]
420
+ bun: [" bun install --frozen-lockfile --ignore-scripts"]
353
421
  };
354
422
  function renderPnpmVersionStep(gate) {
355
423
  return [
@@ -365,7 +433,7 @@ function renderPnpmVersionStep(gate) {
365
433
  ].join("\n");
366
434
  }
367
435
  function renderWorkspaceSetupSteps(packageManager) {
368
- const gate = " if: steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'";
436
+ const gate = ` if: ${JUDGE_CONDITION}`;
369
437
  const steps = [];
370
438
  if (packageManager === "pnpm") {
371
439
  steps.push(renderPnpmVersionStep(gate));
@@ -400,6 +468,60 @@ function renderWorkspaceSetupSteps(packageManager) {
400
468
  ].join("\n"));
401
469
  return steps.join("\n\n");
402
470
  }
471
+ function renderReviewWorkflow(input, parts) {
472
+ const aiReviewSteps = [renderSecretGateStep(parts.secretName), renderRoundGateStep(input.maxRounds), ...parts.reviewSteps];
473
+ const reviewSteps = [
474
+ renderAiReviewResultStep(),
475
+ renderCheckoutStep(JUDGE_CONDITION),
476
+ renderWorkspaceSetupSteps(input.packageManager),
477
+ renderVerdictGateStep(input.maxRounds, input.locale),
478
+ renderBlockStep()
479
+ ];
480
+ return [
481
+ `name: ${parts.name}`,
482
+ "",
483
+ renderTriggerBlock(),
484
+ "",
485
+ renderConcurrencyBlock(),
486
+ "",
487
+ "permissions: {}",
488
+ "",
489
+ "jobs:",
490
+ " ai-review:",
491
+ " runs-on: ubuntu-latest",
492
+ indentBlock(renderReviewPermissions(parts.idToken), 4),
493
+ " outputs:",
494
+ " enabled: ${{ steps.secret-gate.outputs.enabled }}",
495
+ " allowed: ${{ steps.round-gate.outputs.allowed }}",
496
+ " last-comment-id: ${{ steps.round-gate.outputs.last-comment-id }}",
497
+ " steps:",
498
+ indentBlock(aiReviewSteps.join("\n\n"), 6),
499
+ "",
500
+ " review:",
501
+ " needs: ai-review",
502
+ " if: always()",
503
+ " runs-on: ubuntu-latest",
504
+ " permissions:",
505
+ " contents: read",
506
+ " pull-requests: read",
507
+ " outputs:",
508
+ " comment-body: ${{ steps.verdict.outputs.comment-body }}",
509
+ " previous-comment-id: ${{ steps.verdict.outputs.previous-comment-id }}",
510
+ " steps:",
511
+ indentBlock(reviewSteps.join("\n\n"), 6),
512
+ "",
513
+ " review-comment:",
514
+ " needs: review",
515
+ // Runs after a BLOCK failed the review job, too: the comment explains the red check.
516
+ " if: ${{ !cancelled() && needs.review.outputs.comment-body != '' }}",
517
+ " runs-on: ubuntu-latest",
518
+ " permissions:",
519
+ " pull-requests: write",
520
+ " steps:",
521
+ indentBlock(renderVerdictCommentStep(), 6),
522
+ ""
523
+ ].join("\n");
524
+ }
403
525
 
404
526
  // ../template-engine/dist/review/claude/claude-provider.js
405
527
  var SECRET_NAME = "CLAUDE_CODE_OAUTH_TOKEN";
@@ -432,40 +554,26 @@ function composePrompt(input) {
432
554
  return sections.join("\n\n---\n\n");
433
555
  }
434
556
  function buildWorkflowYaml(input) {
435
- const steps = [
436
- renderSecretGateStep(SECRET_NAME),
437
- renderRoundGateStep(input.maxRounds),
438
- renderCheckoutStep("steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'"),
439
- [
440
- "- name: Run Claude review",
441
- " if: steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'",
442
- ` uses: ${pinnedUses("anthropics/claude-code-action")}`,
443
- " with:",
444
- ` claude_code_oauth_token: \${{ secrets.${SECRET_NAME} }}`,
445
- " prompt: |",
446
- indentBlock(composePrompt(input), 6),
447
- " claude_args: |",
448
- ` --allowedTools "${ALLOWED_TOOLS}"`
449
- ].join("\n"),
450
- renderWorkspaceSetupSteps(input.packageManager),
451
- renderVerdictGateStep(input.maxRounds, input.locale)
452
- ];
453
- return [
454
- "name: Claude Code Review",
455
- "",
456
- renderTriggerBlock(),
457
- "",
458
- renderConcurrencyBlock(),
459
- "",
460
- renderPermissionsBlock(),
461
- "",
462
- "jobs:",
463
- " review:",
464
- " runs-on: ubuntu-latest",
465
- " steps:",
466
- indentBlock(steps.join("\n\n"), 6),
467
- ""
468
- ].join("\n");
557
+ return renderReviewWorkflow(input, {
558
+ name: "Claude Code Review",
559
+ secretName: SECRET_NAME,
560
+ // The Claude GitHub App signs in with the workflow's OIDC token (claude-code-action's FAQ).
561
+ idToken: true,
562
+ reviewSteps: [
563
+ renderCheckoutStep(REVIEW_GATE_CONDITION),
564
+ [
565
+ "- name: Run Claude review",
566
+ ` if: ${REVIEW_GATE_CONDITION}`,
567
+ ` uses: ${pinnedUses("anthropics/claude-code-action")}`,
568
+ " with:",
569
+ ` claude_code_oauth_token: \${{ secrets.${SECRET_NAME} }}`,
570
+ " prompt: |",
571
+ indentBlock(composePrompt(input), 6),
572
+ " claude_args: |",
573
+ ` --allowedTools "${ALLOWED_TOOLS}"`
574
+ ].join("\n")
575
+ ]
576
+ });
469
577
  }
470
578
  var claudeProvider = {
471
579
  id: "claude",
@@ -505,49 +613,39 @@ function composePrompt2(input) {
505
613
  return sections.join("\n\n---\n\n");
506
614
  }
507
615
  function buildWorkflowYaml2(input) {
508
- const gateCondition = "steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'";
509
- const steps = [
510
- renderSecretGateStep(SECRET_NAME2),
511
- renderRoundGateStep(input.maxRounds),
512
- renderCheckoutStep(gateCondition),
513
- [
514
- "- name: Install cursor-agent CLI",
515
- ` if: ${gateCondition}`,
516
- " run: |",
517
- " curl https://cursor.com/install -fsS | bash",
518
- ' echo "$HOME/.cursor/bin" >> "$GITHUB_PATH"'
519
- ].join("\n"),
520
- [
521
- "- name: Run Cursor review",
522
- ` if: ${gateCondition}`,
523
- " env:",
524
- ` CURSOR_API_KEY: \${{ secrets.${SECRET_NAME2} }}`,
525
- " GH_TOKEN: ${{ github.token }}",
526
- " run: |",
527
- ` agent -p "$(cat <<'${PROMPT_HEREDOC_DELIMITER}'`,
528
- indentBlock(composePrompt2(input), 4),
529
- ` ${PROMPT_HEREDOC_DELIMITER}`,
530
- ' )"'
531
- ].join("\n"),
532
- renderWorkspaceSetupSteps(input.packageManager),
533
- renderVerdictGateStep(input.maxRounds, input.locale)
534
- ];
535
- return [
536
- "name: Cursor Code Review",
537
- "",
538
- renderTriggerBlock(),
539
- "",
540
- renderConcurrencyBlock(),
541
- "",
542
- renderPermissionsBlock(),
543
- "",
544
- "jobs:",
545
- " review:",
546
- " runs-on: ubuntu-latest",
547
- " steps:",
548
- indentBlock(steps.join("\n\n"), 6),
549
- ""
550
- ].join("\n");
616
+ return renderReviewWorkflow(input, {
617
+ name: "Cursor Code Review",
618
+ secretName: SECRET_NAME2,
619
+ // An API key: the Cursor CLI needs no OIDC token.
620
+ idToken: false,
621
+ reviewSteps: [
622
+ renderCheckoutStep(REVIEW_GATE_CONDITION),
623
+ [
624
+ "- name: Install cursor-agent CLI",
625
+ ` if: ${REVIEW_GATE_CONDITION}`,
626
+ " run: |",
627
+ // HTTPS only, TLS 1.2 or newer. Cursor publishes no pinned version or checksum for
628
+ // this installer; docs/pr-review.md states what that leaves open.
629
+ " curl --proto '=https' --tlsv1.2 -fsS https://cursor.com/install | bash",
630
+ // The docs name ~/.cursor/bin; the installer currently links `agent` into ~/.local/bin.
631
+ // Both go on the PATH, so the next step finds it wherever the installer puts it.
632
+ ' echo "$HOME/.local/bin" >> "$GITHUB_PATH"',
633
+ ' echo "$HOME/.cursor/bin" >> "$GITHUB_PATH"'
634
+ ].join("\n"),
635
+ [
636
+ "- name: Run Cursor review",
637
+ ` if: ${REVIEW_GATE_CONDITION}`,
638
+ " env:",
639
+ ` CURSOR_API_KEY: \${{ secrets.${SECRET_NAME2} }}`,
640
+ " GH_TOKEN: ${{ github.token }}",
641
+ " run: |",
642
+ ` agent -p "$(cat <<'${PROMPT_HEREDOC_DELIMITER}'`,
643
+ indentBlock(composePrompt2(input), 4),
644
+ ` ${PROMPT_HEREDOC_DELIMITER}`,
645
+ ' )"'
646
+ ].join("\n")
647
+ ]
648
+ });
551
649
  }
552
650
  var cursorProvider = {
553
651
  id: "cursor",
@@ -586,40 +684,26 @@ function composePrompt3(input) {
586
684
  return sections.join("\n\n---\n\n");
587
685
  }
588
686
  function buildWorkflowYaml3(input) {
589
- const steps = [
590
- renderSecretGateStep(SECRET_NAME3),
591
- renderRoundGateStep(input.maxRounds),
592
- renderCheckoutStep("steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'"),
593
- [
594
- "- name: Run Gemini review",
595
- " if: steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'",
596
- ` uses: ${pinnedUses("google-github-actions/run-gemini-cli")}`,
597
- " env:",
598
- " GITHUB_TOKEN: ${{ github.token }}",
599
- " with:",
600
- ` gemini_api_key: \${{ secrets.${SECRET_NAME3} }}`,
601
- " prompt: |",
602
- indentBlock(composePrompt3(input), 6)
603
- ].join("\n"),
604
- renderWorkspaceSetupSteps(input.packageManager),
605
- renderVerdictGateStep(input.maxRounds, input.locale)
606
- ];
607
- return [
608
- "name: Gemini Code Review",
609
- "",
610
- renderTriggerBlock(),
611
- "",
612
- renderConcurrencyBlock(),
613
- "",
614
- renderPermissionsBlock(),
615
- "",
616
- "jobs:",
617
- " review:",
618
- " runs-on: ubuntu-latest",
619
- " steps:",
620
- indentBlock(steps.join("\n\n"), 6),
621
- ""
622
- ].join("\n");
687
+ return renderReviewWorkflow(input, {
688
+ name: "Gemini Code Review",
689
+ secretName: SECRET_NAME3,
690
+ // An API key: run-gemini-cli uses OIDC only for Google Cloud workload identity federation.
691
+ idToken: false,
692
+ reviewSteps: [
693
+ renderCheckoutStep(REVIEW_GATE_CONDITION),
694
+ [
695
+ "- name: Run Gemini review",
696
+ ` if: ${REVIEW_GATE_CONDITION}`,
697
+ ` uses: ${pinnedUses("google-github-actions/run-gemini-cli")}`,
698
+ " env:",
699
+ " GITHUB_TOKEN: ${{ github.token }}",
700
+ " with:",
701
+ ` gemini_api_key: \${{ secrets.${SECRET_NAME3} }}`,
702
+ " prompt: |",
703
+ indentBlock(composePrompt3(input), 6)
704
+ ].join("\n")
705
+ ]
706
+ });
623
707
  }
624
708
  var geminiProvider = {
625
709
  id: "gemini",
@@ -658,64 +742,49 @@ function composePrompt4(input) {
658
742
  return sections.join("\n\n---\n\n");
659
743
  }
660
744
  function buildWorkflowYaml4(input) {
661
- const gateCondition = "steps.secret-gate.outputs.enabled == 'true' && steps.round-gate.outputs.allowed == 'true'";
662
- const steps = [
663
- renderSecretGateStep(SECRET_NAME4),
664
- renderRoundGateStep(input.maxRounds),
665
- renderCheckoutStep(gateCondition, ["ref: refs/pull/${{ github.event.pull_request.number }}/merge"]),
666
- [
667
- "- name: Fetch base and head refs for the PR",
668
- ` if: ${gateCondition}`,
669
- " env:",
670
- " PR_BASE_REF: ${{ github.event.pull_request.base.ref }}",
671
- " PR_NUMBER: ${{ github.event.pull_request.number }}",
672
- " run: |",
673
- " # Explicit destinations: the sandboxed review step has no network, so both sides",
674
- " # of the diff must survive as stable local refs (FETCH_HEAD alone is ambiguous).",
675
- " git fetch --no-tags origin \\",
676
- ' "+refs/heads/$PR_BASE_REF:refs/remotes/origin/pr-base" \\',
677
- ' "+refs/pull/$PR_NUMBER/head:refs/remotes/origin/pr-head"'
678
- ].join("\n"),
679
- [
680
- "- name: Run Codex review",
681
- " id: codex-review",
682
- ` if: ${gateCondition}`,
683
- ` uses: ${pinnedUses("openai/codex-action")}`,
684
- " with:",
685
- ` openai-api-key: \${{ secrets.${SECRET_NAME4} }}`,
686
- ' permission-profile: ":read-only"',
687
- " prompt: |",
688
- indentBlock(composePrompt4(input), 6)
689
- ].join("\n"),
690
- [
691
- "- name: Post review comment",
692
- ` if: ${gateCondition}`,
693
- " env:",
694
- " GH_TOKEN: ${{ github.token }}",
695
- " PR_NUMBER: ${{ github.event.pull_request.number }}",
696
- " REVIEW_BODY: ${{ steps.codex-review.outputs.final-message }}",
697
- " run: |",
698
- ' printf %s "$REVIEW_BODY" | gh pr comment "$PR_NUMBER" --body-file -'
699
- ].join("\n"),
700
- renderWorkspaceSetupSteps(input.packageManager),
701
- renderVerdictGateStep(input.maxRounds, input.locale)
702
- ];
703
- return [
704
- "name: GPT Code Review",
705
- "",
706
- renderTriggerBlock(),
707
- "",
708
- renderConcurrencyBlock(),
709
- "",
710
- renderPermissionsBlock(),
711
- "",
712
- "jobs:",
713
- " review:",
714
- " runs-on: ubuntu-latest",
715
- " steps:",
716
- indentBlock(steps.join("\n\n"), 6),
717
- ""
718
- ].join("\n");
745
+ return renderReviewWorkflow(input, {
746
+ name: "GPT Code Review",
747
+ secretName: SECRET_NAME4,
748
+ // An API key: codex-action needs no OIDC token.
749
+ idToken: false,
750
+ reviewSteps: [
751
+ renderCheckoutStep(REVIEW_GATE_CONDITION, ["ref: refs/pull/${{ github.event.pull_request.number }}/merge"]),
752
+ [
753
+ "- name: Fetch base and head refs for the PR",
754
+ ` if: ${REVIEW_GATE_CONDITION}`,
755
+ " env:",
756
+ " PR_BASE_REF: ${{ github.event.pull_request.base.ref }}",
757
+ " PR_NUMBER: ${{ github.event.pull_request.number }}",
758
+ " run: |",
759
+ " # Explicit destinations: the sandboxed review step has no network, so both sides",
760
+ " # of the diff must survive as stable local refs (FETCH_HEAD alone is ambiguous).",
761
+ " git fetch --no-tags origin \\",
762
+ ' "+refs/heads/$PR_BASE_REF:refs/remotes/origin/pr-base" \\',
763
+ ' "+refs/pull/$PR_NUMBER/head:refs/remotes/origin/pr-head"'
764
+ ].join("\n"),
765
+ [
766
+ "- name: Run Codex review",
767
+ " id: codex-review",
768
+ ` if: ${REVIEW_GATE_CONDITION}`,
769
+ ` uses: ${pinnedUses("openai/codex-action")}`,
770
+ " with:",
771
+ ` openai-api-key: \${{ secrets.${SECRET_NAME4} }}`,
772
+ ' permission-profile: ":read-only"',
773
+ " prompt: |",
774
+ indentBlock(composePrompt4(input), 6)
775
+ ].join("\n"),
776
+ [
777
+ "- name: Post review comment",
778
+ ` if: ${REVIEW_GATE_CONDITION}`,
779
+ " env:",
780
+ " GH_TOKEN: ${{ github.token }}",
781
+ " PR_NUMBER: ${{ github.event.pull_request.number }}",
782
+ " REVIEW_BODY: ${{ steps.codex-review.outputs.final-message }}",
783
+ " run: |",
784
+ ' printf %s "$REVIEW_BODY" | gh pr comment "$PR_NUMBER" --body-file -'
785
+ ].join("\n")
786
+ ]
787
+ });
719
788
  }
720
789
  var gptProvider = {
721
790
  id: "gpt",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clearlydev/nx-archweave",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Nx generators that make a workspace ready to work on in one preset: FSD Lite structure with enforced module boundaries, AI agent rules, GitHub templates, and optional AI PR review (Claude, Gemini, GPT, Cursor)",
5
5
  "license": "MIT",
6
6
  "author": "clearlydev (https://github.com/clearlydev)",