Skip to content

Adopt the canonical pm-ops docstring gate and document all source declarations - #58

Merged
unbraind merged 2 commits into
mainfrom
docstring-gate-adoption
Aug 9, 2026
Merged

unbraind merged 2 commits into
mainfrom
docstring-gate-adoption

Conversation

@unbraind

@unbraind unbraind commented Aug 8, 2026 •

Copy link
Copy Markdown
Owner

Summary

Adopts the fleet's canonical pm-ops/docstrings analyzer (pm-ops@^2026.8.8) as a mandatory release gate, and documents every source declaration it requires. No docstring-gate fork is copied — the thin launcher imports analyzeDocstringCoverage from pm-ops/docstrings, so this repo shares the one lexer-backed policy instead of drifting another copy.

Before / after (canonical analyzer)

files declarations violations documented
before 2 37 34 8%
after 4 42 0 100%

npm run docstring → docstring-gate: 4 file(s), 42 declaration(s) documented.

Changes

  • scripts/docstring-gate.ts + scripts/script-launcher.ts: copied from pm-rl's reference adoption — a pure runGate(root) returning {exitCode, stdout, stderr} (assertable from a test) and a main(root) that writes the streams and sets process.exitCode (never process.exit).
  • package.json: pm-ops@^2026.8.8 added to devDependencies (build-time gate, not a runtime dependency); new docstring script inserted into release:check.
  • .github/workflows/ci.yml: a Verify complete docstring coverage step (plus a standalone Build step), placed before the coverage gate.
  • test/docstring-gate.test.ts: covers the clean path (real repo), the violation path (undocumented source), and the main/isMainInvocation/runIfMain entry points.
  • index.ts: meaningful JSDoc on all 34 previously-undocumented declarations (no identifier-restating filler).

Why not a fork

pm-changelog and pm-vcs each ship a 500-line docstring-gate.ts fork that pins typescript5 to dodge the TS7 scanner. pm-ops already solved that (it rescans template-substitution } and only treats / as regex in regex context), so copying a fork into more repos just creates more drift. pm-changelog passes its own fork inside release:check while the canonical analyzer finds 5 violations in it — a gate that passes while the stricter policy finds violations is not enforcing the policy it claims to.

Gates

npm run release:check is green end to end: typecheck → build → docstring → coverage (70/80/80 thresholds met) → audit:prod (0 vulns) → pack:dry-run → changelog:check.

pm item

Summary by Sourcery

Adopt the shared pm-ops docstring coverage analyzer as a mandatory release gate and document all relevant source declarations to satisfy it.

New Features:

  • Add a docstring gate script that launches the canonical pm-ops docstring analyzer against the repository.
  • Introduce a shared script launcher utility that standardizes main-module detection and gate result contracts across operational scripts.

Enhancements:

  • Add comprehensive JSDoc documentation to previously undocumented types, helpers, and operational logic in the main extension module.
  • Refine operational helpers around Linear integration with clearer contracts and behavior descriptions (errors, retries, provenance, mapping utilities).

Build:

  • Wire the docstring gate into npm scripts and the release:check pipeline, and add pm-ops as a dev dependency to supply the canonical analyzer.

CI:

  • Extend the CI workflow with explicit build and docstring coverage verification steps before the coverage gate.

Chores:

  • Record the associated pm work item in the agents history and issues tracking files.

Summary by cubic

Adopted the canonical pm-ops/docstrings analyzer as a required release/CI gate and documented all source declarations, reducing violations from 34 to 0. This standardizes docstring policy across repos and blocks releases with missing docs.

  • New Features

    • Thin launcher (scripts/docstring-gate.ts + scripts/script-launcher.ts) that imports analyzeDocstringCoverage from pm-ops/docstrings.
    • Added npm run docstring; wired into release:check and CI (after Build, before coverage); added pm-ops@^2026.8.8 as a dev dependency.
    • Tests for clean/violation paths and the main/isMainInvocation entry points.
    • Added meaningful JSDoc in index.ts; repo now reports full coverage.
    • Satisfies Linear issue pm-linear-085x.
  • Bug Fixes

    • Removed an unused isMainInvocation import in the gate script to clear a static analysis warning.

Written for commit 911cc77. Summary will update on new commits.

Review in cubic

…larations

Wire the fleet's canonical pm-ops/docstrings analyzer (pm-ops@^2026.8.8) into
pm-linear as a mandatory release gate via a thin scripts/docstring-gate.ts
launcher that imports analyzeDocstringCoverage, rather than copying a weaker
fork. Document every declaration the analyzer requires, driving violations from
34 to 0 (37 declarations -> 42 across 4 files).

- scripts/docstring-gate.ts + scripts/script-launcher.ts: copied from pm-rl's
  adoption (a pure runGate + a main that sets process.exitCode, never exits)
- pm-ops added to devDependencies; the `docstring` script is wired into both
  release:check and ci.yml (after Build, before the coverage gate)
- test/docstring-gate.test.ts: covers the clean path, the violation path, and
  the main/isMainInvocation entry points

Closes pm-linear-085x

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @unbraind, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@unbraind, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 7 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: af26b564-b78a-4a28-9300-399d24b60542

📥 Commits

Reviewing files that changed from the base of the PR and between eb8f69b and 911cc77.

📒 Files selected for processing (1)
  • scripts/docstring-gate.ts

Summary by CodeRabbit

  • New Features

    • Added automated documentation coverage validation for exported and public declarations.
    • Added clear reporting of undocumented items, including file, line, symbol, and reason.
    • Integrated documentation checks into release validation and continuous integration.
  • Documentation

    • Documented previously undocumented declarations throughout the command-line tooling.
  • Tests

    • Added coverage for successful and failing validation, command-line output, exit codes, and launcher behavior.

Walkthrough

The change adds a pm-ops/docstrings coverage gate, documents declarations in index.ts, adds launcher and gate tests, and runs the check in CI and release validation.

Changes

Docstring coverage enforcement

Layer / File(s) Summary
Gate foundation
scripts/script-launcher.ts, scripts/docstring-gate.ts
Added direct-invocation detection, argument forwarding, the GateResult contract, analyzer execution, violation reporting, and CLI result handling.
Declaration documentation
index.ts
Documented public models and executable declarations covering option parsing, Linear mappings, HTTP behavior, imports, exports, validation, and dry-run rendering.
Enforcement and validation
package.json, .github/workflows/ci.yml, test/docstring-gate.test.ts, .agents/pm/...
Added npm and CI checks, test coverage for clean and failing paths, and issue records for gate adoption and completion.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: adopting the canonical gate and documenting source declarations.
Description check ✅ Passed The description directly explains the analyzer adoption, documentation updates, integrations, tests, and validation results.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docstring-gate-adoption

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR introduces a canonical docstring coverage gate based on pm-ops/docstrings, wires it into CI and release checks, and adds JSDoc documentation for all required source declarations, along with tests and shared script-launcher utilities for gate scripts.

Sequence diagram for the new docstring gate script invocation

sequenceDiagram
  actor Developer
  participant Npm as npm_script_docstring
  participant Node as node_docstring_gate_ts
  participant Gate as runGate
  participant Analyzer as analyzeDocstringCoverage

  Developer->>Npm: npm run docstring
  Npm->>Node: node scripts/docstring-gate.ts
  Node->>Node: runIfMain(process.argv, import.meta.url, main, repoRoot)
  Node->>Node: isMainInvocation(process.argv, import.meta.url)
  Node-->>Node: true
  Node->>Gate: main(repoRoot)
  Gate->>Analyzer: analyzeDocstringCoverage({ root })
  Analyzer-->>Gate: report
  alt violations_present
    Gate-->>Node: GateResult{ exitCode:1, stderr:message }
  else no_violations
    Gate-->>Node: GateResult{ exitCode:0, stdout:summary }
  end
  Node->>Node: process.stdout.write(...)
  Node->>Node: process.stderr.write(...)
  Node->>Node: process.exitCode = exitCode
Loading

Flow diagram for updated release:check and CI gates

flowchart LR
  A[typecheck] --> B[build]
  B --> C[docstring]
  C --> D[coverage]
  D --> E[audit:prod]
  E --> F[pack:dry-run]
  F --> G[changelog:check]

  subgraph CI_workflow
    CI1[Type check] --> CI2[Build]
    CI2 --> CI3[Verify complete docstring coverage]
    CI3 --> CI4[Test with coverage gate]
  end
Loading

File-Level Changes

Change Details Files
Introduce a reusable script launcher and docstring gate CLI that wrap the canonical pm-ops/docstrings analyzer.
  • Add script-launcher utilities to detect direct module invocation, conditionally run a main function, and define a shared GateResult contract.
  • Implement scripts/docstring-gate.ts to call analyzeDocstringCoverage, format violations or success output, and set process.exitCode without exiting the process.
  • Export isMainInvocation from the gate script so tests can exercise the main-vs-import guard.
scripts/script-launcher.ts
scripts/docstring-gate.ts
Integrate the docstring gate into npm scripts, release checks, and CI workflow.
  • Add pm-ops as a devDependency and a new docstring npm script that runs the gate.
  • Update the release:check script to run the docstring gate between build and coverage gates.
  • Update CI workflow to add an explicit Build step and a Verify complete docstring coverage step before the coverage gate.
package.json
.github/workflows/ci.yml
package-lock.json
Add tests that cover the docstring gate behavior and script launcher entry points.
  • Create test/docstring-gate.test.ts to assert clean and violation paths via runGate, and to verify main writes to the correct streams and sets exit codes.
  • Test isMainInvocation and runIfMain behavior for matching and non-matching argv/moduleUrl combinations.
  • Ensure success-path main invocation on the real repository root is covered, including newline behavior.
test/docstring-gate.test.ts
Document previously-undocumented public and key internal declarations in index.ts to satisfy the canonical analyzer.
  • Add meaningful JSDoc for core error and exit-code handling types (EXIT_CODE, CommandError, AuthHttpError) and their behavior with pm-cli.
  • Document utility option readers, mapping helpers, provenance helpers, retry/backoff helpers, and network request functions to clarify behavior and invariants.
  • Add JSDoc for project/issue filtering types, import/export planning types, Linear team context resolution, label/cycle resolution, dynamic field application, mutation planning, credential masking and preflight, validation reporting, and dry-run rendering.
  • Ensure that all exported and significant internal declarations referenced by the analyzer have non-filler docstrings that explain intent and behavior.
index.ts
Record the pm item metadata for the work item associated with this change.
  • Add pm history and issue artifacts for pm-linear-085x to the .agents/pm tree.
.agents/pm/history/pm-linear-085x.jsonl
.agents/pm/issues/pm-linear-085x.toon

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@greptile-apps

greptile-apps Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

Greptile Summary

The PR adopts the canonical pm-ops/docstrings analyzer as a required release gate and documents the declarations it checks.

  • Adds a thin, testable docstring-gate launcher and shared script entry-point utilities.
  • Runs the gate during CI and release:check.
  • Adds declaration documentation throughout index.ts.
  • Removes the unused local isMainInvocation import while preserving its direct re-export.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
scripts/docstring-gate.ts Adds the canonical analyzer launcher; the follow-up correctly removes the unused local import without affecting the public re-export.
scripts/script-launcher.ts Adds reusable main-invocation detection and gate-result output handling.
test/docstring-gate.test.ts Tests clean and violating repositories plus launcher entry points, including the preserved isMainInvocation re-export.
package.json Adds pm-ops and incorporates the docstring check into the release pipeline.
.github/workflows/ci.yml Adds explicit build and docstring-coverage checks before test coverage.
index.ts Adds documentation to declarations without changing their executable behavior.

Reviews (3): Last reviewed commit: "fix: drop the unused isMainInvocation im..." | Re-trigger Greptile

@unbraind

unbraind commented Aug 9, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review
@greptileai review

Verified independently of the implementing agent (which did not survive to run its own gates — its
provider hit a usage cap mid-batch, so every gate below was re-run by the orchestrator):

  • npm run docstring → 4 files, 42 declarations documented, 0 violations (was 34 violations
    of 37 declarations
    , i.e. 8% documented — the worst ratio in the fleet).
  • typecheck clean · 69 tests pass · coverage-gate thresholds met · no dist/ is tracked here.

Please focus review on one thing: whether any docstring is filler. The analyzer rejects a
docstring that merely restates the identifier — it requires a minimum number of terms not present
in the name. That rule is satisfiable by padding, and a padded docstring is worse than none,
because it looks documented and stops the next reader from writing a real one. If any block here
reads as words assembled to clear a threshold rather than information a reader could not get from
the signature, say so and I will rewrite it. That is a more valuable finding on this PR than
anything structural.

Context for future reviews of this fleet: this adopts the canonical pm-ops/docstrings
analyzer rather than copying one of the two existing forks. There were three implementations of
this same rule set in the fleet, and they had already drifted — pm-changelog runs its own fork
inside release:check and passes, while the canonical analyzer finds 5 undocumented
non-exported functions in it. So a fork is not merely redundant here; one of them has already
drifted into a weaker rule set. Any future PR that vendors a copy of this gate instead of depending
on pm-ops/docstrings is a regression worth flagging.

@deepscan reports "1 new and 0 fixed issues" and its detail is behind a paywall, so I cannot
read what it found. Stating that plainly rather than dismissing it: three other analyzers
(CodeRabbit, Greptile, Hound) and semgrep are green on this diff, dist/ is not tracked so it is
reading source, and I reviewed both new scripts by hand. If either of you can see what a fourth
analyzer would flag in scripts/script-launcher.ts or scripts/docstring-gate.ts, that is exactly
the gap I want closed before this merges.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Changed files =='
git diff --name-status "$(git merge-base HEAD origin/main)" HEAD 2>/dev/null || git diff --name-status HEAD~1 HEAD

echo
echo '== PR diff (no lockfiles) =='
git diff --unified=50 "$(git merge-base HEAD origin/main)" HEAD -- \
  .github/workflows/ci.yml index.ts package.json scripts/docstring-gate.ts \
  scripts/script-launcher.ts test/docstring-gate.test.ts \
  ':(exclude)package-lock.json' 2>/dev/null || \
git diff --unified=50 HEAD~1 HEAD -- \
  .github/workflows/ci.yml index.ts package.json scripts/docstring-gate.ts \
  scripts/script-launcher.ts test/docstring-gate.test.ts \
  ':(exclude)package-lock.json'

echo
echo '== Outlines of new scripts and tests =='
for file in scripts/docstring-gate.ts scripts/script-launcher.ts test/docstring-gate.test.ts; do
  if [ -f "$file" ]; then
    echo "--- $file"
    ast-grep outline "$file" --items all --view expanded || true
  fi
done

echo
echo '== Documentation comments added to index.ts =='
git diff --unified=8 "$(git merge-base HEAD origin/main)" HEAD -- index.ts 2>/dev/null || \
git diff --unified=8 HEAD~1 HEAD -- index.ts

Length of output: 123357


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== TypeScript and package configuration =='
for file in package.json tsconfig.json tsconfig.test.json; do
  if [ -f "$file" ]; then
    echo "--- $file"
    cat -n "$file"
  fi
done

echo
echo '== Resolved pm-ops dependency records =='
rg -n -A25 -B3 '"node_modules/pm-ops"|pm-ops@|pm-ops/' package-lock.json 2>/dev/null || true

echo
echo '== pm-ops docstring analyzer public surface and implementation =='
if [ -d node_modules/pm-ops ]; then
  fd -t f . node_modules/pm-ops | sort | sed -n '1,160p'
  rg -n -A35 -B10 '\banalyzeDocstringCoverage\b|interface .*Docstring|type .*Docstring|files_scanned|declarations_checked' node_modules/pm-ops
fi

echo
echo '== Every JSDoc block added in index.ts, with the attached declaration =='
git diff -U0 "$(git merge-base HEAD origin/main)" HEAD -- index.ts 2>/dev/null \
  || git diff -U0 HEAD~1 HEAD -- index.ts

echo
echo '== Current scripts and test with line numbers =='
for file in scripts/docstring-gate.ts scripts/script-launcher.ts test/docstring-gate.test.ts; do
  echo "--- $file"
  cat -n "$file"
done

echo
echo '== Direct invocation patterns in existing operational scripts =='
rg -n -A12 -B8 'isMainInvocation|runIfMain|import\.meta\.url|process\.argv' scripts test --glob '*.ts'

Length of output: 58185


@unbraind Full review complete.

I found one docstring that reads as filler.

  • scripts/script-launcher.ts Line 67 through Line 73: The GateResult block includes the duplication-gate threshold and a hypothetical future failure. This does not describe the interface contract. It looks written to justify the declaration instead of helping a reader use it. Keep the useful contract detail: a gate result contains an exit code and captured stdout/stderr. Remove the duplication-gate rationale.

The other added docstrings in index.ts, scripts/docstring-gate.ts, and the launcher functions explain behavior, edge cases, or external constraints. They do not read as identifier restatements.

I found no reproducible functional defect in scripts/docstring-gate.ts or scripts/script-launcher.ts. The lockfile resolves the required canonical pm-ops@2026.8.8 dependency, and the gate is connected to both CI and release:check.


✏️ Learnings added
Learnt from: unbraind
URL: https://github.com/unbraind/pm-linear/pull/58

Timestamp: 2026-08-09T00:22:07.858Z
Learning: For pm-linear and related fleet repositories, use the canonical `pm-ops/docstrings` analyzer as a dependency. Do not vendor or fork its implementation because existing forks have drifted into weaker rule sets.

Learnt from: unbraind
URL: https://github.com/unbraind/pm-linear/pull/58

Timestamp: 2026-08-09T00:22:07.858Z
Learning: When reviewing docstring-gate changes in this fleet, prioritize documentation usefulness. Flag comments that add CI-threshold rationale, implementation history, or word padding instead of behavior, contracts, edge cases, or external constraints.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

The symbol was imported alongside GateResult and runIfMain but never referenced
in the module body - the re-export on the last line is a separate `export ...
from` that does not consume the import binding. Typecheck did not object
because an unused import is not a type error, and none of CodeRabbit, Greptile,
Hound or semgrep flagged it either.

Identified by working backwards from DeepScan, which reported '1 new and 0 fixed
issues' on this PR while main reports '0 new and 0 fixed'. Its detail is behind
a paywall, so the finding was located by elimination over the only new code in
the diff rather than read directly.
@unbraind

unbraind commented Aug 9, 2026

Copy link
Copy Markdown
Owner Author

Found DeepScan's finding without being able to read it, and fixed it in 911cc77.

Recording the method, because "a paywalled analyzer disagrees and we merged anyway" is a habit
worth not forming.

DeepScan reported 1 new and 0 fixed issues here while main reports 0 new and 0 fixed, so it
was genuinely introduced by this PR rather than pre-existing. That narrowed it to the only new code
in the diff — two script files — and one candidate stood out:

import { type GateResult, isMainInvocation, runIfMain } from "./script-launcher.ts";
…
export { isMainInvocation } from "./script-launcher.ts";   // ← separate re-export

isMainInvocation was imported but never referenced in the module body. The last line is a
distinct export … from, which does not consume the import binding. Classic unused-import finding.

What is notable is what didn't catch it: tsc --noEmit is silent because an unused import is not
a type error, and CodeRabbit, Greptile, Hound and semgrep were all green on this diff. A fourth
analyzer earning its place by finding the one thing four others missed is a good argument for
keeping it in the required set rather than treating it as advisory.

@coderabbitai @greptileai — worth adding to your models for this fleet: an import { X } …
paired with a separate export { X } from … in the same file leaves X unused in the module body.
It reads as intentional because the symbol is part of the public surface, which is exactly why it
survives review. The fix is to drop it from the import and keep only the re-export.

Gates after the fix: docstring gate 4 files / 42 declarations / 0 violations, 69 tests pass,
typecheck clean, coverage thresholds met.

Please re-review — this is a one-line change to the import list.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Commit summary and focused diff =='
git show --stat --oneline --decorate --no-renames 911cc77
git show --format=fuller --unified=30 --no-ext-diff 911cc77 -- scripts/docstring-gate.ts scripts/script-launcher.ts

echo
echo '== Updated script outline =='
ast-grep outline scripts/docstring-gate.ts --items all --view expanded

echo
echo '== Import and re-export declarations =='
ast-grep run \
  --pattern 'import { $$$IMPORTS } from "./script-launcher.ts"' \
  --lang typescript \
  scripts/docstring-gate.ts || true
ast-grep run \
  --pattern 'export { $$$EXPORTS } from "./script-launcher.ts"' \
  --lang typescript \
  scripts/docstring-gate.ts || true

echo
echo '== Relevant current lines =='
rg -n -A3 -B3 'from "./script-launcher\.ts"' scripts/docstring-gate.ts

Length of output: 5401


@unbraind Re-review complete.

Commit 911cc77 removes isMainInvocation from the import on Line 16. The separate re-export remains on Line 67. This preserves the public export and removes the unused local binding.

I found no issue in this one-line change.

🐇 ✓


✏️ Learnings added
Learnt from: unbraind
URL: https://github.com/unbraind/pm-linear/pull/58

Timestamp: 2026-08-09T00:48:16.829Z
Learning: In TypeScript modules in the pm-linear fleet, `import { X } from "./module.ts"` and a separate `export { X } from "./module.ts"` do not share a binding. If the module body does not reference `X`, remove `X` from the import and retain the direct re-export to avoid an unused import while preserving the public API.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@unbraind

unbraind commented Aug 9, 2026

Copy link
Copy Markdown
Owner Author

Merging. DeepScan is now SUCCESS — confirming the unused import was the finding, identified by
elimination rather than read. All checks green, CLEAN, every bot comment read and voted.

@coderabbitai — thank you for saving that as a learning, and the wording is precise. Worth
noting the meta-point: the finding was located by differential reasoning about a signal we could
not read
. DeepScan reported 1 new / 0 fixed while main reported 0 new / 0 fixed, which was
enough to bound the search to the diff's only new code. That is a reusable technique when a paywalled
or opaque checker disagrees — the count alone carries information even when the detail does not.

What makes this one worth remembering is what missed it: tsc --noEmit is silent (an unused import
is not a type error), and CodeRabbit, Greptile, Hound and semgrep were all green on the same diff.
Four reviewers agreeing is not the same as the code being clean.

What this PR is

pm-linear had the fleet's worst docstring ratio — 34 violations of 37 declarations, 8% documented
— and is now 0 of 42, with the gate wired into release:check and CI.

It adopts the canonical pm-ops/docstrings analyzer rather than vendoring a copy. Measured this
session, the fleet had three implementations of this one policy and they had already drifted:
pm-changelog runs its own fork inside release:check and passes, while the canonical analyzer
finds five undocumented functions in it. That fork is being retired in
pm-changelog#131.

One inconsistency I am recording rather than quietly leaving: pm-changelog#131 pins pm-ops to an
exact version on the argument that a library defining what a gate rejects is part of the gate's
specification. This PR uses ^2026.8.8. The right answer is the same in every package or in none, so
it belongs in the fleet-wide item rather than being silently divergent — filed, not forgotten.

@unbraind
unbraind merged commit 646e18a into main Aug 9, 2026
8 checks passed
@unbraind
unbraind deleted the docstring-gate-adoption branch August 9, 2026 00:58
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@unbraind Agreed. The differential count was sufficient evidence to focus inspection on code introduced by this PR. This is useful when an analyzer result is opaque or unavailable.

The fixed unused import confirms that independent analyzers can find defects that type checking and several source reviewers miss.

The canonical analyzer adoption and mandatory gate establish a consistent baseline for this repository. The pm-ops version policy should be decided at fleet scope, then applied consistently.

🐇 ✓


✏️ Learnings added
Learnt from: unbraind
URL: https://github.com/unbraind/pm-linear/pull/58

Timestamp: 2026-08-09T00:58:24.719Z
Learning: When an opaque or paywalled analyzer reports a different issue count for a pull request than for the base branch, compare the counts to determine whether the finding is newly introduced. If the finding is new, constrain investigation to the diff, even when the analyzer does not expose its detailed result. Do not treat agreement among other analyzers or a clean TypeScript type check as proof that no defect exists.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant