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
19 changes: 19 additions & 0 deletions .agents/pm/chores/pm-github-1wka.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
id: pm-github-1wka
title: Eliminate all 37 any usages from pm-github source with real GitHub Projects V2 GraphQL types and typed handler contexts
description: "index.ts carried 37 any usages in two groups. Group A was untyped GitHub Projects V2 GraphQL responses: githubGraphQL<any> at every call site plus untyped map callbacks over nodes, fields and options. Replaced with 18 precise interfaces derived from the ACTUAL query strings next to each call site rather than guessed: project metadata, item connections with pageInfo and nodes, field lists with their option sets, the draft-issue and add-item mutation payloads, the owner-projects listing and the issue node-id resolution. GraphQL nullability is modelled honestly, so nodes is typed Array<T | null> because connections may include nulls for redacted or inaccessible items and the callers already filter them. Verified one type field-for-field against its query: fetchProjectItems selects pageInfo hasNextPage endCursor and nodes id fieldValueByName content, and the interfaces declare exactly those and nothing unselected. Group B was untyped extension handler and hook contexts across runSync, runExport, runValidate, the project commands, the seven registered run handlers, registerPreflight, registerImporter, registerExporter, hooks.afterCommand and the search query path; all now use the real SDK types. Source any count is 0, down from 37, and tests are 0 down from 52 (the two remaining grep hits are comments that mention as any, not usages)."
type: Chore
status: closed
priority: 1
tags: []
created_at: "2026-07-27T16:28:44.867Z"
updated_at: "2026-07-27T16:43:43.814Z"
closed_at: "2026-07-27T16:28:47.026Z"
author: claude-code
acceptance_criteria: "grep for any patterns over index.ts and test/*.ts returns no real usages (was 37 source / 52 test); typecheck, check and 168 tests pass; behaviour unchanged; every GraphQL interface is derived from the query string at its call site with honest nullability; production proof shows install ok, all five subcommands registered, no flag collision and pm health extensions ok."
notes[4]{created_at,author,text}:
"2026-07-27T16:28:45.882Z",claude-code,"Production proof with the built extension installed into a throwaway workspace holding two seeded items: install ok with no warnings, host commands unaffected (pm list renders items, pm list --json valid), all five registered subcommands export import project sync validate resolve, no host-owned global flag is declared, pm health reports extensions ok with no warnings, and github validate --help works. 168 tests pass."
"2026-07-27T16:28:46.285Z",claude-code,"Audited the camelCase multi-word flag contract that caused three defects in pm-ops, and pm-github was already correct: index.ts line 432 documents that flags may arrive kebab-case or camelCase, and every one of the eleven multi-word flags (comments-mode, dry-run, include-comments, include-prs, label-map, link-deps, no-add-missing, skip-drafts, status-map, with-comments) is read with BOTH forms via optionEnabled. No change needed."
"2026-07-27T16:43:43.086Z",claude-code,"Greptile review on PR 18 found a REAL crash the typing refactor introduced, reproduced with T-Rex: the SDK declares SearchProviderQueryContext.documents as ItemDocument[] with a REQUIRED metadata, so the refactor replaced the pre-existing guard d?.metadata ? d.metadata : d with a bare d.metadata. But SearchProviderQueryContext carries an index signature and the runtime hands RAW pm items through on some paths, so trusting the declared type produced undefined entries and crashed indexByProvenance with a TypeError. This is the classic typing-refactor hazard: the type says the field always exists, the runtime disagrees, and the guard that proved otherwise gets deleted in the name of the type. Guard restored as a typed narrowing helper searchDocumentToItem handling wrapped, raw and neither, with no any."
"2026-07-27T16:43:43.812Z",claude-code,"My first regression tests for this were NOT falsifiable: reverting the guard still passed 172/172, because they tested the helper in isolation and a hand-mirrored copy of the mapping rather than the code the provider runs. That is exactly the flaw this session kept finding elsewhere. Fixed by extracting the provider's real mapping into resolveSearchCorpus and testing THAT: the surrounding query handler does network I/O first so an end-to-end test cannot reach the mapping without stubbing internals, and an inline expression is untestable in practice. Falsification now verified: reverting the guard inside resolveSearchCorpus fails the test (171 pass 1 fail), restoring passes 172."
close_reason: "Shipped: 37 source any eliminated with real Projects V2 GraphQL types and SDK handler contexts, verified by production proof rather than tests alone."
body: ""
14 changes: 14 additions & 0 deletions .agents/pm/chores/pm-github-iai5.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
id: pm-github-iai5
title: Adopt pm-cli 2026.7.27 in pm-github
description: "Raises the pm-cli peerDependency to >=2026.7.27 and the devDependency to ^2026.7.27, refreshing the lockfile. The package version and manifest version were already 2026.7.27 from the daily release. An activation proof is mandatory rather than optional for this bump because 2026.7.27 hardened host-owned global flags and a collision aborts command registration at the offending command, dropping it and every later sibling. Proven: all five registered subcommands resolve, no host-owned global is declared anywhere in index.ts, and pm health reports extensions ok with no warnings."
type: Chore
status: closed
priority: 2
tags: []
created_at: "2026-07-27T16:29:02.835Z"
updated_at: "2026-07-27T16:29:04.381Z"
closed_at: "2026-07-27T16:29:04.380Z"
author: claude-code
acceptance_criteria: peerDependencies >=2026.7.27 and devDependencies ^2026.7.27 with an updated lockfile; node_modules resolves 2026.7.27; all five pm-github subcommands register and resolve on the real CLI; flag-collision audit clean; pm health extensions ok.
close_reason: Shipped with the activation proof the hardened 2026.7.27 host requires.
body: ""
8 changes: 8 additions & 0 deletions .agents/pm/history/pm-github-1wka.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{"ts":"2026-07-27T16:28:44.867Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-github-1wka"},{"op":"add","path":"/metadata/title","value":"Eliminate all 37 any usages from pm-github source with real GitHub Projects V2 GraphQL types and typed handler contexts"},{"op":"add","path":"/metadata/description","value":"index.ts carried 37 any usages in two groups. Group A was untyped GitHub Projects V2 GraphQL responses: githubGraphQL<any> at every call site plus untyped map callbacks over nodes, fields and options. Replaced with 18 precise interfaces derived from the ACTUAL query strings next to each call site rather than guessed: project metadata, item connections with pageInfo and nodes, field lists with their option sets, the draft-issue and add-item mutation payloads, the owner-projects listing and the issue node-id resolution. GraphQL nullability is modelled honestly, so nodes is typed Array<T | null> because connections may include nulls for redacted or inaccessible items and the callers already filter them. Verified one type field-for-field against its query: fetchProjectItems selects pageInfo hasNextPage endCursor and nodes id fieldValueByName content, and the interfaces declare exactly those and nothing unselected. Group B was untyped extension handler and hook contexts across runSync, runExport, runValidate, the project commands, the seven registered run handlers, registerPreflight, registerImporter, registerExporter, hooks.afterCommand and the search query path; all now use the real SDK types. Source any count is 0, down from 37, and tests are 0 down from 52 (the two remaining grep hits are comments that mention as any, not usages)."},{"op":"add","path":"/metadata/type","value":"Chore"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":1},{"op":"add","path":"/metadata/tags","value":[]},{"op":"add","path":"/metadata/created_at","value":"2026-07-27T16:28:44.867Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-07-27T16:28:44.867Z"},{"op":"add","path":"/metadata/author","value":"claude-code"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"92891c55c0b900971ee9f6f70dc9eda8b07351fc0604dc1e3f7863e9867090a2","message":""}
{"ts":"2026-07-27T16:28:45.452Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:28:45.452Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"92891c55c0b900971ee9f6f70dc9eda8b07351fc0604dc1e3f7863e9867090a2","after_hash":"785eacc78293c21e730927c3a96b95755ecc15c92acbf9eabeac00bfee8e47b5"}
{"ts":"2026-07-27T16:28:45.883Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"note_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:28:45.883Z"},{"op":"add","path":"/metadata/notes","value":[{"created_at":"2026-07-27T16:28:45.882Z","author":"claude-code","text":"Production proof with the built extension installed into a throwaway workspace holding two seeded items: install ok with no warnings, host commands unaffected (pm list renders items, pm list --json valid), all five registered subcommands export import project sync validate resolve, no host-owned global flag is declared, pm health reports extensions ok with no warnings, and github validate --help works. 168 tests pass."}]}],"before_hash":"785eacc78293c21e730927c3a96b95755ecc15c92acbf9eabeac00bfee8e47b5","after_hash":"91ddacd8b025bec9408efeec22cab941cf77281393a61e0bdeb878e78501b60c"}
{"ts":"2026-07-27T16:28:46.286Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"note_add","patch":[{"op":"add","path":"/metadata/notes/1","value":{"created_at":"2026-07-27T16:28:46.285Z","author":"claude-code","text":"Audited the camelCase multi-word flag contract that caused three defects in pm-ops, and pm-github was already correct: index.ts line 432 documents that flags may arrive kebab-case or camelCase, and every one of the eleven multi-word flags (comments-mode, dry-run, include-comments, include-prs, label-map, link-deps, no-add-missing, skip-drafts, status-map, with-comments) is read with BOTH forms via optionEnabled. No change needed."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:28:46.286Z"}],"before_hash":"91ddacd8b025bec9408efeec22cab941cf77281393a61e0bdeb878e78501b60c","after_hash":"a67fa7e5c06f1df3254f1fe8024232bb1c859a6d55ec79e7384a10af8d4a8cc4"}
{"ts":"2026-07-27T16:28:46.697Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:28:46.697Z"},{"op":"add","path":"/metadata/acceptance_criteria","value":"grep for any patterns over index.ts and test/*.ts returns no real usages (was 37 source / 52 test); typecheck, check and 168 tests pass; behaviour unchanged; every GraphQL interface is derived from the query string at its call site with honest nullability; production proof shows install ok, all five subcommands registered, no flag collision and pm health extensions ok."}],"before_hash":"a67fa7e5c06f1df3254f1fe8024232bb1c859a6d55ec79e7384a10af8d4a8cc4","after_hash":"afe8d90457aeda9cea5801c0fb975af8eff2065958c5fceda7cb8c54a762c30c"}
{"ts":"2026-07-27T16:28:47.027Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"close","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:28:47.027Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-07-27T16:28:47.026Z"},{"op":"add","path":"/metadata/close_reason","value":"Shipped: 37 source any eliminated with real Projects V2 GraphQL types and SDK handler contexts, verified by production proof rather than tests alone."}],"before_hash":"afe8d90457aeda9cea5801c0fb975af8eff2065958c5fceda7cb8c54a762c30c","after_hash":"f03ce54264da4d987e3417a61bba8b1c22c821abb576bdc2815b1eb40edb3f3a"}
{"ts":"2026-07-27T16:43:43.087Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"note_add","patch":[{"op":"add","path":"/metadata/notes/2","value":{"created_at":"2026-07-27T16:43:43.086Z","author":"claude-code","text":"Greptile review on PR 18 found a REAL crash the typing refactor introduced, reproduced with T-Rex: the SDK declares SearchProviderQueryContext.documents as ItemDocument[] with a REQUIRED metadata, so the refactor replaced the pre-existing guard d?.metadata ? d.metadata : d with a bare d.metadata. But SearchProviderQueryContext carries an index signature and the runtime hands RAW pm items through on some paths, so trusting the declared type produced undefined entries and crashed indexByProvenance with a TypeError. This is the classic typing-refactor hazard: the type says the field always exists, the runtime disagrees, and the guard that proved otherwise gets deleted in the name of the type. Guard restored as a typed narrowing helper searchDocumentToItem handling wrapped, raw and neither, with no any."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:43:43.087Z"}],"before_hash":"f03ce54264da4d987e3417a61bba8b1c22c821abb576bdc2815b1eb40edb3f3a","after_hash":"066fa3fbae3de7e1b41c4cb89df92a1507c13f6289186ba2f31deccdeeb4fc93"}
{"ts":"2026-07-27T16:43:43.814Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"note_add","patch":[{"op":"add","path":"/metadata/notes/3","value":{"created_at":"2026-07-27T16:43:43.812Z","author":"claude-code","text":"My first regression tests for this were NOT falsifiable: reverting the guard still passed 172/172, because they tested the helper in isolation and a hand-mirrored copy of the mapping rather than the code the provider runs. That is exactly the flaw this session kept finding elsewhere. Fixed by extracting the provider's real mapping into resolveSearchCorpus and testing THAT: the surrounding query handler does network I/O first so an end-to-end test cannot reach the mapping without stubbing internals, and an inline expression is untestable in practice. Falsification now verified: reverting the guard inside resolveSearchCorpus fails the test (171 pass 1 fail), restoring passes 172."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:43:43.814Z"}],"before_hash":"066fa3fbae3de7e1b41c4cb89df92a1507c13f6289186ba2f31deccdeeb4fc93","after_hash":"c5c5eb066efbeade0950da4e8f6a08dc1e748bf8da7dbfe679b2cbaa53b84224"}
4 changes: 4 additions & 0 deletions .agents/pm/history/pm-github-iai5.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{"ts":"2026-07-27T16:29:02.835Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-github-iai5"},{"op":"add","path":"/metadata/title","value":"Adopt pm-cli 2026.7.27 in pm-github"},{"op":"add","path":"/metadata/description","value":"Raises the pm-cli peerDependency to >=2026.7.27 and the devDependency to ^2026.7.27, refreshing the lockfile. The package version and manifest version were already 2026.7.27 from the daily release. An activation proof is mandatory rather than optional for this bump because 2026.7.27 hardened host-owned global flags and a collision aborts command registration at the offending command, dropping it and every later sibling. Proven: all five registered subcommands resolve, no host-owned global is declared anywhere in index.ts, and pm health reports extensions ok with no warnings."},{"op":"add","path":"/metadata/type","value":"Chore"},{"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-27T16:29:02.835Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-07-27T16:29:02.835Z"},{"op":"add","path":"/metadata/author","value":"claude-code"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"f13087d6b5712219966d22468c0e8d74787c81c4039caff9f7f79d7afeb13f5f","message":""}
{"ts":"2026-07-27T16:29:03.334Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:29:03.334Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"f13087d6b5712219966d22468c0e8d74787c81c4039caff9f7f79d7afeb13f5f","after_hash":"82b44c9201fb0e04ad42c4bf99ed34e7be12501e737669c00d99c3d9faf1d2a9"}
{"ts":"2026-07-27T16:29:03.827Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:29:03.827Z"},{"op":"add","path":"/metadata/acceptance_criteria","value":"peerDependencies >=2026.7.27 and devDependencies ^2026.7.27 with an updated lockfile; node_modules resolves 2026.7.27; all five pm-github subcommands register and resolve on the real CLI; flag-collision audit clean; pm health extensions ok."}],"before_hash":"82b44c9201fb0e04ad42c4bf99ed34e7be12501e737669c00d99c3d9faf1d2a9","after_hash":"4344ae2fbe075c46152086d0573e376636822ca0d12dd5eb12ce0b0d355e4980"}
{"ts":"2026-07-27T16:29:04.381Z","author":"claude-code","author_source":"asserted","agent_harness":"claude-code","agent_instance":"6ff7a19f0fde28814757fa94","op":"close","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-27T16:29:04.381Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-07-27T16:29:04.380Z"},{"op":"add","path":"/metadata/close_reason","value":"Shipped with the activation proof the hardened 2026.7.27 host requires."}],"before_hash":"4344ae2fbe075c46152086d0573e376636822ca0d12dd5eb12ce0b0d355e4980","after_hash":"0349103eec3601bc181ad207f82ed5a90a34ab263df6a078ff023196f8ec8d43"}
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## Unreleased

### Other

- Adopt pm-cli 2026.7.27 in pm-github ([pm-github-iai5](https://github.com/unbraind/pm-github/blob/main/.agents/pm/chores/pm-github-iai5.toon))
- Eliminate all 37 any usages from pm-github source with real GitHub Projects V2 GraphQL types and typed handler contexts ([pm-github-1wka](https://github.com/unbraind/pm-github/blob/main/.agents/pm/chores/pm-github-1wka.toon))

## 2026.7.27 - 2026-07-27

### Removed
Expand Down
Loading