copilot-session-usage 0.6.0__tar.gz → 0.6.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. copilot_session_usage-0.6.4/.github/skills/gh-release-notes/SKILL.md +325 -0
  2. copilot_session_usage-0.6.4/.github/workflows/refresh-pricing.yml +72 -0
  3. copilot_session_usage-0.6.4/.github/workflows/release-notes.yml +134 -0
  4. copilot_session_usage-0.6.4/.github/workflows/release.yml +208 -0
  5. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/AGENTS.md +10 -0
  6. copilot_session_usage-0.6.4/CONTRIBUTING.md +66 -0
  7. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/PKG-INFO +1 -1
  8. copilot_session_usage-0.6.4/docs/internal/automated_release_proces.md +504 -0
  9. copilot_session_usage-0.6.4/knowledge/findings/2026.07.13-14.27-release-notes-overreported-maintainer-changes.md +34 -0
  10. copilot_session_usage-0.6.4/knowledge/findings/2026.07.24-15.01-actions-token-cannot-create-pr.md +31 -0
  11. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/findings/index.md +2 -0
  12. copilot_session_usage-0.6.4/scripts/validate_release_notes.py +101 -0
  13. copilot_session_usage-0.6.4/src/copilot_session_usage/data/models-and-pricing.lock +7 -0
  14. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/data/models-and-pricing.yml +19 -0
  15. copilot_session_usage-0.6.4/tests/test_release_notes.py +94 -0
  16. copilot_session_usage-0.6.0/.github/skills/gh-release-notes/SKILL.md +0 -255
  17. copilot_session_usage-0.6.0/CONTRIBUTING.md +0 -49
  18. copilot_session_usage-0.6.0/src/copilot_session_usage/data/models-and-pricing.lock +0 -7
  19. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.editorconfig +0 -0
  20. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.gitattributes +0 -0
  21. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  22. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  23. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/changes/requests/skill-breakdown/01-request.md +0 -0
  24. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/guidelines/git-commit-message.guideline.md +0 -0
  25. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/guidelines/knowledge-base.guidelines.md +0 -0
  26. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/pull_request_template.md +0 -0
  27. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/skills/consolidate-knowledge-base/SKILL.md +0 -0
  28. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/skills/record-finding/SKILL.md +0 -0
  29. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/workflows/ci.yml +0 -0
  30. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.github/workflows/publish.yml +0 -0
  31. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.gitignore +0 -0
  32. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/.readthedocs.yaml +0 -0
  33. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/CHANGELOG.md +0 -0
  34. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/LICENSE +0 -0
  35. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/README.md +0 -0
  36. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/_static/changelog.js +0 -0
  37. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/_static/custom.css +0 -0
  38. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/changelog.md +0 -0
  39. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/conf.py +0 -0
  40. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/explanation/how-cost-estimation-works.md +0 -0
  41. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/explanation/index.md +0 -0
  42. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/how-to/add-commit-trailer.md +0 -0
  43. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/how-to/analyze-specific-session.md +0 -0
  44. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/how-to/batch-and-spending.md +0 -0
  45. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/how-to/export-json.md +0 -0
  46. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/how-to/index.md +0 -0
  47. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/how-to/wsl2.md +0 -0
  48. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/index.md +0 -0
  49. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/installation.md +0 -0
  50. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/reference/api.md +0 -0
  51. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/reference/cli.md +0 -0
  52. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/reference/index.md +0 -0
  53. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/reference/pricing.md +0 -0
  54. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/tutorials/getting-started.md +0 -0
  55. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/docs/source/tutorials/index.md +0 -0
  56. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/justfile +0 -0
  57. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Base.schema.yaml +0 -0
  58. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Concept.schema.yaml +0 -0
  59. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Experiment.schema.yaml +0 -0
  60. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Finding.schema.yaml +0 -0
  61. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Hypothesis.schema.yaml +0 -0
  62. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Outcome.schema.yaml +0 -0
  63. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Playbook.schema.yaml +0 -0
  64. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Principle.schema.yaml +0 -0
  65. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Reference.schema.yaml +0 -0
  66. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/_schema/Structure.schema.yaml +0 -0
  67. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/concepts/copilot-cli.md +0 -0
  68. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/concepts/index.md +0 -0
  69. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/concepts/overview.md +0 -0
  70. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/concepts/session-cost-analysis.md +0 -0
  71. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/concepts/threshold-based-pricing.md +0 -0
  72. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/experiments/index.md +0 -0
  73. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/experiments/verify-subagent-cost-attribution.md +0 -0
  74. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/findings/2026.07.02-00.00-subagent-logs-runsubagent-prefix.md +0 -0
  75. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/findings/2026.07.02-22.00-title-generation-not-counted-as-model-turn.md +0 -0
  76. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/findings/2026.07.02-23.00-cache-write-approximation.md +0 -0
  77. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/guides/automation-scripts.md +0 -0
  78. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/guides/cost-optimization.md +0 -0
  79. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/guides/index.md +0 -0
  80. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/guides/wsl2-setup.md +0 -0
  81. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/ideas/index.md +0 -0
  82. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/ideas/multi-session-efficiency-analytics.md +0 -0
  83. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/index.md +0 -0
  84. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/log.md +0 -0
  85. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/principles/findings-are-immutable.md +0 -0
  86. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/principles/index.md +0 -0
  87. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/reference/debug-log-format.md +0 -0
  88. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/reference/index.md +0 -0
  89. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/reference/pricing-formats.md +0 -0
  90. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/structures/cache-cost-approximation.md +0 -0
  91. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/structures/index.md +0 -0
  92. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/structures/knowledge-base-information-types.md +0 -0
  93. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/structures/session-discovery-algorithm.md +0 -0
  94. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/structures/subagent-cost-tracking.md +0 -0
  95. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/knowledge/structures/vscode-copilot-extension.md +0 -0
  96. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/pyproject.toml +0 -0
  97. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/scripts/refresh_pricing.py +0 -0
  98. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/skills/copilot-session-usage/SKILL.md +0 -0
  99. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/__init__.py +0 -0
  100. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/_internal/__init__.py +0 -0
  101. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/_internal/copilot_cli.py +0 -0
  102. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/_internal/core.py +0 -0
  103. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/_internal/git.py +0 -0
  104. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/_internal/vscode.py +0 -0
  105. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/api.py +0 -0
  106. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/cli.py +0 -0
  107. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/data/__init__.py +0 -0
  108. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/src/copilot_session_usage/data/custom-models-pricing.yml +0 -0
  109. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/conftest.py +0 -0
  110. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/test_api.py +0 -0
  111. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/test_cli.py +0 -0
  112. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/test_core.py +0 -0
  113. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/test_coverage_gaps.py +0 -0
  114. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/test_git.py +0 -0
  115. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/test_rendering.py +0 -0
  116. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/test_vscode.py +0 -0
  117. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/tests/test_vscode_platform.py +0 -0
  118. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/uv.lock +0 -0
  119. {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.4}/uv.toml +0 -0
@@ -0,0 +1,325 @@
1
+ ---
2
+ name: gh-release-notes
3
+ description: Generate end-user-friendly GitHub release notes from the actual diff between releases, including user impact, examples, breaking changes, and public documentation links.
4
+ argument-hint: "from_tag=... to_tag=... repo_path=..."
5
+ user-invocable: true
6
+ ---
7
+
8
+ # Release Notes Generator (Git Diff Based)
9
+
10
+ Generate **end-user-friendly, user-impact-only** release notes by analyzing the actual changes between releases.
11
+ No scripts required — use git commands to understand what changed and why it matters to someone using the product.
12
+
13
+ The output is meant to be **copy-pasted into a GitHub Release**. It must contain release-note sections only: never add a document title, preamble, file summary, commit summary, or closing separator.
14
+
15
+ ---
16
+
17
+ ## Quick Start
18
+
19
+ Provide your repository and range:
20
+
21
+ ```
22
+ Generate release notes from v1.0.0 to v1.1.0 in /path/to/repo
23
+ ```
24
+
25
+ Or reference the last release:
26
+
27
+ ```
28
+ What changed since the last release tag?
29
+ ```
30
+
31
+ ---
32
+
33
+ ## What It Does
34
+
35
+ 1. **Reads actual diffs** — examines code changes, not just commit messages
36
+ 3. **Applies a user-impact gate** — includes a change only when a user-visible behavior, supported interface, user workflow, output, compatibility guarantee, or public documentation experience changed
37
+ 4. **Interprets for end-users** — no technical jargon, functions, variable names, file paths, or implementation summaries
38
+ 5. **Categorizes intelligently** — Features, Enhancements, Bug Fixes, Breaking Changes, or a no-product-impact classification
39
+ 6. **Adds concrete examples** — shows what users see or can do after a qualifying change
40
+ 7. **Links to public docs** — points to published documentation, not repo paths
41
+ 8. **Consolidates related changes** — groups related diffs and eliminates back-and-forth noise
42
+ 9. **Outputs clean markdown** — ready to paste into a GitHub Release note
43
+
44
+ ---
45
+
46
+ ## Input
47
+
48
+ Accept either:
49
+
50
+ - **Natural language**: "Show release notes from v1.2.0 to v1.3.0"
51
+ - **Range spec**: `from_tag=v1.2.0 to_tag=v1.3.0 repo_path=/path/to/repo`
52
+ - **Last release**: `since_tag=v1.2.0` (everything from tag to HEAD)
53
+
54
+ Required:
55
+ - Repository path (optional: defaults to current directory)
56
+ - Range: `from_tag` + `to_tag`, OR `since_tag`, OR `last_n_commits`
57
+
58
+ ---
59
+
60
+ ## Analysis Process
61
+
62
+ ### Step 0: Apply the release-worthiness gate
63
+
64
+ Before writing any bullet, ask: **What can a user do, observe, configure, rely on, or learn differently after this change?** Require evidence from the diff, public CLI/API help, supported configuration, user-facing output, migration behavior, or published documentation.
65
+
66
+ Include a change only if it has at least one of these effects:
67
+
68
+ - Adds, removes, fixes, or changes a user-facing feature, command, API, configuration option, output, error message, compatibility guarantee, or supported platform.
69
+ - Changes runtime behavior in a way users can observe, such as performance, reliability, pricing data, security behavior, or data handling.
70
+ - Changes public documentation that users actually consume to operate the product, including a new guide, changed instructions, or migration guidance.
71
+
72
+ Do **not** infer user impact from a commit type, changed filename, test coverage, or the fact that a change is large. If the evidence does not show a user consequence, exclude it.
73
+
74
+ ### Step 1: Collect Commits
75
+ ```bash
76
+ git log v1.0.0..v1.1.0 --oneline --no-merges
77
+ ```
78
+ Gather all commits in the specified range with their messages.
79
+
80
+ ### Step 2: Examine relevant diffs
81
+ ```bash
82
+ git diff v1.0.0..v1.1.0 -- . ':(exclude).github' ':(exclude)skills' ':(exclude)guidelines'
83
+ ```
84
+ Read actual code changes line-by-line to understand behavior. Inspect excluded paths only when needed to verify whether they caused a direct user-visible consequence; never report the paths themselves.
85
+
86
+ Treat these as non-release content by default:
87
+
88
+ - CI/CD workflows, automation, release jobs, repository settings, and bot configuration
89
+ - Internal skills, agent prompts, contributor guidelines, engineering process, and maintainer runbooks
90
+ - Tests, fixtures, formatting, linting, refactors, type annotations, and code organization
91
+ - Dependency, lockfile, build, packaging, or development-environment changes without a user-visible runtime consequence
92
+ - File counts, changed-file lists, commit counts, authors, implementation details, and internal URLs
93
+
94
+ These exclusions can be overridden only when the diff proves a direct user impact, such as a packaging change that changes the installable artifact or a security fix that changes behavior for users.
95
+
96
+ ### Step 3: Interpret qualifying changes
97
+
98
+ Translate technical changes into user impact:
99
+
100
+ | Code Change | User Impact |
101
+ |-------------|------------|
102
+ | `+ const darkMode = true` in settings | "Dark mode toggle now available in settings" |
103
+ | Deleted login retry logic | "Removed automatic retry on login timeout" |
104
+ | `+ validateEmail()` function | "Email validation improved during signup" |
105
+ | Updated database schema version | "Database schema upgraded (run migration)" |
106
+ | Added 10+ calls to cache layer | "Improved performance on large operations" |
107
+ | Removed old CSV export code | "CSV export removed; use Excel or PDF instead" |
108
+
109
+ **Key: Focus on the user's experience, not the code implementation.**
110
+
111
+ Never turn a repository change into a release note merely by paraphrasing it. For example, “added CI workflow,” “updated contributor guidelines,” “improved project metadata,” and “7 files changed” are not release notes.
112
+
113
+ ### Step 4: Identify Breaking Changes
114
+
115
+ Breaking changes come from:
116
+ - **Commit messages** containing: "BREAKING", "Breaking", "!:"
117
+ - **Diffs showing**: removed public APIs, changed file formats, data migrations
118
+ - **Config changes**: renamed settings, changed defaults
119
+
120
+ ### Step 5: Consolidate
121
+ - If a feature was added then removed → don't mention it
122
+ - If something changed multiple times → only note the final state
123
+ - If multiple commits fix the same issue → merge into one bullet
124
+
125
+ ### Step 6: Categorize & Format
126
+
127
+ Organize qualifying changes into buckets. **Only include sections that have content.** Omit empty sections entirely. Do not add a title heading.
128
+
129
+ If there are no qualifying product changes, use exactly one concise fallback block. Keep its structure consistent across releases while adapting the wording to the evidence:
130
+
131
+ - `**Maintenance**` for a maintenance release containing internal upkeep, CI, release automation, dependency/build work, refactors, or other operational changes
132
+ - `**Documentation**` for a documentation-update release whose meaningful outcome is public user documentation, even when no runtime behavior changed
133
+ - `**Internal**` for an internal release containing changes intentionally limited to maintainers, contributors, or internal tooling
134
+
135
+ Choose the most accurate fallback; do not list the underlying files or tasks. Follow the label with one short paragraph that says what was maintained or documented and whether core product functionality changed. Do not manufacture examples or links for either.
136
+ For a no-product-impact fallback, do not name CI, workflows, release automation,
137
+ internal guidelines, tests, commits, pull requests, or individual files. Keep the
138
+ paragraph generic and focused on the absence of user-facing behavior changes.
139
+
140
+ ```markdown
141
+ ## New Features
142
+ - Added dark mode toggle in settings
143
+ - New PDF export option
144
+
145
+ ## Enhancements
146
+ - Improved search performance (now supports partial matches)
147
+ - Faster file opening for large documents
148
+
149
+ ## Bug Fixes
150
+ - Fixed login failures on slow connections
151
+ - Resolved crash when uploading 10MB+ files
152
+
153
+ ## Breaking Changes
154
+ - Database schema updated — run migration before upgrading
155
+ - CSV export removed; use Excel or PDF instead
156
+
157
+ ## Examples
158
+ - Dark mode can be enabled in Settings → Appearance → Theme
159
+ - CSV export is no longer available; choose Excel or PDF from Export menu
160
+
161
+ ## Documentation
162
+ - [Dark mode guide](https://docs.example.com/settings#dark-mode)
163
+ - [Migration notes](https://docs.example.com/upgrade#database)
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Workflow for Agent
169
+
170
+ 1. **Parse input** — extract `from_tag`, `to_tag`, `repo_path`, and optional filters
171
+ 2. **Discover public docs URL** — inspect `README.md`, `pyproject.toml`, `mkdocs.yml`, `docs/conf.py`, or `.readthedocs.yml` for the published documentation URL. Prefer ReadTheDocs, GitHub Pages, or the project's public docs site. If none is found, omit doc links.
172
+ 3. **Fetch commits** — run `git log` with range, collect hashes and messages
173
+ 4. **Read diffs per file** — use `git show <hash>` for each relevant commit and examine changed behavior, not just filenames
174
+ 5. **Apply the user-impact gate** — discard CI, internal, process, and implementation-only changes unless the diff proves direct user impact
175
+ 6. **Interpret impact** — state what users can do, observe, configure, rely on, or learn differently
176
+ 7. **Detect breaking changes** — scan for BREAKING markers, public API removals, format changes, migrations, and changed defaults
177
+ 8. **Group by category** — assign each qualifying change to **New Features**, **Enhancements**, **Bug Fixes**, **Breaking Changes**, **Examples**, or **Documentation**
178
+ 9. **Build examples** — for each user-facing change, use README, public docs, tests, or CLI help as evidence and add a short example only when it clarifies the user outcome
179
+ 10. **Consolidate** — merge related items, remove duplicates and flip-flops
180
+ 11. **Use a fallback** — if no product change qualifies, emit exactly one of **Maintenance**, **Documentation**, or **Internal**
181
+ 12. **Format markdown** — generate clean section headings and bullets with no title, preamble, footer, file summary, or commit summary
182
+ 13. **Use public docs links** — every Documentation bullet and every feature/enhancement docs reference must use the public URL with a fragment identifier, not a repo-relative path
183
+
184
+ ---
185
+
186
+ ## Output Format
187
+
188
+ **Clean markdown** for a GitHub Release body:
189
+
190
+ ```markdown
191
+ ## New Features
192
+ - Added dark mode toggle in settings
193
+ - New PDF export option
194
+
195
+ ## Enhancements
196
+ - Improved search performance (supports partial matches)
197
+ - Faster file opening for large documents
198
+
199
+ ## Bug Fixes
200
+ - Fixed login failures on slow connections
201
+ - Resolved crash when uploading 10MB+ files
202
+
203
+ ## Breaking Changes
204
+ - Database schema updated — run migration before upgrading
205
+
206
+ ## Examples
207
+ - Enable dark mode from Settings → Appearance → Theme
208
+ - Export a report as PDF from the File → Export menu
209
+
210
+ ## Documentation
211
+ - [Dark mode guide](https://docs.example.com/settings#dark-mode)
212
+ - [Upgrade instructions](https://docs.example.com/upgrade#database)
213
+ ```
214
+
215
+ For a release with no runtime product impact, use this consistent shape:
216
+
217
+ ```markdown
218
+ **Maintenance**
219
+
220
+ This release primarily includes updates to the knowledge base documentation and internal repository structure. No changes to the core product functionality or user-facing features.
221
+ ```
222
+
223
+ **Key Rules:**
224
+ - One line per bullet point
225
+ - No sub-bullets or elaborate descriptions
226
+ - User impact only (not implementation details, changed-file summaries, CI, internal process, or contributor guidance)
227
+ - Do not include a title heading; the GitHub Release supplies the title
228
+ - Use public documentation URLs; never use repo-relative paths like `docs/...` or `README.md`
229
+ - Use fragment identifiers (`#section-name`) to point to specific docs sections
230
+ - Add an **Examples** section when the diff shows a CLI command, API call, config snippet, or before/after behavior
231
+ - Add a **Documentation** section only when public user documentation changed in a way users need or benefit from; never report internal guidelines or maintainer documentation
232
+ - Multiple links OK if they point to different topics
233
+ - Omit any section that has no bullets
234
+ - If no user-facing change qualifies, emit exactly one concise bold `Maintenance`, `Documentation`, or `Internal` block followed by one explanatory paragraph
235
+ - Never include file counts, changed-file lists, commit metadata, CI/workflow summaries, or a closing separator
236
+ - Do not add a "Notes", "Miscellaneous", or "Other" catch-all section
237
+
238
+ ---
239
+
240
+ ## Non-interactive automation mode
241
+
242
+ When this skill is invoked by a CI job with an explicit output-file request:
243
+
244
+ - Honor the requested tag range and repository path exactly.
245
+ - Treat the requested output file as mandatory. Writing it is the only successful completion condition.
246
+ - Use the `create` file tool when the requested file does not exist, or the `edit` file tool when it already exists.
247
+ - After writing, use the `read` file tool to verify that the requested file exists and contains the final release-note Markdown.
248
+ - Do not modify, commit, or push any other repository files.
249
+ - The output file must contain only the final release-note Markdown, without an explanation, title heading, or code fence.
250
+ - The first line must be exactly one of: `## New Features`, `## Enhancements`, `## Bug Fixes`, `## Breaking Changes`, `## Examples`, `## Documentation`, `**Maintenance**`, `**Documentation**`, or `**Internal**`.
251
+ - Do not write a preamble, title, code fence, or explanatory text before the first release-note section or fallback label.
252
+ - Never use the Copilot response stream as output. The caller may discard it after the file is written.
253
+ - Do not report the release notes only in the response. If the file cannot be written or verified, the task has failed.
254
+ - Preserve the user-impact categories, examples, breaking-change detection, and public documentation links described above.
255
+
256
+ ## How to Use This Skill in a Session
257
+
258
+ **User Query:**
259
+ ```
260
+ Generate release notes from v2.1.0 to v2.2.0 for /path/to/my-app
261
+ ```
262
+
263
+ **Agent Workflow:**
264
+ 1. Navigate to repo: `cd /path/to/my-app`
265
+ 2. Fetch commits: `git log v2.1.0..v2.2.0 --oneline --no-merges`
266
+ 3. For each commit, examine changes: `git show <hash>`
267
+ 4. Interpret: What's the user impact? (not the code details)
268
+ 5. Categorize: Feature? Bug fix? Breaking change?
269
+ 6. Consolidate: Merge similar items
270
+ 7. Format: Clean markdown with categories
271
+ 8. Output: Save to the requested output file, such as `release-notes.md`
272
+
273
+ ---
274
+
275
+ ## Best Practices
276
+
277
+ ✅ **Do:**
278
+ - Read actual diffs to understand changes
279
+ - Use end-user language ("improved performance" not "optimized O(n) loop")
280
+ - Require evidence of a user-visible consequence before including a change
281
+ - Include breaking changes prominently
282
+ - Group related changes
283
+ - Add concrete examples drawn from README, docs, tests, or CLI help in the diff
284
+ - Link to the project's public documentation site (ReadTheDocs, GitHub Pages, etc.)
285
+ - Omit empty sections
286
+
287
+ ❌ **Don't:**
288
+ - Copy commit messages verbatim
289
+ - Include function/variable names
290
+ - Mention internal refactors users won't notice
291
+ - Include dependency bumps or build changes unless they are user-visible
292
+ - Include secrets, passwords, or internal URLs
293
+ - Use repo-relative paths like `docs/source/how-to/...` or `README.md`
294
+ - Report CI, workflows, internal skills, contributor guidelines, maintainer process, file counts, or changed-file lists as release content
295
+ - Add a title heading to the generated body
296
+ - Make up changes not shown in diffs
297
+
298
+ ---
299
+
300
+ ## Common Patterns
301
+
302
+ **Performance improvements:**
303
+ > "Improved search speed when filtering 1000+ records"
304
+
305
+ **New integrations:**
306
+ > "Added support for OAuth login via GitHub"
307
+
308
+ **Data format changes:**
309
+ > "Settings file now uses JSON instead of YAML (auto-converted on first run)"
310
+
311
+ **Removed features:**
312
+ > "Removed IE 11 support to modernize codebase"
313
+
314
+ **API changes:**
315
+ > "Changed user profile endpoint response format (see migration guide)"
316
+
317
+ ---
318
+
319
+ ## Limitations
320
+
321
+ - Requires a git repository with proper tags
322
+ - Complex changes may need human interpretation
323
+ - Very large diffs should be reduced to their evidenced user impact; never summarize them by file count
324
+ - Works best with semantic versioning (v1.0.0 format)
325
+ - Needs meaningful commit messages for best results, but commit messages alone are never evidence of user impact
@@ -0,0 +1,72 @@
1
+ name: Refresh GitHub model pricing
2
+
3
+ on:
4
+ schedule:
5
+ # Run once a day, shortly after GitHub's documentation refresh window.
6
+ - cron: "17 2 * * *"
7
+ workflow_dispatch:
8
+
9
+ concurrency:
10
+ group: refresh-pricing
11
+ cancel-in-progress: false
12
+
13
+ permissions:
14
+ contents: write
15
+ pull-requests: write
16
+
17
+ jobs:
18
+ refresh-pricing:
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - name: Check out repository
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v5
27
+ with:
28
+ enable-cache: true
29
+ python-version: "3.12"
30
+
31
+ - name: Install just
32
+ uses: extractions/setup-just@v2
33
+
34
+ - name: Install dependencies
35
+ run: uv sync --frozen --all-groups
36
+
37
+ - name: Refresh pricing
38
+ run: just refresh-pricing
39
+
40
+ - name: Check for upstream pricing changes
41
+ id: changes
42
+ shell: bash
43
+ run: |
44
+ pricing_file="src/copilot_session_usage/data/models-and-pricing.yml"
45
+ if git diff --quiet -- "$pricing_file"; then
46
+ echo "changed=false" >> "$GITHUB_OUTPUT"
47
+ echo "No pricing YAML changes detected."
48
+ else
49
+ echo "changed=true" >> "$GITHUB_OUTPUT"
50
+ echo "Pricing YAML changed:"
51
+ git diff --stat -- "$pricing_file"
52
+ fi
53
+
54
+ - name: Create or update pull request
55
+ if: steps.changes.outputs.changed == 'true'
56
+ uses: peter-evans/create-pull-request@v7
57
+ with:
58
+ token: ${{ secrets.GITHUB_TOKEN }}
59
+ base: main
60
+ branch: automation/refresh-pricing
61
+ delete-branch: true
62
+ commit-message: "chore(pricing): refresh GitHub model pricing"
63
+ title: "chore(pricing): refresh GitHub model pricing"
64
+ body: |
65
+ This automated pull request updates the bundled GitHub Copilot model pricing data.
66
+
67
+ Source: https://raw.githubusercontent.com/github/docs/main/data/tables/copilot/models-and-pricing.yml
68
+
69
+ The update was generated by running `just refresh-pricing`.
70
+ add-paths: |
71
+ src/copilot_session_usage/data/models-and-pricing.yml
72
+ src/copilot_session_usage/data/models-and-pricing.lock
@@ -0,0 +1,134 @@
1
+ name: Generate release notes (manual)
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ tag:
7
+ description: "Existing version tag to generate a draft release for"
8
+ required: true
9
+ type: string
10
+
11
+ concurrency:
12
+ group: release-notes-${{ github.ref }}
13
+ cancel-in-progress: false
14
+
15
+ permissions:
16
+ contents: write
17
+
18
+ jobs:
19
+ generate-release-notes:
20
+ runs-on: ubuntu-latest
21
+
22
+ steps:
23
+ - name: Check out tagged source
24
+ uses: actions/checkout@v4
25
+ with:
26
+ fetch-depth: 0
27
+ ref: ${{ inputs.tag || github.ref }}
28
+
29
+ - name: Resolve release range
30
+ id: range
31
+ shell: bash
32
+ env:
33
+ TARGET_TAG: ${{ inputs.tag || github.ref_name }}
34
+ run: |
35
+ set -euo pipefail
36
+
37
+ if [[ ! "$TARGET_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-].*)?$ ]]; then
38
+ echo "::error::Expected a semantic-version tag such as v0.7.0, got '$TARGET_TAG'."
39
+ exit 1
40
+ fi
41
+
42
+ previous_tag="$(git tag --sort=-v:refname --merged "$TARGET_TAG" \
43
+ | awk -v current="$TARGET_TAG" '$0 != current { print; exit }')"
44
+
45
+ if [[ -z "$previous_tag" ]]; then
46
+ echo "::error::Could not find a previous release tag for $TARGET_TAG."
47
+ exit 1
48
+ fi
49
+
50
+ echo "target_tag=$TARGET_TAG" >> "$GITHUB_OUTPUT"
51
+ echo "previous_tag=$previous_tag" >> "$GITHUB_OUTPUT"
52
+ echo "Generating notes from $previous_tag to $TARGET_TAG."
53
+
54
+ - name: Verify release-note skill
55
+ env:
56
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
57
+ run: |
58
+ set -euo pipefail
59
+
60
+ if [[ -z "${COPILOT_GITHUB_TOKEN:-}" ]]; then
61
+ echo "::error::The COPILOT_GITHUB_TOKEN repository secret is not configured."
62
+ echo "Create a fine-grained PAT with the Copilot Requests permission and add it as a repository secret."
63
+ exit 1
64
+ fi
65
+
66
+ if ! gh copilot -- skill list | grep -Fq 'gh-release-notes'; then
67
+ echo "::error::The gh-release-notes skill was not discovered by GitHub CLI."
68
+ exit 1
69
+ fi
70
+
71
+ - name: Generate release notes with the skill
72
+ env:
73
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
74
+ PREVIOUS_TAG: ${{ steps.range.outputs.previous_tag }}
75
+ TARGET_TAG: ${{ steps.range.outputs.target_tag }}
76
+ run: |
77
+ set -euo pipefail
78
+
79
+ output_file="release-notes.md"
80
+ rm -f "$output_file"
81
+
82
+ prompt="Use the /gh-release-notes skill.
83
+
84
+ Generate the final release notes for ${TARGET_TAG}, covering the actual changes from ${PREVIOUS_TAG} to ${TARGET_TAG} in ${GITHUB_WORKSPACE}.
85
+
86
+ Follow the skill's diff-based analysis process. Include only changes with a proven user-facing consequence; exclude CI, workflows, release automation, internal skills, guidelines, tests, file lists, and other repository housekeeping unless the diff proves direct product impact. If there is no product impact, write exactly this fallback block and no other wording: **Maintenance** followed by a blank line and This release primarily includes updates to the knowledge base documentation and internal repository structure. No changes to the core product functionality or user-facing features. Write the final release-note Markdown directly to ${output_file} in the current workspace using the file-writing tool. Do not put the release notes in your response because the response stream is discarded. Do not modify, commit, or push any other repository files."
87
+
88
+ gh copilot -- \
89
+ --prompt "$prompt" \
90
+ --silent \
91
+ --no-ask-user \
92
+ --no-auto-update \
93
+ --no-color \
94
+ --output-format text \
95
+ --disable-builtin-mcps \
96
+ --available-tools='read,create,edit,bash' \
97
+ --allow-tool='read' \
98
+ --allow-tool='write' \
99
+ --allow-tool='shell(git:*)' \
100
+ --allow-url='https://github.com' \
101
+ --allow-url='https://copilot-session-usage.readthedocs.io' \
102
+ > /dev/null
103
+
104
+ if [[ ! -s "$output_file" ]]; then
105
+ echo "::error::The gh-release-notes skill did not create $output_file."
106
+ exit 1
107
+ fi
108
+
109
+ python scripts/validate_release_notes.py "$output_file"
110
+
111
+ - name: Upload generated notes for review
112
+ uses: actions/upload-artifact@v4
113
+ with:
114
+ name: release-notes-${{ steps.range.outputs.target_tag }}
115
+ path: release-notes.md
116
+
117
+ - name: Create draft GitHub release
118
+ env:
119
+ GH_TOKEN: ${{ github.token }}
120
+ TARGET_TAG: ${{ steps.range.outputs.target_tag }}
121
+ run: |
122
+ set -euo pipefail
123
+
124
+ if gh release view "$TARGET_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
125
+ echo "::error::A GitHub Release already exists for $TARGET_TAG."
126
+ exit 1
127
+ fi
128
+
129
+ gh release create "$TARGET_TAG" \
130
+ --repo "$GITHUB_REPOSITORY" \
131
+ --verify-tag \
132
+ --draft \
133
+ --title "$TARGET_TAG" \
134
+ --notes-file release-notes.md