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
20 changes: 20 additions & 0 deletions .agents/pm/features/pm-github-uv1a.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
id: pm-github-uv1a
title: Enforce a real coverage gate by running tests against TypeScript sources
description: ""
type: Feature
status: closed
priority: 2
tags: []
created_at: "2026-07-28T23:32:24.103Z"
updated_at: "2026-07-28T23:33:58.688Z"
closed_at: "2026-07-28T23:33:58.687Z"
author: pi-agent
resolution: "Tests moved onto TypeScript sources and scripts/coverage-gate.ts wired into release:check and CI."
expected_result: "A coverage gate runs in the release check and in CI on both supported Node lines, reports against TypeScript sources, and fails when a source file is untested or a threshold regresses."
actual_result: "npm run check passes. npm run coverage passes with 172 tests, both source files present in the report, at 76.14 line, 78.93 branch and 75.74 function coverage. A negative control adding an untested source file made the gate exit 1 and name that file, so the presence check is not vacuous. Thresholds pinned at 76/78/75. The Node 22 CI leg is unobserved until the PR runs."
comments[1]{created_at,author,text}:
"2026-07-28T23:33:19.033Z",pi-agent,"Negative control: added an untested __probe.ts source file to coverageGate.sources, ran node scripts/coverage-gate.ts, observed exit code 1 with the gate naming __probe.ts as never loaded. Removed the probe and re-ran: exit code 0, 2 source files reported. The presence check is not vacuous."
learnings[1]{created_at,author,text}:
"2026-07-28T23:33:45.811Z",pi-agent,"Node omits never-loaded files from its coverage report rather than reporting them at zero, so a threshold flag alone is satisfiable by narrowing what the suite imports. Any coverage gate must reconcile the report against the source tree."
close_reason: Coverage gate landed and locally verified; the Node 22 CI leg is unobserved until the pull request runs.
body: "Baseline measured 2026-07-29 across two source files: index.ts at 73.08 line, 78.30 branch, 73.03 function; projects.ts at 97.00 line, 81.41 branch, 100.00 function. All files aggregate: 76.14 line, 78.93 branch, 75.74 function. Thresholds pinned at the measured floor (76/78/75) so the numbers can only ratchet up. 172 tests, 0 failures."
Comment thread
unbraind marked this conversation as resolved.
7 changes: 7 additions & 0 deletions .agents/pm/history/pm-github-uv1a.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{"ts":"2026-07-28T23:32:24.103Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_provenance":{"model":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-github-uv1a"},{"op":"add","path":"/metadata/title","value":"Enforce a real coverage gate by running tests against TypeScript sources"},{"op":"add","path":"/metadata/description","value":""},{"op":"add","path":"/metadata/type","value":"Feature"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":2},{"op":"add","path":"/metadata/tags","value":[]},{"op":"add","path":"/metadata/created_at","value":"2026-07-28T23:32:24.103Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-07-28T23:32:24.103Z"},{"op":"add","path":"/metadata/assignee","value":"pi-agent"},{"op":"add","path":"/metadata/author","value":"pi-agent"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"4ff9f1878bdf7b6c042fdc8a5f3835e09201452b39349f4db44b2e179288361c","message":""}
{"ts":"2026-07-28T23:33:03.628Z","author":"codex","author_source":"configured","agent_harness":"pi","agent_provenance":{"model":null},"op":"update","patch":[{"op":"replace","path":"/body","value":"Baseline measured 2026-07-29 across two source files: index.ts at 73.08 line, 78.30 branch, 73.03 function; projects.ts at 97.00 line, 81.41 branch, 100.00 function. All files aggregate: 76.14 line, 78.93 branch, 75.74 function. Thresholds pinned at the measured floor (76/78/75) so the numbers can only ratchet up. 172 tests, 0 failures."},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-28T23:33:03.628Z"}],"before_hash":"4ff9f1878bdf7b6c042fdc8a5f3835e09201452b39349f4db44b2e179288361c","after_hash":"212419c94d449a6f48c6f8b0ee9ef62da46d7777ae991d83facc809d99cb7037"}
{"ts":"2026-07-28T23:33:08.515Z","author":"codex","author_source":"configured","agent_harness":"pi","agent_provenance":{"model":null},"op":"comment_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-28T23:33:08.515Z"},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-07-28T23:33:08.515Z","author":"codex","text":"Negative control: added an untested __probe.ts source file to coverageGate.sources, ran node scripts/coverage-gate.ts, observed exit code 1 with the gate naming __probe.ts as never loaded. Removed the probe and re-ran: exit code 0, 2 source files reported. The presence check is not vacuous."}]}],"before_hash":"212419c94d449a6f48c6f8b0ee9ef62da46d7777ae991d83facc809d99cb7037","after_hash":"83d96227b427fdaa3ec6c560f5b8d01fdeb5dd61ca157a464677fd5c7fe4128a"}
{"ts":"2026-07-28T23:33:19.033Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_provenance":{"model":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/1","value":{"created_at":"2026-07-28T23:33:19.033Z","author":"pi-agent","text":"Negative control: added an untested __probe.ts source file to coverageGate.sources, ran node scripts/coverage-gate.ts, observed exit code 1 with the gate naming __probe.ts as never loaded. Removed the probe and re-ran: exit code 0, 2 source files reported. The presence check is not vacuous."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-28T23:33:19.033Z"}],"before_hash":"83d96227b427fdaa3ec6c560f5b8d01fdeb5dd61ca157a464677fd5c7fe4128a","after_hash":"112aba8ff38bde0e955707691748d0733d815315c0b3fc4a4a064e6dc5f0190b"}
{"ts":"2026-07-28T23:33:40.620Z","author":"codex","author_source":"configured","agent_harness":"pi","agent_provenance":{"model":null},"op":"comment_delete","patch":[{"op":"remove","path":"/metadata/comments/1"},{"op":"replace","path":"/metadata/comments/0/author","value":"pi-agent"},{"op":"replace","path":"/metadata/comments/0/created_at","value":"2026-07-28T23:33:19.033Z"},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-28T23:33:40.620Z"}],"before_hash":"112aba8ff38bde0e955707691748d0733d815315c0b3fc4a4a064e6dc5f0190b","after_hash":"ed4f93345e79d5a9ad843482f5a7735741b1197a74744ef2df7c3f12db01b748"}
{"ts":"2026-07-28T23:33:45.812Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_provenance":{"model":null},"op":"learning_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-28T23:33:45.812Z"},{"op":"add","path":"/metadata/learnings","value":[{"created_at":"2026-07-28T23:33:45.811Z","author":"pi-agent","text":"Node omits never-loaded files from its coverage report rather than reporting them at zero, so a threshold flag alone is satisfiable by narrowing what the suite imports. Any coverage gate must reconcile the report against the source tree."}]}],"before_hash":"ed4f93345e79d5a9ad843482f5a7735741b1197a74744ef2df7c3f12db01b748","after_hash":"002bf7d9137a9ea7920f6e6809c98d22ffdb259ee4eac684312aab12f64ad9ad"}
{"ts":"2026-07-28T23:33:58.688Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_provenance":{"model":null},"op":"close","patch":[{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-28T23:33:58.688Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-07-28T23:33:58.687Z"},{"op":"add","path":"/metadata/resolution","value":"Tests moved onto TypeScript sources and scripts/coverage-gate.ts wired into release:check and CI."},{"op":"add","path":"/metadata/expected_result","value":"A coverage gate runs in the release check and in CI on both supported Node lines, reports against TypeScript sources, and fails when a source file is untested or a threshold regresses."},{"op":"add","path":"/metadata/actual_result","value":"npm run check passes. npm run coverage passes with 172 tests, both source files present in the report, at 76.14 line, 78.93 branch and 75.74 function coverage. A negative control adding an untested source file made the gate exit 1 and name that file, so the presence check is not vacuous. Thresholds pinned at 76/78/75. The Node 22 CI leg is unobserved until the PR runs."},{"op":"add","path":"/metadata/close_reason","value":"Coverage gate landed and locally verified; the Node 22 CI leg is unobserved until the pull request runs."}],"before_hash":"002bf7d9137a9ea7920f6e6809c98d22ffdb259ee4eac684312aab12f64ad9ad","after_hash":"5042ac70caca4a6513c0865fd6805a90559568769b41bcfb91e5cd89a3ac79fc"}
12 changes: 9 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ permissions:
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# 22 is the floor declared in `engines` and the first line that strips
# TypeScript without a flag; 26 is what the fleet develops against.
node-version: [22, 26]
steps:
- name: Checkout
uses: actions/checkout@v7
Expand All @@ -22,7 +28,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: 22
node-version: ${{ matrix.node-version }}
cache: npm

- name: Setup Bun
Expand All @@ -43,8 +49,8 @@ jobs:
- name: Build
run: npm run build

- name: Run tests
run: npm test
- name: Test with coverage gate
run: npm run coverage

- name: Production dependency audit
run: npm run audit:prod
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ dist-test/
.agents/pm/runtime/
.agents/pm/search/
.agents/pm/extensions/
coverage/
2 changes: 1 addition & 1 deletion index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import {
parseProjectRef,
parseStatusMap,
projectItemTag,
} from "./projects.js";
} from "./projects.ts";


// ---------------------------------------------------------------------------
Expand Down
21 changes: 18 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"scripts": {
"build": "tsc",
"build:test": "tsc -p tsconfig.test.json",
"test": "npm run build && npm run build:test && node --test dist-test/*.js",
"test": "npm run build && npm run build:test && node --test test/*.test.ts",
"prepack": "npm run build",
"typecheck": "tsc --noEmit",
"check": "npm run typecheck",
Expand All @@ -31,11 +31,12 @@
"changelog": "pm-changelog --pm-root .agents/pm --mode prepend --output CHANGELOG.md --release-version-from-package --since-previous-tag --until-release-tag --item-url-base https://github.com/unbraind/pm-github/blob/main/.agents/pm --respect-item-release",
"changelog:full": "pm-changelog --pm-root .agents/pm --mode replace --output CHANGELOG.md --all-release-tags --release-version-from-package --item-url-base https://github.com/unbraind/pm-github/blob/main/.agents/pm --respect-item-release",
"changelog:check": "pm-changelog --pm-root .agents/pm --mode prepend --output CHANGELOG.md --release-version-from-package --since-previous-tag --until-release-tag --item-url-base https://github.com/unbraind/pm-github/blob/main/.agents/pm --respect-item-release --check",
"release:check": "npm run typecheck && npm run build && npm test && npm run audit:prod && npm run pack:dry-run && npm run changelog:check",
"release:check": "npm run typecheck && npm run build && npm run coverage && npm run audit:prod && npm run pack:dry-run && npm run changelog:check",
"prepublishOnly": "npm run release:check",
"release:notes": "pm-changelog --pm-root .agents/pm --stdout --since-previous-tag --until-release-tag --release-version-from-package --item-url-base https://github.com/unbraind/pm-github/blob/main/.agents/pm --respect-item-release --pm-bin ./node_modules/.bin/pm --github-step-summary",
"prepare": "node scripts/prepare-merge-driver.mjs",
"merge:install": "pm merge install"
"merge:install": "pm merge install",
"coverage": "npm run build && npm run build:test && node scripts/coverage-gate.ts"
},
"peerDependencies": {
"@unbrained/pm-cli": ">=2026.7.28"
Expand Down Expand Up @@ -92,5 +93,19 @@
},
"publishConfig": {
"access": "public"
},
"coverageGate": {
"sources": [
"."
],
"tests": [
"test/*.test.ts"
],
"thresholds": {
"lines": 76,
"branches": 78,
"functions": 75
},
"ignore": []
}
}
Loading