Skip to content

Adopt the mandatory docstring gate - #58

Merged
unbraind merged 4 commits into
mainfrom
adopt-docstring-gate
Aug 9, 2026
Merged

Adopt the mandatory docstring gate#58
unbraind merged 4 commits into
mainfrom
adopt-docstring-gate

Conversation

@unbraind

@unbraind unbraind commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Summary

Adopts the fleet's mandatory docstring gate in pm-graph, mirroring the canonical wiring already shipping in pm-brief. The analyzer is not vendored or re-implemented — it is imported from the published pm-ops/docstrings subpath and pinned exactly to pm-ops@2026.8.8 (no ^/~).

A docstring gate enforces presence, never truth, so every violation was documented against its body rather than its name.

What changed

  • scripts/docstring-gate.ts — thin launcher exporting a pure runGate(root): {exitCode, stdout, stderr} plus a thin main(args), ported from pm-brief.
  • test/docstring-gate.test.ts — ports the pm-brief launcher suite.
  • package.jsonpm-ops devDep (exact pin), a docstring script, docstring wired into release:check, and scripts/docstring-gate.ts added to coverageGate.sources (the scripts/ dir is a coverage skip-dir, mirroring the existing prepare-merge-driver.ts entry).
  • .github/workflows/ci.yml — a Verify complete docstring coverage step.
  • src/index.ts (+ rebuilt dist/) — 26 previously-undocumented declarations now have JSDoc.

Violations: 26 → 0

All in src/index.ts, spanning: the Neo4j runtime (neo4jConfigured, neo4jMissingMessage, loadNeo4j, createDriver, syncNeo4j, findDestructiveKeyword), graph construction (relationshipTarget, graphFromItems, toNumber, readNumberProperty, itemNodeMap), multi-format export (cypherStatements, ExportFormat, EdgeFilter, renderMermaid, renderDot, renderExport, readExportOption), analysis (criticalConnectors, ExplainNeighbor, ExplainReport), item-id resolution (sharedPrefixLength, suggestItemIds, ambiguousItemIdError, resolveItemIdOrThrow), and activate.

A few non-obvious truths the docstrings now state:

  • criticalConnectors builds symmetric adjacency — it analyzes the dependency graph as undirected.
  • findDestructiveKeyword flags SET but exempts SET SESSION (regex negative-lookahead).
  • readNumberProperty returns null for a missing value (so "no priority" ≠ 0) while toNumber collapses missing to 0 for summing.
  • syncNeo4j incremental mode deletes stale nodes absent from the current graph; fullSync wipes first.

Quality gates (all green)

  • npm run typecheck
  • npm run build
  • npm run docstring0 violations
  • npm run coverage85.42 / 80.20 / 90.43 against thresholds 81 / 77 / 88 (no regression)
  • npm run release:check (aggregate: typecheck, build, docstring, coverage, audit:prod, pack:dry-run, changelog:check)
  • npm test — 216 passing

pm item

Tracked in pm-graph-k5ao.

Summary by Sourcery

Adopt the shared docstring coverage gate for pm-graph and document all previously undocumented public APIs.

New Features:

  • Add a docstring gate launcher script wired into npm scripts, release checks, and CI to enforce full docstring coverage.
  • Introduce a dedicated docstring gate test suite verifying launcher behavior and entry-point guarding.

Enhancements:

  • Add comprehensive JSDoc documentation to previously undocumented Neo4j, graph construction, export, analysis, and item resolution functions and types in src/index.ts.
  • Clarify the behavior of critical connectivity analysis, destructive query detection, numeric property handling, Neo4j sync semantics, and export rendering formats via docstrings.

Build:

  • Wire the docstring gate into package.json as a dev dependency on pm-ops, add a docstring npm script, and include the launcher script in the coverage gate sources.

CI:

  • Extend the GitHub Actions workflow with a docstring coverage verification step as part of CI.

Tests:

  • Add tests covering the docstring gate launcher, including success, failure, empty-root behavior, CLI main wiring, and direct invocation detection.

Summary by cubic

Adopted the mandatory docstring gate for pm-graph via pm-ops/docstrings, wired into CI and release:check. Documented all previously undocumented declarations and clarified that incremental Neo4j sync skips pruning when the incoming graph is empty; use full sync to wipe.

  • New Features

    • Added scripts/docstring-gate.ts launcher and a docstring npm script; integrated into release:check and CI.
    • Added test/docstring-gate.test.ts and included scripts/docstring-gate.ts in coverageGate.sources.
    • Resolved 26 violations (now 0); rebuilt dist/ to reflect the sync docstring update and updated CHANGELOG.
  • Dependencies

    • Added pm-ops@2026.8.8 (exact pin) and import from pm-ops/docstrings.

Written for commit cbaad0d. Summary will update on new commits.

Review in cubic

Add a thin launcher (scripts/docstring-gate.ts) over the canonical
pm-ops/docstrings analyzer so this package enforces the same lexer-backed
docstring policy as the rest of the fleet, rather than a per-repo fork. The
analyzer is pinned exactly to pm-ops@2026.8.8 and imported from the published
pm-ops/docstrings subpath; it has no ignore list and fails closed on unknown
declaration forms.

The gate requires a JSDoc block that adds information beyond the identifier on
every exported declaration, every public member of an exported class, and every
non-exported function with a body over the threshold. This package had
twenty-six undocumented declarations in src/index.ts, spanning the Neo4j
runtime (config/load/driver/sync/destructive-query guard), graph construction,
multi-format export (cypher/mermaid/dot/graphml/plantuml), analysis
(criticalConnectors, explain types, item-id resolution) and the extension
entry point. Each now has a docstring written against its body — for example
that criticalConnectors analyses the dependency graph as UNDIRECTED, that
findDestructiveKeyword exempts "SET SESSION", and that the two number readers
(readNumberProperty vs toNumber) differ on whether a missing value is null or 0.

Wiring:
  - package.json: pm-ops devDep (exact pin), `docstring` script, the step added
    to release:check, and scripts/docstring-gate.ts listed in coverageGate.sources
    (the scripts/ dir is a coverage skip-dir, mirroring prepare-merge-driver.ts).
  - .github/workflows/ci.yml: a "Verify complete docstring coverage" step.
  - test/docstring-gate.test.ts ports the pm-brief launcher suite.
  - dist/ rebuilt: this package is installed by copying the repo, so the
    compiled docstrings are committed alongside the source.

All quality gates green: typecheck, build, docstring (0 violations), coverage
(85.42 / 80.20 / 90.43 against 81 / 77 / 88), audit:prod, pack:dry-run,
changelog:check, and the full test suite (216 passing).

Tracked pm item: .agents/pm/tasks/pm-graph-k5ao.toon

@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 9, 2026

Copy link
Copy Markdown

Review Change Stack

Summary by CodeRabbit

  • Documentation

    • Added comprehensive documentation throughout the application’s graph configuration, rendering, analytics, synchronization, validation, and command workflows.
  • Quality Improvements

    • Added automated documentation coverage validation to release and continuous integration checks.
    • Validation now reports missing documentation clearly and prevents incomplete documentation from passing checks.
  • Testing

    • Added coverage for successful validation, detected issues, command output, exit statuses, and edge cases.

Walkthrough

The PR adds a mandatory docstring coverage gate. It documents declarations in src/index.ts, adds a testable launcher and tests, and runs the gate in release checks and CI.

Changes

Docstring coverage gate

Layer / File(s) Summary
Source declaration documentation
src/index.ts
Added documentation for Neo4j operations, graph processing, rendering, analytics, synchronization, validation, item resolution, and command registration.
Gate launcher implementation
scripts/docstring-gate.ts
Added coverage analysis, CLI output, exit-code handling, repository-root resolution, and direct-invocation detection.
Launcher validation
test/docstring-gate.test.ts
Added tests for scans, violations, CLI behavior, exit codes, symlinks, and invalid entry paths.
Project integration
package.json, .github/workflows/ci.yml, .agents/pm/tasks/pm-graph-k5ao.toon, .agents/pm/history/pm-graph-k5ao.jsonl
Added the pinned development dependency, package scripts, coverage registration, CI execution, and task completion records.

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

Sequence Diagram(s)

sequenceDiagram
  participant CI as CI test job
  participant npm as npm run docstring
  participant gate as docstring-gate.ts
  participant analyzer as pm-ops/docstrings
  CI->>npm: run docstring check
  npm->>gate: start launcher
  gate->>analyzer: analyze TypeScript docstrings
  analyzer-->>gate: return coverage result
  gate-->>CI: output result and exit status
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly and concisely describes the primary change: adopting the mandatory docstring gate.
Description check ✅ Passed The description directly explains the docstring gate implementation, documentation updates, CI integration, tests, and validation results.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch adopt-docstring-gate

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 9, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR wires pm-graph into the fleet-wide mandatory docstring gate using the canonical pm-ops/docstrings analyzer, adds a thin launcher and test suite around it, integrates the gate into CI and release checks, and backfills JSDoc docstrings for previously undocumented public and key internal APIs so the gate passes with zero violations.

Sequence diagram for the new docstring gate launcher and CI integration

sequenceDiagram
  actor Dev
  participant GitHubActions
  participant npm
  participant docstring_gate_ts as docstring_gate_main
  participant pm_ops_docstrings as analyzeDocstringCoverage

  Dev->>GitHubActions: push / PR
  GitHubActions->>npm: run docstring
  npm->>docstring_gate_ts: node scripts/docstring-gate.ts
  docstring_gate_ts->>pm_ops_docstrings: analyzeDocstringCoverage({ root })
  alt [violations > 0]
    pm_ops_docstrings-->>docstring_gate_ts: report with violations
    docstring_gate_ts-->>npm: exitCode = 1
    docstring_gate_ts-->>npm: stderr "docstring-gate: n violation(s)…"
  else [no violations]
    pm_ops_docstrings-->>docstring_gate_ts: clean report
    docstring_gate_ts-->>npm: exitCode = 0
    docstring_gate_ts-->>npm: stdout "docstring-gate: files, declarations documented"
  end
  npm-->>GitHubActions: propagate exit code
Loading

File-Level Changes

Change Details Files
Add a thin docstring gate launcher and its behavioral tests, delegating analysis to pm-ops/docstrings.
  • Introduce scripts/docstring-gate.ts as a CLI-friendly wrapper around analyzeDocstringCoverage, with a pure runGate(root) that returns exitCode/stdout/stderr and a main(args) that wires results to process streams and exitCode.
  • Implement isMainInvocation(argv, moduleUrl) using realpathSync + pathToFileURL to safely detect direct CLI invocation (including symlinked entry points) without throwing on bad argv[1].
  • Use a small dispatch array at module end to call main only on real CLI invocations, keeping tests able to import the module without side effects or uncoverable branches.
scripts/docstring-gate.ts
Port and adapt the docstring gate launcher test suite from pm-brief to validate pm-graph’s launcher behavior.
  • Add tests that run runGate against the real package root, a synthetic violating root, a synthetic clean root, and an empty root, asserting exit codes and stdout/stderr layout without depending on analyzer wording.
  • Add tests for main(args) to verify it targets the correct default root, writes to the appropriate stream, appends trailing newlines, and sets process.exitCode instead of exiting.
  • Add tests for isMainInvocation to cover direct invocations, non-gate argv, missing argv[1], symlinked entry paths, and non-existent paths (ensuring ENOENT is handled by returning false).
test/docstring-gate.test.ts
Integrate the docstring gate into npm scripts, dev dependencies, coverage gating, and CI.
  • Add a docstring npm script that runs the new launcher, and include it in the release:check aggregate pipeline so releases are blocked on full docstring coverage.
  • Add pm-ops as an exact-pinned devDependency (no caret/tilde) to consume the canonical docstring analyzer from pm-ops/docstrings.
  • Extend coverageGate.sources to include scripts/docstring-gate.ts so the launcher itself is covered despite scripts/ being a skip dir, mirroring prepare-merge-driver.ts.
  • Update the GitHub Actions CI workflow to add a ‘Verify complete docstring coverage’ step that runs npm run docstring before the coverage gate.
package.json
.github/workflows/ci.yml
Backfill JSDoc docstrings for previously undocumented public types and key internal helpers to satisfy the docstring gate and clarify behavior.
  • Document Neo4j-centric helpers (neo4jConfigured, neo4jMissingMessage, loadNeo4j, createDriver, syncNeo4j) with environment expectations, lazy install semantics, error handling, pool tuning, and full vs incremental sync semantics.
  • Clarify graph construction and export utilities (relationshipTarget, graphFromItems, cypherStatements, ExportFormat, EdgeFilter, renderMermaid, renderDot, renderExport, readExportOption) including how inputs are normalized, dangles handled, formats rendered, and options resolved.
  • Describe analysis and item-id resolution helpers (criticalConnectors, ExplainNeighbor, ExplainReport, itemNodeMap, sharedPrefixLength, suggestItemIds, ambiguousItemIdError, resolveItemIdOrThrow) including undirected treatment of edges, articulation/bridge semantics, suggestion ranking, and ambiguity handling.
  • Document numeric helpers and safety behaviors (toNumber vs readNumberProperty) and the destructive query guard findDestructiveKeyword, including the SET vs SET SESSION nuance.
  • Explain the activate entry point’s registration of commands and the output_format service override for pm-graph export results.
src/index.ts
dist/index.js
dist/index.d.ts

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/index.ts`:
- Around line 2431-2443: Update the synchronization documentation for the
function containing the fullSync and currentIds logic to state that incremental
deletion of absent nodes occurs only when currentIds.size is greater than zero;
explicitly document that an empty graph leaves existing project nodes unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4e8388ac-5904-413a-9328-f7db5f2a01c3

📥 Commits

Reviewing files that changed from the base of the PR and between fcbea5f and 77d0f0e.

⛔ Files ignored due to path filters (4)
  • dist/index.d.ts is excluded by !**/dist/**
  • dist/index.js is excluded by !**/dist/**
  • dist/index.js.map is excluded by !**/dist/**, !**/*.map
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • .agents/pm/history/pm-graph-k5ao.jsonl
  • .agents/pm/tasks/pm-graph-k5ao.toon
  • .github/workflows/ci.yml
  • package.json
  • scripts/docstring-gate.ts
  • src/index.ts
  • test/docstring-gate.test.ts

Comment thread src/index.ts
@greptile-apps

greptile-apps Bot commented Aug 9, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adopts the shared mandatory docstring gate and documents previously uncovered declarations.

  • Adds a thin pm-ops/docstrings launcher with unit coverage.
  • Wires docstring validation into CI and the release checks.
  • Adds JSDoc to source declarations and rebuilds committed distribution artifacts.
  • Pins pm-ops exactly and records the change in project metadata and the changelog.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
scripts/docstring-gate.ts Adds a testable launcher around the shared analyzer, including CLI output and direct-invocation handling.
test/docstring-gate.test.ts Covers successful and failed analysis, stream handling, root selection, and entry-point detection.
package.json Adds the exact-pinned analyzer dependency and integrates the gate into release and coverage configuration.
.github/workflows/ci.yml Runs the new docstring gate in the main CI job.
src/index.ts Adds documentation to previously undocumented declarations without changing executable behavior.
dist/index.js Rebuilds the distributed JavaScript with corresponding documentation comments and unchanged runtime logic.
dist/index.d.ts Publishes the newly added API documentation in generated type declarations.

Reviews (3): Last reviewed commit: "Rebuild dist for the incremental-sync do..." | Re-trigger Greptile

CI verifies with changelog:check, which runs in --mode replace --all-release-tags.
Only changelog:full generates in that mode, so a changelog produced by the
prepend-mode changelog script leaves the check failing.
The docstring said an incremental sync DETACH DELETEs every node absent from
the incoming graph. The pruning query is guarded by currentIds.size > 0, so an
incremental sync of an empty graph deletes nothing and the stored project nodes
survive.

The guard is deliberate - an empty read is far more likely to be a failed or
misconfigured scan than a project whose every item was deleted - so the
docstring now states the exception and the reasoning, and points at fullSync as
the way to empty a project on purpose.

Reported by CodeRabbit on #58.
@unbraind

unbraind commented Aug 9, 2026

Copy link
Copy Markdown
Owner Author

Both docstring corrections pushed, each verified against the call site before editing.

@greptileai review
@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

@unbraind, I will perform a complete review of PR #58, including the updated docstrings and their call-site alignment.

⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 38 minutes.

The docstring correction to syncNeo4j (documenting the empty-graph pruning
exception) changed src/index.ts but the committed dist/ was not rebuilt, so the
"committed dist matches a fresh build" gate drifted. Rebuilt with `npm run build`;
only dist/index.js and its source map changed, both reflecting the docstring.
@unbraind
unbraind merged commit 648b91e into main Aug 9, 2026
10 checks passed
@unbraind
unbraind deleted the adopt-docstring-gate branch August 9, 2026 15:46
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