Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .agents/pm/history/ops-zq8c.jsonl

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions .agents/pm/issues/ops-zq8c.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
id: ops-zq8c
title: Include TSX in docstring and duplication gates with verified source counts
description: "GitHub #128: pm-ops docstring and duplication gates silently omit TSX sources. Make both engines scan TSX, prove source-count completeness, and certify the exact package head."
type: Issue
status: blocked
priority: 1
tags[4]: "area:quality",docstrings,duplication,tsx
created_at: "2026-09-28T15:05:31.893Z"
updated_at: "2026-10-02T23:43:44.706Z"
author: codex
estimated_minutes: 180
acceptance_criteria: Directory and single-file docstring analysis find undocumented TSX exports; jscpd 4 and 5 detect TSX clones with the real engines; mismatched scan counts fail closed; release gate passes; companion records exact limitations.
comments[5]{created_at,author,text}:
"2026-10-02T18:27:05.767Z",pi-glm,"Rebase to current main (pi-glm, orchestrator land pass): PR #132 rebased onto origin/main 5ea8406 (releases 2026.9.28-1 and 2026.9.29 merged in cleanly, no conflicts). New head f3e66c3; same three commits. Full gate re-verified on the rebased head: npm run release:check passes (typecheck, lint, duplication, docstrings, coverage 100/100/100/100 across 23 sources, prod audit 0 findings, pack dry run, changelog:check, release-changelog-date, publish-attestation, lifecycle-policy), and pm health --strict-exit --json exits 0 with only stale-in-progress advisories. Re-review requested from CodeRabbit/Greptile/Gemini."
"2026-10-02T21:01:14.692Z",pi-grok,"Cubic review 5395516638 on head b15bf93, land-pass disposition:\n\n4168776167 is valid. Note 3 began with a pasted author=codex,text= label. pm item notes --edit 3 stripped that prefix so the text starts at \"CodeRabbit review comment 4124694533\". The original note_add history line is kept; the edit is a new history event.\n\n4168776160 is refused. tokenize selects LanguageVariant.JSX only when the file identifier ends with .tsx, which is the same rule collectSourceFiles uses to admit sources. analyzeSource's file argument is that identifier, not a free-form module name. Inferring JSX from source text would treat TypeScript generics in .ts files as tags. A caller that passes TSX bytes under a non-.tsx name is outside the gate contract; the walker never does that.\n\n4168776178 is refused. A live jscpd 5.2.1 JSON report stores statistics.formats.typescript.sources and statistics.total.sources as counts, not file maps. Duplicate records name only files that participated in a clone. The one-token probe therefore cannot name a same-size substitution, and the function comment above analyzeWithBinary already states that the JSON report carries only aggregate source counts. jscpd 4 still fails closed with skippedSources file names."
"2026-10-02T21:09:30.355Z",pi-grok,"Land-pass gate: the note-only head was included in the rebased pm-ops#134 tree, where npm run release:check exited 0 (455 pass, 0 fail, 2 default-suite real-data skips, c8 100/100/100/100 across 23 sources, changelog:check current). Local changelog:check on this branch also exited 0. pm health --strict-exit --require-merge-drivers exited 0."
"2026-10-02T23:41:34.683Z",codex-sol-land,"Resumed PR #132 from 8ae094a066a542113f04dd4a9716205f106bd42c. Rebase onto current main yields 8ae094a066a542113f04dd4a9716205f106bd42c. All existing bot artifacts and restart-era owner replies inspected; no new actionable finding. Preserve earlier fixes and technical refusals. Verifying unchanged CI gates under the shared heavy lock; no merge, release or closure."
"2026-10-02T23:43:43.564Z",codex-sol-land,"Resumed verification: npm ci, current-base rebase, fresh committed-dist comparison, strict local tracker health with required merge drivers, npm run release:check, and bun install --no-save all passed. Full gate: 454 tests, 452 pass, 2 skips; configured coverage thresholds unchanged. PM-linked test/lint-and-duplication-gates.test.ts passed. Earlier findings and technical refusals retained; no new source fix was needed in this restart. Exact pushed-head CI and substantive reviewer availability remain separate checks; no merge, release, publication or item closure."
notes[3]:
Comment thread
unbraind marked this conversation as resolved.
- created_at: "2026-09-28T15:05:31.893Z"
author: codex
text: "TDD: TSX docstring and real jscpd 4 tests failed before the source fix. The candidate passes 449/451 tests with two existing opt-in skips, c8 100/100/100/100, 221/221 documented declarations, zero duplication across 43 sources, zero production audit findings, and real packed npm/Node and Bun TSX acceptance. The local PM CLI SDK pin is 2026.9.28."
- created_at: "2026-09-28T15:18:38.784Z"
author: codex
text: "PR #132 first-head review found two valid regressions. Greptile P1 reproduced: a JSX closing tag let the tokenizer hide a later export; the TSX scanner now uses LanguageVariant.JSX and focused tests cover both direct analysis and directory walking. CodeRabbit major reproduced: fast-glob followed symlinked paths while jscpd 5 did not; fast-glob and jscpd 4 now share the no-symlink policy with jscpd 5, with real 4/5 symlink fixtures. Focused tests, build, typecheck, lint, and docstrings pass; full exact-head gate and packed acceptance remain pending."
- created_at: "2026-09-28T16:48:08.764Z"
author: "harness:codex"
text: "CodeRabbit review comment 4124694533 reproduced a jscpd 5.2.1 ambient .jscpd.json threshold failure: primary 200-token scan passed, one-token source probe detected 81.2% duplication and exited 1 before reading its count. A real-binary regression failed first. The fix resolves the repo root before launching jscpd and runs both canonical scans from an isolated output directory, so package duplicationGate remains authoritative. Focused test now passes, full release:check exits 0 with 100% on all four measured coverage dimensions, zero prod audit findings, and fresh packed npm/Node and Bun imports both report two complete sources and zero primary clones."
edited_at: "2026-10-02T21:01:02.968Z"
files[5]{path,scope,note}:
docstrings.ts,project,TSX source walker
duplication.ts,project,Both jscpd engines and source-count verification
README.md,project,Updated consumer guidance
test/docstrings.test.ts,project,TSX docstring regression
test/lint-and-duplication-gates.test.ts,project,Real jscpd 4 and 5 TSX acceptance
tests[2]:
- command: "npm run release:check"
path: package.json
scope: project
timeout_seconds: 900
provenance:
author: codex
created_at: "2026-09-28T15:05:31.893Z"
source_kind: local_mutation
source_ref: fix/pm-ops-tsx-quality-gates-2026-09-28
- command: node --test test/lint-and-duplication-gates.test.ts
scope: project
timeout_seconds: 120
provenance:
author: codex-sol-land
created_at: "2026-10-02T23:41:36.955Z"
source_kind: local_mutation
source_ref: fix/pm-ops-tsx-quality-gates-2026-09-28
docs[4]:
- path: "https://github.com/unbraind/pm-ops/issues/128"
scope: global
note: Source issue and reproduction
- path: "https://github.com/unbraind/pm-ops/pull/132#discussion_r4123846054"
scope: global
note: Greptile JSX closing-tag finding
- path: "https://github.com/unbraind/pm-ops/pull/132#discussion_r4123865252"
scope: global
note: CodeRabbit symlink scope finding
- path: "https://github.com/unbraind/pm-ops/pull/132"
scope: project
Comment thread
unbraind marked this conversation as resolved.
body: ""
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,12 @@ process.exitCode = await runLintGate();
`runLintGate` uses the canonical policy, prints stylish diagnostics to stderr, and
returns `0` or `1` for use as the process exit code.

The duplication export reads `package.json`, scans `**/*.ts` by default (including
root sources, `scripts/`, and tests), reports every clone pair with both file
line ranges, and fails when the measured percentage is above the configured
threshold. `globs` and `minTokens` can be overridden for direct analysis;
The duplication export reads `package.json`, scans `**/*.{ts,tsx}` by default
(including root sources, `scripts/`, UI components, and tests), reports every
clone pair with both file line ranges, and fails when the measured percentage
is above the configured threshold. Both jscpd 4 and 5 scan TS and TSX; the
jscpd 5 gate checks its source count with a one-token pass and refuses an
incomplete scan. `globs` and `minTokens` can be overridden for direct analysis;
the gate uses `minTokens: 50` when the field is omitted.

### Consumers
Expand All @@ -362,7 +364,7 @@ exports adds all five packages, using the version ranges shown in
```ts
import { analyzeDuplication, runDuplicationGate } from "pm-ops/duplication";

const report = await analyzeDuplication({ globs: ["src/**/*.ts", "test/**/*.ts"] });
const report = await analyzeDuplication({ globs: ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}"] });
await runDuplicationGate();
```

Expand Down
4 changes: 2 additions & 2 deletions dist/docstrings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export interface DocstringViolation {
}
/** Aggregate result of scanning one tree. */
export interface DocstringReport {
/** Number of `.ts` files analyzed. */
/** Number of `.ts` and `.tsx` files analyzed. */
readonly files_scanned: number;
/** Number of declarations evaluated against the rules. */
readonly declarations_checked: number;
Expand All @@ -137,7 +137,7 @@ export interface SourceAnalysis {
*/
export declare function analyzeSource(text: string, file: string): SourceAnalysis;
/**
* Walk a directory tree and analyze every authored `.ts` source beneath it,
* Walk a directory tree and analyze every authored `.ts` or `.tsx` source beneath it,
* skipping `.d.ts` files and the structural non-source directories. Scanning
* zero files fails by throwing rather than passing vacuously.
*/
Expand Down
2 changes: 1 addition & 1 deletion dist/docstrings.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 10 additions & 8 deletions dist/docstrings.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/docstrings.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/duplication.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ interface ReportedAnalysis {
readonly total: {
readonly lines: number;
readonly duplicatedLines: number;
readonly sources: number;
};
};
}
Expand Down
2 changes: 1 addition & 1 deletion dist/duplication.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading