@weareikko/code-review 0.8.3 → 0.8.4

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.
package/README.md CHANGED
@@ -110,7 +110,7 @@ jobs:
110
110
  steps:
111
111
  # Checkout (full history) is bundled — no separate checkout step needed.
112
112
  # Opt out with `checkout: false` if your job already checked out the code.
113
- - uses: weareikko/code-review@0.8.2 # pin to a release tag
113
+ - uses: weareikko/code-review@0.8 # moving minor tag — auto patch updates (see Pinning below)
114
114
  with:
115
115
  model: anthropic/claude-sonnet-4-5
116
116
  api-key: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -122,6 +122,13 @@ Inputs: `model` (required), `api-key`, `github-token` (default `${{ github.token
122
122
 
123
123
  Because the composite action references your secrets directly (`${{ secrets.ANTHROPIC_API_KEY }}`), it works from **any** repository, including consumers in a different organization from this one.
124
124
 
125
+ > **Pinning the ref.** Two moving tags are maintained, each re-pointed to the latest release it covers:
126
+ >
127
+ > - `@0.8` — **minor series**: newest `0.8.x`, patches only. Because a `0.x` minor bump marks a breaking change, this is the non-breaking channel and the recommended pin while the project is pre-1.0.
128
+ > - `@0` — **major series**: newest stable release. **Caveat:** in 0.x a minor bump _is_ a breaking change, so `@0` may advance across breaking releases (`0.8 → 0.9`); it becomes a true semver compatibility boundary only once `1.0` ships.
129
+ >
130
+ > For a frozen build, pin an exact patch (`@0.8.3`) or a commit SHA (immutable; strongest supply-chain posture); to track the tip, use `@main`. GitHub `uses:` refs do not support wildcards, so `@0.8.x` is not valid — use a moving tag instead.
131
+
125
132
  ### Reusable workflow (same org/enterprise)
126
133
 
127
134
  The bundled reusable workflow lets a caller enable reviews with no `steps:` of its own — it checks out the code, installs the CLI, and runs the review for you:
@@ -137,7 +144,7 @@ permissions:
137
144
 
138
145
  jobs:
139
146
  review:
140
- uses: weareikko/code-review/.github/workflows/code-review.yml@0.8.2 # pin to a release tag
147
+ uses: weareikko/code-review/.github/workflows/code-review.yml@0.8 # moving minor tag — auto patch updates
141
148
  secrets: inherit
142
149
  ```
143
150
 
@@ -512,7 +512,12 @@ function buildSizeNoticeBlock(notice) {
512
512
  if (sizeSkippedFiles.length > 0) {
513
513
  const fileList = sizeSkippedFiles.map((file) => `- \`${file.path}\` (${formatChars(file.chars)})`).join("\n");
514
514
  const cov = notice.coverage;
515
- const coverageLine = cov && cov.totalLines > 0 ? `> **Partial review — ~${Math.round(cov.reviewedLines / cov.totalLines * 100)}% of changed lines reviewed** (${cov.reviewedLines} of ${cov.totalLines}). The files below were NOT reviewed; their absence from the findings is not a clean bill of health.` : `> **${sizeSkippedFiles.length} file(s) were not reviewed** — the diff exceeded the size budget, so these files were dropped from the review:`;
515
+ const retrieved = notice.retrieved === true;
516
+ let coverageLine;
517
+ if (cov && cov.totalLines > 0) {
518
+ const pct = Math.round(cov.reviewedLines / cov.totalLines * 100);
519
+ coverageLine = retrieved ? `> **Large diff — ~${pct}% of changed lines fit the inline budget** (${cov.reviewedLines} of ${cov.totalLines}). The files below exceeded it and were staged for on-demand retrieval; see the review summary for which were read. Absence from the findings is not a clean bill of health.` : `> **Partial review — ~${pct}% of changed lines reviewed** (${cov.reviewedLines} of ${cov.totalLines}). The files below were NOT reviewed; their absence from the findings is not a clean bill of health.`;
520
+ } else coverageLine = retrieved ? `> **${sizeSkippedFiles.length} file(s) exceeded the size budget** — their diffs were staged for on-demand retrieval; see the review summary for which were read:` : `> **${sizeSkippedFiles.length} file(s) were not reviewed** — the diff exceeded the size budget, so these files were dropped from the review:`;
516
521
  blocks.push([
517
522
  `> [!WARNING]`,
518
523
  coverageLine,
@@ -543,7 +548,7 @@ function buildSummaryBody(summary, costFooter, options = {}) {
543
548
  return `${withFooter}\n\n${buildSummaryHistoryBlock(historyEntries)}`;
544
549
  }
545
550
  function buildReviewedCommitFooter(commitSha) {
546
- return `Reviewed by ${PRODUCT_LINK} v0.8.3 for commit ${commitSha}.`;
551
+ return `Reviewed by ${PRODUCT_LINK} v0.8.4 for commit ${commitSha}.`;
547
552
  }
548
553
  function extractReviewedCommitSha(body) {
549
554
  return REVIEWED_COMMIT_FOOTER_PATTERN.exec(body)?.[1] ?? null;
@@ -936,6 +941,7 @@ var BOOLEAN_FLAGS = new Set([
936
941
  "no-summary",
937
942
  "force-review",
938
943
  "retrieve-skipped",
944
+ "no-retrieve-skipped",
939
945
  "verbose",
940
946
  "help",
941
947
  "version"
@@ -994,6 +1000,22 @@ function resolvePostSummary(args, env) {
994
1000
  }
995
1001
  return true;
996
1002
  }
1003
+ function resolveRetrieveSkipped(args, env) {
1004
+ if (args.noRetrieveSkipped === true) return false;
1005
+ if (args.retrieveSkipped === true) return true;
1006
+ const raw = env.CODE_REVIEW_RETRIEVE_SKIPPED;
1007
+ if (typeof raw === "string") {
1008
+ const normalized = raw.trim().toLowerCase();
1009
+ if ([
1010
+ "0",
1011
+ "false",
1012
+ "no",
1013
+ "off"
1014
+ ].includes(normalized)) return false;
1015
+ if (normalized.length > 0) return true;
1016
+ }
1017
+ return true;
1018
+ }
997
1019
  function normalizeChoice(value) {
998
1020
  return String(value ?? "").trim().toLowerCase();
999
1021
  }
@@ -1197,7 +1219,7 @@ function resolveConfig(argv = process.argv.slice(2), env = process.env) {
1197
1219
  maxDiffChars,
1198
1220
  decomposeHintLines,
1199
1221
  diffContext,
1200
- retrieveSkipped: toBoolean(args.retrieveSkipped) || toBoolean(env.CODE_REVIEW_RETRIEVE_SKIPPED),
1222
+ retrieveSkipped: resolveRetrieveSkipped(args, env),
1201
1223
  reviewFile: String(args.reviewFile ?? "code-review.md"),
1202
1224
  output: String(args.output ?? "review-comments.json"),
1203
1225
  dryRun: toBoolean(args.dryRun),
@@ -3788,10 +3810,10 @@ function buildUserPrompt(diff, skippedFiles = [], commitLog, priorThreads, inten
3788
3810
  if (commitLog?.trim()) parts.push(`Commits in this MR (oldest first):\n<commits>\n${commitLog.trim()}\n</commits>`);
3789
3811
  parts.push(`Review this diff:\n<diff>\n${diff}\n</diff>`);
3790
3812
  if (retrievableSkipped && retrievableSkipped.length > 0) parts.push(renderRetrievableSkippedBlock(retrievableSkipped));
3791
- else if (skippedFiles.length > 0) parts.push(`<skipped_files>\n${skippedFiles.map((file) => `- ${file}`).join("\n")}\n</skipped_files>\nThe above files were not included because the diff exceeded the size limit. Mention them explicitly in your summary as not reviewed.`);
3813
+ else if (skippedFiles.length > 0) parts.push(`<skipped_files>\n${skippedFiles.map((file) => `- ${file}`).join("\n")}\n</skipped_files>\nThe above files were not included because the diff exceeded the size limit. They are already surfaced to the reader in the MR summary, so do not re-list them; just do not assume they are clean, since you did not see them.`);
3792
3814
  if (coverage && coverage.totalLines > 0 && coverage.reviewedLines < coverage.totalLines) {
3793
3815
  const pct = Math.round(coverage.reviewedLines / coverage.totalLines * 100);
3794
- parts.push(`<coverage>You reviewed ${coverage.reviewedLines} of ${coverage.totalLines} changed lines (~${pct}%). The rest were dropped for the size budget and you did NOT see them. State this partial coverage in your summary and do not imply the unreviewed files are clean — their absence from your findings is not a clearance.</coverage>`);
3816
+ parts.push(`<coverage>You reviewed ${coverage.reviewedLines} of ${coverage.totalLines} changed lines (~${pct}%). The rest were dropped for the size budget and you did NOT see them. The MR summary already reports this partial coverage to the reader, so do not restate it; just do not imply the unreviewed files are clean — their absence from your findings is not a clearance.</coverage>`);
3795
3817
  }
3796
3818
  if (priorThreads && priorThreads.length > 0) {
3797
3819
  const block = renderPriorThreadsBlock(priorThreads);
@@ -4023,13 +4045,14 @@ async function runReview(config, options) {
4023
4045
  reviewedLines: reviewedChangedLines,
4024
4046
  totalLines: reviewedChangedLines + skippedChangedLines
4025
4047
  } : void 0;
4048
+ const retrievableSkipped = config.retrieveSkipped && sizeSkippedSections.length > 0 ? await writeSkippedDiffs(cwd, sizeSkippedSections) : [];
4049
+ if (retrievableSkipped.length > 0) logger.info(`Staged ${retrievableSkipped.length} dropped-file diff(s) on disk for retrieval.`);
4026
4050
  const sizeNotice = {
4027
4051
  sizeSkippedFiles,
4028
4052
  decomposeHint,
4029
- coverage
4053
+ coverage,
4054
+ retrieved: retrievableSkipped.length > 0
4030
4055
  };
4031
- const retrievableSkipped = config.retrieveSkipped && sizeSkippedSections.length > 0 ? await writeSkippedDiffs(cwd, sizeSkippedSections) : [];
4032
- if (retrievableSkipped.length > 0) logger.info(`Staged ${retrievableSkipped.length} dropped-file diff(s) on disk for retrieval.`);
4033
4056
  const context = await loadReviewContext(cwd, config.skills, (msg) => logger.warn(msg), { refreshGitSkills: config.refreshGitSkills });
4034
4057
  const systemPrompt = buildJSONSystemPrompt(context, minSeverity);
4035
4058
  const userPrompt = buildUserPrompt(diff, skippedFiles, options.commitLog, options.priorThreads, options.intent, coverage, retrievableSkipped);
@@ -4909,7 +4932,7 @@ async function loadDefaultRuntime() {
4909
4932
  const [sdkNode, resources, semconv] = modules;
4910
4933
  const serviceResource = resources.resourceFromAttributes({
4911
4934
  [semconv.ATTR_SERVICE_NAME ?? "service.name"]: SERVICE_NAME,
4912
- [semconv.ATTR_SERVICE_VERSION ?? "service.version"]: "0.8.3"
4935
+ [semconv.ATTR_SERVICE_VERSION ?? "service.version"]: "0.8.4"
4913
4936
  });
4914
4937
  process.env.OTEL_METRICS_EXPORTER = process.env.OTEL_METRICS_EXPORTER ?? "otlp";
4915
4938
  process.env.OTEL_LOGS_EXPORTER = process.env.OTEL_LOGS_EXPORTER ?? "otlp";
@@ -5341,7 +5364,7 @@ function boldCommentTitle(body) {
5341
5364
  */
5342
5365
  function buildCommentBody(body, commitSha, confidence) {
5343
5366
  const confidenceLine = `_Confidence: ${confidence}._`;
5344
- const footer = `<sub>Reviewed by ${PRODUCT_LINK} v0.8.3 for commit ${commitSha}.</sub>`;
5367
+ const footer = `<sub>Reviewed by ${PRODUCT_LINK} v0.8.4 for commit ${commitSha}.</sub>`;
5345
5368
  return `${boldCommentTitle(body.trim())}\n\n${confidenceLine}\n\n---\n\n${footer}`;
5346
5369
  }
5347
5370
  function buildPayload(comment, body, refs, resolved) {
@@ -6066,9 +6089,10 @@ Options:
6066
6089
  context aids reasoning but inflates tokens and fits fewer files in
6067
6090
  the budget; less fits more. 0 = built-in default (20).
6068
6091
  (env: CODE_REVIEW_DIFF_CONTEXT)
6069
- --retrieve-skipped Stage diffs for files dropped by the size budget on disk so the
6070
- reviewer can read them on demand instead of losing them.
6071
- (env: CODE_REVIEW_RETRIEVE_SKIPPED=true)
6092
+ --no-retrieve-skipped Disable staging diffs for files dropped by the size budget on disk.
6093
+ Retrieval is on by default: dropped diffs are staged so the reviewer
6094
+ can read them on demand instead of losing them.
6095
+ (env: CODE_REVIEW_RETRIEVE_SKIPPED=0)
6072
6096
  --min-severity <level> info, warn, or critical (default: info)
6073
6097
  --thinking <level> off, minimal, low, medium, high, or xhigh (default: off).
6074
6098
  Higher levels add billable thinking tokens at the model output rate.
@@ -6428,10 +6452,10 @@ async function main(argv = process.argv.slice(2)) {
6428
6452
  return;
6429
6453
  }
6430
6454
  if (argv.includes("--version") || argv.includes("-v")) {
6431
- console.log("0.8.3");
6455
+ console.log("0.8.4");
6432
6456
  return;
6433
6457
  }
6434
- process.stderr.write(`[code-review] @weareikko/code-review v0.8.3\n`);
6458
+ process.stderr.write(`[code-review] @weareikko/code-review v0.8.4\n`);
6435
6459
  assertNodeVersion();
6436
6460
  applyCodeReviewEnvPrefix();
6437
6461
  applyDefaultCacheRetention();
@@ -6454,4 +6478,4 @@ if (isDirectRun()) main().catch((error) => {
6454
6478
  //#endregion
6455
6479
  export { normalizeBody as $, SUMMARY_HISTORY_END as A, buildSummaryHistoryEntries as B, createDiagnosticContext as C, traceDiagnosticPhase as D, traceDiagnostic as E, SUMMARY_MARKER as F, findExistingSummaryNoteId as G, extractSummaryHistoryEntries as H, buildArchivedSummaryEntry as I, upsertSummaryNote as J, stripSummaryHistory as K, buildReviewedCommitFooter as L, SUMMARY_HISTORY_ENTRY_START as M, SUMMARY_HISTORY_LIMIT as N, normalizeSeverity as O, SUMMARY_HISTORY_START as P, fingerprints as Q, buildSizeNoticeBlock as R, DIAGNOSTIC_CHANNEL_PREFIX as S, diagnosticChannels as T, findExistingReviewedCommitSha as U, extractReviewedCommitSha as V, findExistingSummaryNote as W, extractDiffHunkContext as X, appendFingerprintMarkers as Y, extractExistingFingerprints as Z, resolveNpmSkillDir as _, main as a, parseReviewMarkdownWithWarnings as b, buildGeneratedComments as c, startOtelBridge as d, sha256 as et, filterDiff as f, parseSkillSpec as g, loadNamedSkill as h, formatUsageLine as i, SUMMARY_HISTORY_ENTRY_END as j, toGitLabReviewSeverity as k, buildPayload as l, gitSkillCacheKey as m, formatPerModelUsage as n, run as o, runReview as p, stripSummaryMarker as q, formatSkillsFooter as r, withHttpStamping as s, countPostedBySeverity as t, isOtelEnabled as u, resolveSkillCacheDir as v, createDiagnosticRunId as w, DIAGNOSTIC_CHANNEL_NAMES as x, parseReviewMarkdown as y, buildSummaryBody as z };
6456
6480
 
6457
- //# sourceMappingURL=cli-CICuhytH.js.map
6481
+ //# sourceMappingURL=cli-FDpPZaNn.js.map