rqmd 0.1.0rc2__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 (127) hide show
  1. rqmd-0.1.0rc2/PKG-INFO +758 -0
  2. rqmd-0.1.0rc2/README.md +729 -0
  3. rqmd-0.1.0rc2/pyproject.toml +75 -0
  4. rqmd-0.1.0rc2/setup.cfg +4 -0
  5. rqmd-0.1.0rc2/src/rqmd/__init__.py +5 -0
  6. rqmd-0.1.0rc2/src/rqmd/__main__.py +10 -0
  7. rqmd-0.1.0rc2/src/rqmd/ai_cli.py +3717 -0
  8. rqmd-0.1.0rc2/src/rqmd/batch_inputs.py +297 -0
  9. rqmd-0.1.0rc2/src/rqmd/cli.py +3949 -0
  10. rqmd-0.1.0rc2/src/rqmd/config.py +340 -0
  11. rqmd-0.1.0rc2/src/rqmd/constants.py +114 -0
  12. rqmd-0.1.0rc2/src/rqmd/default_catalogs.py +47 -0
  13. rqmd-0.1.0rc2/src/rqmd/history.py +920 -0
  14. rqmd-0.1.0rc2/src/rqmd/json_speedups.py +30 -0
  15. rqmd-0.1.0rc2/src/rqmd/markdown_io.py +768 -0
  16. rqmd-0.1.0rc2/src/rqmd/menus.py +720 -0
  17. rqmd-0.1.0rc2/src/rqmd/priority_model.py +254 -0
  18. rqmd-0.1.0rc2/src/rqmd/readme_gen.py +166 -0
  19. rqmd-0.1.0rc2/src/rqmd/render_heuristics.py +88 -0
  20. rqmd-0.1.0rc2/src/rqmd/req_parser.py +956 -0
  21. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/agents/README.md +43 -0
  22. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/agents/rqmd-dev.agent.md +23 -0
  23. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/agents/rqmd-docs.agent.md +23 -0
  24. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/agents/rqmd-explore.agent.md +19 -0
  25. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/agents/rqmd-history.agent.md +23 -0
  26. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/agents/rqmd-requirements.agent.md +23 -0
  27. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/copilot-instructions.md +40 -0
  28. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-brainstorm/SKILL.md +65 -0
  29. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-bundle/SKILL.md +34 -0
  30. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-doc-sync/SKILL.md +31 -0
  31. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-export-context/SKILL.md +35 -0
  32. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-history/SKILL.md +31 -0
  33. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-implement/SKILL.md +42 -0
  34. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-init/SKILL.md +38 -0
  35. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-init-legacy/SKILL.md +39 -0
  36. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-status-maintenance/SKILL.md +31 -0
  37. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-triage/SKILL.md +31 -0
  38. rqmd-0.1.0rc2/src/rqmd/resources/bundle/.github/skills/rqmd-verify/SKILL.md +31 -0
  39. rqmd-0.1.0rc2/src/rqmd/resources/bundle/full.txt +18 -0
  40. rqmd-0.1.0rc2/src/rqmd/resources/bundle/minimal.txt +13 -0
  41. rqmd-0.1.0rc2/src/rqmd/resources/bundle/templates/dev-skill.md +40 -0
  42. rqmd-0.1.0rc2/src/rqmd/resources/bundle/templates/test-skill.md +37 -0
  43. rqmd-0.1.0rc2/src/rqmd/resources/catalogs/priorities.yml +29 -0
  44. rqmd-0.1.0rc2/src/rqmd/resources/catalogs/statuses.yml +38 -0
  45. rqmd-0.1.0rc2/src/rqmd/resources/init/README.md +133 -0
  46. rqmd-0.1.0rc2/src/rqmd/resources/init/chat-handoff-heading.md +1 -0
  47. rqmd-0.1.0rc2/src/rqmd/resources/init/chat-init-notice.md +1 -0
  48. rqmd-0.1.0rc2/src/rqmd/resources/init/domain-example.md +45 -0
  49. rqmd-0.1.0rc2/src/rqmd/resources/init/init-handoff-base.md +10 -0
  50. rqmd-0.1.0rc2/src/rqmd/resources/init/init-handoff-bundle-followup.md +4 -0
  51. rqmd-0.1.0rc2/src/rqmd/resources/init/init-handoff-tail.md +4 -0
  52. rqmd-0.1.0rc2/src/rqmd/resources/init/init-interview.yml +279 -0
  53. rqmd-0.1.0rc2/src/rqmd/resources/init/init-strategy-existing-markdown.md +1 -0
  54. rqmd-0.1.0rc2/src/rqmd/resources/init/init-strategy-force-legacy.md +1 -0
  55. rqmd-0.1.0rc2/src/rqmd/resources/init/init-strategy-marker-count.md +1 -0
  56. rqmd-0.1.0rc2/src/rqmd/resources/init/init-strategy-starter-default.md +1 -0
  57. rqmd-0.1.0rc2/src/rqmd/resources/init/legacy-issue-domain.md +8 -0
  58. rqmd-0.1.0rc2/src/rqmd/resources/init/legacy-readme-interview-notes.md +5 -0
  59. rqmd-0.1.0rc2/src/rqmd/resources/init/legacy-readme-seeded-note.md +3 -0
  60. rqmd-0.1.0rc2/src/rqmd/resources/init/legacy-source-domain.md +12 -0
  61. rqmd-0.1.0rc2/src/rqmd/resources/init/legacy-workflow-domain.md +16 -0
  62. rqmd-0.1.0rc2/src/rqmd/resources/init/preview-only.md +1 -0
  63. rqmd-0.1.0rc2/src/rqmd/resources/init/project-config.yml +9 -0
  64. rqmd-0.1.0rc2/src/rqmd/resources/init/scaffold-already-present.md +1 -0
  65. rqmd-0.1.0rc2/src/rqmd/resources/init/scaffold-created-heading.md +1 -0
  66. rqmd-0.1.0rc2/src/rqmd/resources/init/scaffold-empty-confirm.md +1 -0
  67. rqmd-0.1.0rc2/src/rqmd/resources/init/scaffold-prefix-heading.md +1 -0
  68. rqmd-0.1.0rc2/src/rqmd/resources/init/scaffold-prefix-tip.md +1 -0
  69. rqmd-0.1.0rc2/src/rqmd/resources/init/startup-empty-dir.md +2 -0
  70. rqmd-0.1.0rc2/src/rqmd/resources/init/startup-missing-dir.md +2 -0
  71. rqmd-0.1.0rc2/src/rqmd/resources/init/startup-missing-index.md +2 -0
  72. rqmd-0.1.0rc2/src/rqmd/resources/init/startup-no-docs.md +8 -0
  73. rqmd-0.1.0rc2/src/rqmd/rollup_config.py +299 -0
  74. rqmd-0.1.0rc2/src/rqmd/status_model.py +421 -0
  75. rqmd-0.1.0rc2/src/rqmd/status_update.py +553 -0
  76. rqmd-0.1.0rc2/src/rqmd/summary.py +364 -0
  77. rqmd-0.1.0rc2/src/rqmd/target_selection.py +355 -0
  78. rqmd-0.1.0rc2/src/rqmd/theme.py +132 -0
  79. rqmd-0.1.0rc2/src/rqmd/workflows.py +2853 -0
  80. rqmd-0.1.0rc2/src/rqmd.egg-info/PKG-INFO +758 -0
  81. rqmd-0.1.0rc2/src/rqmd.egg-info/SOURCES.txt +125 -0
  82. rqmd-0.1.0rc2/src/rqmd.egg-info/dependency_links.txt +1 -0
  83. rqmd-0.1.0rc2/src/rqmd.egg-info/entry_points.txt +5 -0
  84. rqmd-0.1.0rc2/src/rqmd.egg-info/requires.txt +10 -0
  85. rqmd-0.1.0rc2/src/rqmd.egg-info/top_level.txt +1 -0
  86. rqmd-0.1.0rc2/tests/test_RQMD_core_022.py +140 -0
  87. rqmd-0.1.0rc2/tests/test_RQMD_core_024.py +142 -0
  88. rqmd-0.1.0rc2/tests/test_RQMD_interactive_012.py +112 -0
  89. rqmd-0.1.0rc2/tests/test_RQMD_interactive_013.py +307 -0
  90. rqmd-0.1.0rc2/tests/test_RQMD_interactive_018.py +110 -0
  91. rqmd-0.1.0rc2/tests/test_RQMD_interactive_022.py +271 -0
  92. rqmd-0.1.0rc2/tests/test_RQMD_priority_008_undo_history.py +98 -0
  93. rqmd-0.1.0rc2/tests/test_RQMD_priority_011.py +205 -0
  94. rqmd-0.1.0rc2/tests/test_RQMD_priority_012.py +160 -0
  95. rqmd-0.1.0rc2/tests/test_RQMD_time_002_timeline.py +155 -0
  96. rqmd-0.1.0rc2/tests/test_RQMD_time_005_compare.py +267 -0
  97. rqmd-0.1.0rc2/tests/test_RQMD_time_006_actions.py +162 -0
  98. rqmd-0.1.0rc2/tests/test_RQMD_time_007_timeline_filters.py +213 -0
  99. rqmd-0.1.0rc2/tests/test_RQMD_time_009_reports.py +136 -0
  100. rqmd-0.1.0rc2/tests/test_RQMD_time_010_temporal_matrix.py +214 -0
  101. rqmd-0.1.0rc2/tests/test_RQMD_ui_001_screen_write_rendering.py +210 -0
  102. rqmd-0.1.0rc2/tests/test_RQMD_ui_003_non_tty_fallback.py +281 -0
  103. rqmd-0.1.0rc2/tests/test_RQMD_ui_004_minimal_diff_redraw.py +314 -0
  104. rqmd-0.1.0rc2/tests/test_RQMD_ui_005_pagination_cursor.py +470 -0
  105. rqmd-0.1.0rc2/tests/test_RQMD_ui_006_footer_legend.py +362 -0
  106. rqmd-0.1.0rc2/tests/test_RQMD_ui_007_accessibility.py +75 -0
  107. rqmd-0.1.0rc2/tests/test_RQMD_ui_008_resize_handling.py +68 -0
  108. rqmd-0.1.0rc2/tests/test_RQMD_ui_009_performance_heuristics.py +81 -0
  109. rqmd-0.1.0rc2/tests/test_RQMD_ui_010_testing_ci.py +50 -0
  110. rqmd-0.1.0rc2/tests/test_RQMD_undo_002_persistence.py +88 -0
  111. rqmd-0.1.0rc2/tests/test_RQMD_undo_003_branching.py +271 -0
  112. rqmd-0.1.0rc2/tests/test_RQMD_undo_004_confirmation.py +261 -0
  113. rqmd-0.1.0rc2/tests/test_RQMD_undo_005_storage_backend.py +261 -0
  114. rqmd-0.1.0rc2/tests/test_RQMD_undo_006_metadata.py +81 -0
  115. rqmd-0.1.0rc2/tests/test_RQMD_undo_009_history_api.py +404 -0
  116. rqmd-0.1.0rc2/tests/test_RQMD_undo_010_matrix.py +140 -0
  117. rqmd-0.1.0rc2/tests/test_ai_cli.py +1962 -0
  118. rqmd-0.1.0rc2/tests/test_automation_api.py +3043 -0
  119. rqmd-0.1.0rc2/tests/test_colors.py +62 -0
  120. rqmd-0.1.0rc2/tests/test_config.py +656 -0
  121. rqmd-0.1.0rc2/tests/test_core_engine.py +1190 -0
  122. rqmd-0.1.0rc2/tests/test_interactive.py +2803 -0
  123. rqmd-0.1.0rc2/tests/test_json_speedups.py +36 -0
  124. rqmd-0.1.0rc2/tests/test_performance.py +124 -0
  125. rqmd-0.1.0rc2/tests/test_portability_packaging_docs.py +924 -0
  126. rqmd-0.1.0rc2/tests/test_priority_features.py +608 -0
  127. rqmd-0.1.0rc2/tests/test_priority_updates.py +132 -0
rqmd-0.1.0rc2/PKG-INFO ADDED
@@ -0,0 +1,758 @@
1
+ Metadata-Version: 2.4
2
+ Name: rqmd
3
+ Version: 0.1.0rc2
4
+ Summary: Requirements Markdown manager CLI tool, `rqmd`. GitHub Copilot AI integration supported via `rqmd-ai init`.
5
+ Author: RQMD Contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/example/rqmd
8
+ Project-URL: Repository, https://github.com/example/rqmd
9
+ Project-URL: Issues, https://github.com/example/rqmd/issues
10
+ Project-URL: Changelog, https://github.com/example/rqmd/blob/main/CHANGELOG.md
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Software Development :: Documentation
18
+ Classifier: Topic :: Utilities
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: click>=8.1.0
22
+ Requires-Dist: tabulate>=0.9.0
23
+ Requires-Dist: PyYAML>=6.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
26
+ Requires-Dist: pytest-timeout>=2.3.1; extra == "dev"
27
+ Provides-Extra: speedups
28
+ Requires-Dist: orjson>=3.10.0; extra == "speedups"
29
+
30
+ # rqmd
31
+
32
+ Reusable requirements and acceptance-requirements workflow CLI.
33
+
34
+ rqmd: Human-readable + AI-readable requirements for Requirements Driven Development (RDD).
35
+
36
+ Project links:
37
+ - GitHub: https://github.com/example/rqmd
38
+ - PyPI: https://pypi.org/project/rqmd/
39
+
40
+ This package extracts the markdown status-tracking workflow used in this repository into a portable Python package that can be copied to other projects and eventually published to PyPI.
41
+
42
+ ## What this tool does
43
+
44
+ - Scans requirement markdown files in a requirements directory.
45
+ - Uses `README.md` inside that directory as the requirements index.
46
+ - When `--docs-dir` is omitted, auto-detects the nearest viable requirement index from the current working path.
47
+ - Normalizes `- **Status:** ...` lines to canonical statuses.
48
+ - Parses requirement headers such as `### AC-FOO-001: Title` or `### R-FOO-001: Title`.
49
+ - Regenerates per-file summary blocks:
50
+
51
+ ```md
52
+ <!-- acceptance-status-summary:start -->
53
+ Summary: 10💡 2🔧 3✅ 0⚠️ 0⛔ 1🗑️
54
+ <!-- acceptance-status-summary:end -->
55
+ ```
56
+
57
+ - Supports interactive status editing with keyboard navigation.
58
+ - Supports non-interactive updates for automation/agents.
59
+
60
+ Requirement bodies can be as short as a title plus status line, or include richer detail under the same heading. When both are useful, prefer pairing a short user story (`As a ...`, `I want ...`, `So that ...`) with Given/When/Then acceptance bullets.
61
+
62
+ ## Status model
63
+
64
+ The built-in default status and priority catalogs ship as packaged YAML resources under `src/rqmd/resources/catalogs/`, so changing the shipped defaults no longer requires touching multiple Python tables.
65
+
66
+ - `💡 Proposed`
67
+ - `🔧 Implemented`
68
+ - `✅ Verified`
69
+ - `⚠️ Janky`
70
+ - `⛔ Blocked`
71
+ - `🗑️ Deprecated`
72
+
73
+ ## Priority model (optional field)
74
+
75
+ Requirements can optionally include a `**Priority:**` line alongside the status line. When present, priority metadata supports sorting, filtering, and priority-aware summaries.
76
+
77
+ Default priority levels:
78
+
79
+ - `🔴 P0 - Critical`
80
+ - `🟠 P1 - High`
81
+ - `🟡 P2 - Medium`
82
+ - `🟢 P3 - Low`
83
+
84
+ Example requirement with priority:
85
+
86
+ ```md
87
+ ### AC-FEATURE-001: Core API endpoint
88
+ - **Status:** 🔧 Implemented
89
+ - **Priority:** 🔴 P0 - Critical
90
+ ```
91
+
92
+ Priority is optional; requirements without a priority line parse successfully with `priority: None`.
93
+
94
+ Priority values are normalized case-insensitively, so `p0`, `P0`, `critical`, and `CRITICAL` all map to `🔴 P0 - Critical`.
95
+
96
+ Project config can still override these built-ins with `.rqmd.yml`, `.rqmd.json`, or standalone status/priority catalog files.
97
+
98
+ ## Install (local development)
99
+
100
+ From this folder:
101
+
102
+ ```bash
103
+ uv sync
104
+ ```
105
+
106
+ Install test dependencies:
107
+
108
+ ```bash
109
+ uv sync --extra dev
110
+ ```
111
+
112
+ Install optional native JSON acceleration:
113
+
114
+ ```bash
115
+ uv sync --extra speedups
116
+ ```
117
+
118
+ When `orjson` is installed through the `speedups` extra, rqmd and rqmd-ai use it for JSON export and audit-log serialization while preserving the existing JSON schema and a pure-Python fallback when the extra is absent.
119
+
120
+ Then run:
121
+
122
+ ```bash
123
+ rqmd --help
124
+ ```
125
+
126
+ `reqmd` and `reqmd-ai` remain available as compatibility aliases, but the canonical commands are `rqmd` and `rqmd-ai`.
127
+
128
+ Module entrypoint:
129
+
130
+ ```bash
131
+ python -m rqmd --help
132
+ ```
133
+
134
+ Pre-release alias plan:
135
+
136
+ - `rqmd` remains the canonical package name and primary command for now.
137
+ - `reqmd` and `reqmd-ai` are shipped as compatibility aliases so teams can trial the shorter branding before any package regname decision.
138
+ - Any future package-name rename should happen only after a manual PyPI availability check and a documented compatibility window for existing `rqmd` users.
139
+
140
+ ## Shell completion
141
+
142
+ rqmd uses Click dynamic completion and supports shell activation without maintaining static completion files.
143
+ Completion candidates stay in sync with live requirement docs, including positional target tokens (domain names, requirement IDs, and subsection names) plus positional status/priority filter values such as `Proposed` and `P1`.
144
+
145
+ zsh activation (add to `~/.zshrc`):
146
+
147
+ ```bash
148
+ eval "$(_RQMD_COMPLETE=zsh_source rqmd)"
149
+ ```
150
+
151
+ bash activation (add to `~/.bashrc`):
152
+
153
+ ```bash
154
+ eval "$(_RQMD_COMPLETE=bash_source rqmd)"
155
+ ```
156
+
157
+ fish activation (add to `~/.config/fish/config.fish`):
158
+
159
+ ```fish
160
+ _RQMD_COMPLETE=fish_source rqmd | source
161
+ ```
162
+
163
+ If you are running from a local clone during development without installing the console script, use `python -m rqmd`; completion is provided by the installed `rqmd` console entrypoint.
164
+
165
+ Troubleshooting completion cache refresh:
166
+
167
+ - zsh: `rm -f ~/.zcompdump* && exec zsh`
168
+ - bash: open a new shell session after updating rc files
169
+ - fish: `exec fish` after updating config
170
+
171
+ ## Core commands
172
+
173
+ Check summaries only:
174
+
175
+ ```bash
176
+ rqmd --verify-summaries
177
+ ```
178
+
179
+ Interactive mode:
180
+
181
+ ```bash
182
+ rqmd
183
+ ```
184
+
185
+ Open a specific domain file directly (absolute or repo-root-relative path):
186
+
187
+ ```bash
188
+ rqmd docs/requirements/interactive-ux.md
189
+ ```
190
+
191
+ In non-interactive modes, a positional domain file path scopes operations to that file:
192
+
193
+ ```bash
194
+ rqmd docs/requirements/interactive-ux.md --update AC-EXAMPLE-001=verified
195
+ ```
196
+
197
+ Interactive file and requirement menus now support:
198
+
199
+ - `j` and `k` for next/previous vertical movement alongside arrow keys
200
+ - `gg` to jump to the first visible list position and `G` to jump to the last
201
+ - `Ctrl-U` and `Ctrl-D` for deterministic half-page movement in paged menus
202
+ - `/` and `?` to search forward or backward within the current interactive list
203
+ - `n` and `N` to repeat the last list search in the same or opposite direction
204
+ - compact default footers with `:=help` instead of always showing the full key legend inline
205
+ - `:` to open the full help surface from interactive menus
206
+ - invalid or unmapped keys to playfully toggle the help surface open and closed without losing context
207
+ - `s` to cycle sort columns
208
+ - `d` to toggle ascending/descending
209
+ - `r` to refresh/rescan while preserving the active sort
210
+ - `z` to undo the last recorded history step from a requirement action menu
211
+ - `y` to redo the next recorded history step from a requirement action menu
212
+ - `h` to open the paged history browser from a requirement action menu
213
+
214
+ Inside the history browser, selecting an entry opens a detail view where you can:
215
+
216
+ - press `c` to checkout the selected entry's branch
217
+ - press `l` to save a human-readable label for the selected entry's branch
218
+ - press `x` to discard the selected entry's alternate branch, with an option to save a label first
219
+ - press `p` to cherry-pick the selected commit onto the current branch
220
+ - press `r` to replay the selected entry's branch onto the current branch
221
+ - press `g` to run history gc with confirmation
222
+ - press `G` to run history gc with immediate prune
223
+
224
+ Both interactive gc actions can optionally save a human-readable label on the current history branch before maintenance runs.
225
+
226
+ History retention now uses a conservative default policy of retaining the last 1000 entries or the last 90 days of history metadata before running pack/prune maintenance. You can override that policy in project or user config with a top-level `history_retention` object:
227
+
228
+ ```json
229
+ {
230
+ "history_retention": {
231
+ "retain_last": 500,
232
+ "retain_days": 30,
233
+ "max_size_kib": 2048
234
+ }
235
+ }
236
+ ```
237
+
238
+ `retain_last` and `retain_days` decide which persisted history entries remain navigable after `--history-gc`; `max_size_kib` records when the hidden history repo has crossed a size threshold so maintenance reports can surface it alongside the pack/prune result.
239
+
240
+ Long options also accept unique prefixes, so invocations such as `--proj`, `--docs`, and `--as-j` work when they resolve unambiguously.
241
+
242
+ History operations available in non-interactive mode include:
243
+
244
+ - `rqmd --history`
245
+ - `rqmd --timeline`
246
+ - `rqmd --undo`
247
+ - `rqmd --redo`
248
+ - `rqmd --history-label-branch <branch-name> --history-branch-label <label>`
249
+ - `rqmd --history-discard-branch <branch-name> --history-discard-save-label <label> --force-yes`
250
+ - `rqmd --history-gc --history-gc-save-label <label> --force-yes`
251
+ - `rqmd --history-gc --force-yes`
252
+ - `rqmd --history-gc --history-prune-now --force-yes`
253
+ - `rqmd --history-checkout-branch <branch-name>`
254
+ - `rqmd --history-cherry-pick <entry-index-or-ref> [--history-target-branch <branch-name>]`
255
+ - `rqmd --history-replay-branch <branch-name> [--history-target-branch <branch-name>]`
256
+
257
+ `--history-gc` requires explicit confirmation because it runs maintenance against the hidden `.rqmd/history/rqmd-history` repository. Add `--history-prune-now` to expire reflogs and prune immediately instead of using Git's default grace period.
258
+
259
+ File lists now default to the `name` sort in descending order.
260
+
261
+ You can select a named sort strategy catalog for interactive mode:
262
+
263
+ ```bash
264
+ rqmd --sort-profile standard
265
+ rqmd --sort-profile status-focus
266
+ rqmd --sort-profile alpha-asc
267
+ ```
268
+
269
+ Start rqmd in a new project with the default chat-first flow:
270
+
271
+ ```bash
272
+ rqmd init
273
+ ```
274
+
275
+ `rqmd init` prints a copy/paste handoff prompt for your AI chat. That chat then runs `rqmd-ai init --chat --json`, asks the grouped interview questions, previews the generated files, and applies the bootstrap only after confirmation.
276
+
277
+ Direct scaffold compatibility path:
278
+
279
+ ```bash
280
+ rqmd init --scaffold
281
+ ```
282
+
283
+ `rqmd init --scaffold` is the direct starter scaffold path when you want immediate docs without the chat-first onboarding flow.
284
+ Scaffold content is sourced from repository-managed templates in `src/rqmd/resources/init/README.md` and `src/rqmd/resources/init/domain-example.md`.
285
+
286
+ Allocate the next sequential numeric requirement ID for the active namespace:
287
+
288
+ ```bash
289
+ rqmd --id-namespace TEAM --next-id
290
+ rqmd --id-namespace TEAM --next-id --json
291
+ ```
292
+
293
+ `--next-id` respects the active key prefix, uses at least 3 digits of zero-padding by default, and continues past `999` as `1000`, `1001`, and higher.
294
+
295
+ Set one requirement non-interactively:
296
+
297
+ ```bash
298
+ rqmd --update-id AC-EXAMPLE-001 --update-status implemented
299
+ ```
300
+
301
+ Update priorities non-interactively:
302
+
303
+ ```bash
304
+ rqmd --update-priority AC-EXAMPLE-001=p0
305
+ rqmd --update-priority AC-EXAMPLE-001=critical --update-priority AC-EXAMPLE-002=medium
306
+ ```
307
+
308
+ Batch updates can include `priority` fields, or combine `status` and `priority` in one row:
309
+
310
+ ```json
311
+ {"id":"AC-EXAMPLE-001","priority":"p0"}
312
+ {"id":"AC-EXAMPLE-002","status":"implemented","priority":"medium"}
313
+ ```
314
+
315
+ Use positional filters for fast narrowing without explicit flags:
316
+
317
+ ```bash
318
+ rqmd all
319
+ rqmd P1 Proposed --json --no-walk --no-table
320
+ rqmd Proposed core-engine
321
+ ```
322
+
323
+ `rqmd all` opens a whole-catalog overview ordered by newest requirement ID first. When positional status and priority filters are combined, rqmd narrows across both families, so `rqmd P1 Proposed` returns only proposed P1 requirements. Remaining positional tokens are then resolved as requirement IDs, domain tokens, or subsection tokens.
324
+
325
+ Interactive entry panels can start in priority mode:
326
+
327
+ ```bash
328
+ rqmd --focus-priority
329
+ ```
330
+
331
+ Within an entry panel, press `t` to cycle status, priority, and flagged editing.
332
+
333
+ When the entry panel is on status, rqmd also shows a right-hand priority column so the current priority and available shifted number-row shortcuts such as `!`/`@`/`#`/`$`/`%`/`^`/`&`/`*` stay visible while you review statuses. That column is rendered as its own aligned block, and its current-priority highlight remains separate from the active status-row highlight so both states stay readable at once. Those shortcuts set the first configured priorities immediately and keep focus on the current requirement until you explicitly move on with down arrow or `j`.
334
+
335
+ From any requirement detail panel, press `o` to inspect linked local requirement references that rqmd can resolve from the current entry. Selecting one opens that linked requirement in a nested detail view, and pressing `u` there returns you to the originating requirement.
336
+
337
+ From the same detail panel, press `v` to open the current requirement in VS Code at the requirement heading line. If the `code` launcher is unavailable, rqmd reports that cleanly and keeps you in the current interactive context.
338
+
339
+ Regenerate summary blocks with priority aggregates included:
340
+
341
+ ```bash
342
+ rqmd --priority-rollup --no-walk
343
+ ```
344
+
345
+ Filter by priority in tree, JSON, or interactive walk modes:
346
+
347
+ ```bash
348
+ rqmd --priority critical --as-tree
349
+ rqmd --priority p1 --json --no-walk
350
+ ```
351
+
352
+ Filter by subsection name with case-insensitive prefix matching:
353
+
354
+ ```bash
355
+ rqmd --sub-domain query --as-tree
356
+ rqmd --sub-domain api --json --no-walk
357
+ ```
358
+
359
+ Combine filters for slicing/dicing requirements:
360
+
361
+ - OR across different filter flags (`--status`, `--priority`, `--flagged`/`--no-flag`, `--has-link`/`--no-link`, `--sub-domain`)
362
+ - AND within the same flag when repeated
363
+
364
+ ```bash
365
+ rqmd --status proposed --priority p0 --as-tree
366
+ rqmd --no-flag --json --no-walk
367
+ rqmd --has-link --json --no-walk
368
+ rqmd --status proposed --status implemented --json --no-walk
369
+ rqmd --sub-domain query --sub-domain api --json --no-walk
370
+ ```
371
+
372
+ Target an explicit worklist from CLI tokens or a reusable file:
373
+
374
+ ```bash
375
+ rqmd demo "Query API"
376
+ rqmd --targets-file tmp/focus.txt --json --no-walk
377
+ ```
378
+
379
+ `--targets-file` accepts `.txt`, `.conf`, or `.md` files with one-per-line or whitespace/comma-separated tokens, and supports `#` comments.
380
+
381
+ Interactive file and requirement menus also expose `priority` as a sortable column via `s` / `d`.
382
+
383
+ Use a different ID prefix:
384
+
385
+ ```bash
386
+ rqmd --id-namespace R --update-id R-EXAMPLE-001 --update-status implemented
387
+ ```
388
+
389
+ Bulk set by repeated flags:
390
+
391
+ ```bash
392
+ rqmd --update AC-EXAMPLE-001=implemented --update AC-EXAMPLE-002=verified
393
+ ```
394
+
395
+ ## AI CLI (rqmd-ai)
396
+
397
+ `rqmd-ai` is a companion command for AI-oriented workflows. It is read-only by default and supports prompt-context export, plan previews, and guarded apply mode.
398
+
399
+ Recommended AI change loop for brainstorm-driven work:
400
+
401
+ 1. Export focused context first with `rqmd-ai --json` or a targeted `--dump-*` command.
402
+ 2. Update tracked requirement docs, the requirement index, and `CHANGELOG.md` before code when the brainstorm changes product behavior or workflow.
403
+ 3. Review the read-only plan preview from `rqmd-ai --update ...`.
404
+ 4. Apply explicitly with `--write` only after the preview matches the intended requirement/doc changes.
405
+ 5. Finish with `rqmd --verify-summaries` and the test suite so requirement docs and shipped behavior stay aligned.
406
+
407
+ Guidance mode:
408
+
409
+ ```bash
410
+ rqmd-ai --json
411
+ rqmd-ai --json --workflow-mode brainstorm
412
+ rqmd-ai --json --workflow-mode implement
413
+ rqmd-ai init --chat --json
414
+ rqmd-ai --json --workflow-mode init --show-guide
415
+ ```
416
+
417
+ `--workflow-mode brainstorm` emits requirement-first planning guidance for turning notes into ranked proposals. `--workflow-mode implement` emits the execution loop for working the highest-priority proposed 1-3 items at a time, then re-checking `rqmd`, summaries, tests, changelog, and remaining priorities before the next batch. `rqmd-ai init --chat` is the preferred onboarding entrypoint: it routes between starter scaffold mode and legacy-style repository seeding, emits a copy/paste AI handoff prompt, and keeps `--workflow-mode init-legacy` available only as a compatibility surface.
418
+
419
+ By default, `rqmd-ai --json` now includes the packaged skill and agent definitions from `resources/bundle` when the rqmd bundle is not installed in the workspace. If the bundle is already installed, the guide payload stays concise and reports the active local definition files instead of duplicating the packaged content.
420
+
421
+ Brainstorm mode can read `docs/brainstorm.md` by default or a custom markdown note file via `--brainstorm-file`, then emit ranked read-only proposal suggestions with recommended target requirement docs, suggested IDs, canonical `💡 Proposed` status, and inferred priorities.
422
+
423
+ Export context for prompts:
424
+
425
+ ```bash
426
+ rqmd-ai --json --dump-status proposed
427
+ rqmd-ai --json --dump-id RQMD-CORE-001 --include-requirement-body
428
+ rqmd-ai --json --dump-file ai-cli.md --include-domain-markdown --max-domain-markdown-chars 2000
429
+ ```
430
+
431
+ Plan first, then apply explicitly:
432
+
433
+ ```bash
434
+ rqmd-ai --json --update RQMD-CORE-001=implemented
435
+ rqmd-ai --json --write --update RQMD-CORE-001=implemented
436
+ ```
437
+
438
+ Install a standard AI agent/skill instruction bundle (minimal or full preset):
439
+
440
+ ```bash
441
+ rqmd-ai --json --install-agent-bundle --bundle-preset minimal --dry-run
442
+ rqmd-ai --json --install-agent-bundle --bundle-preset full
443
+ rqmd-ai --json --install-agent-bundle --bundle-preset full --overwrite-existing
444
+ ```
445
+
446
+ Bundle installs are idempotent by default and preserve existing customized instruction files unless `--overwrite-existing` is explicitly passed.
447
+
448
+ Bundle install also scaffolds project-local `.github/skills/dev/SKILL.md` and `.github/skills/test/SKILL.md` files based on detected repository commands. Treat those as a starting point: review and tighten the generated build, smoke, and validation commands so future `rqmd-dev` runs can rely on them instead of guessing.
449
+
450
+ Bundle installation can also be driven through a structured chat-style preview with `rqmd-ai install --json --bundle-preset minimal --chat --dry-run`. That payload now includes grouped interview questions, multi-select command suggestions, custom-answer prompts, skip support, detected command sources, recommended choices, safe defaults, and preview content for the generated `/dev` and `/test` skills. Repeat `--answer FIELD=VALUE` to select multiple suggestions or add custom commands before writing.
451
+
452
+ New-project flow: run `rqmd init`, paste the output into your AI chat, let that chat drive `rqmd-ai init --chat --json`, review the generated requirements catalog and any suggested bundle skill setup, and then start refining the resulting requirements docs.
453
+
454
+ Legacy-style repository seeding can still be previewed with `rqmd-ai init --chat --json --legacy`. The grouped interview covers catalog setup, developer workflows, repository understanding, backlog handling, and review notes, and its options include recommended choices, detected-from hints, and safe defaults. The generated starter catalog seeds a requirements index, developer workflow requirements, repository-area seed files, and an issue backlog file when `gh issue list` succeeds.
455
+
456
+ The installed bundle now includes Copilot skills for `/rqmd-brainstorm`, `/rqmd-triage`, `/rqmd-export-context`, `/rqmd-implement`, `/rqmd-init`, `/rqmd-init-legacy`, `/rqmd-status-maintenance`, `/rqmd-doc-sync`, `/rqmd-history`, `/rqmd-bundle`, and `/rqmd-verify` so teams can reuse the core planning, backlog selection, context export, implementation, unified init, compatibility legacy bootstrap, docs-sync, history, bundle-management, and verification loops without rewriting those instructions in every workspace. Those skills help with discovery and consistency, but they do not auto-approve terminal commands or bypass Copilot tool approval prompts.
457
+
458
+ The full bundle preset also installs specialized agents for requirement maintenance, docs sync, history investigation, and bundle maintenance so future agents can stay narrow and workflow-aware instead of overloading the single core agent with every repo-management task.
459
+
460
+ Bundle workflows assume the core lifecycle states remain representable in your status catalog. Custom labels are fine, but if you want `rqmd-ai` guidance, examples, and installed skills to work well out of the box, keep lifecycle equivalents for `💡 Proposed`, `🔧 Implemented`, `✅ Verified`, `⛔ Blocked`, and `🗑️ Deprecated`.
461
+
462
+ When apply mode runs, rqmd-ai appends a structured audit event to the local shared history backend at `.rqmd/history/rqmd-history/audit.jsonl`.
463
+
464
+ Batch set from file:
465
+
466
+ ```bash
467
+ rqmd --update-file tmp/ac-updates.jsonl
468
+ ```
469
+
470
+ Allow custom prefixes such as `REQ-` in a repo:
471
+
472
+ ```bash
473
+ rqmd --id-namespace REQ --status proposed --as-tree
474
+ ```
475
+
476
+ Filter walk:
477
+
478
+ ```bash
479
+ rqmd --status proposed
480
+ ```
481
+
482
+ Filtered walk resume behavior (enabled by default):
483
+
484
+ - Uses persisted state so reruns continue at the last visited requirement.
485
+ - Disable with `--no-resume-walk`.
486
+ - Control storage location with `--session-state-dir`.
487
+
488
+ Examples:
489
+
490
+ ```bash
491
+ rqmd --status implemented --session-state-dir system-temp
492
+ rqmd --status implemented --session-state-dir project-local
493
+ rqmd --status implemented --session-state-dir .rqmd/state
494
+ rqmd --status implemented --no-resume-walk
495
+ ```
496
+
497
+ Filter tree only:
498
+
499
+ ```bash
500
+ rqmd --status proposed --as-tree
501
+ ```
502
+
503
+ Filter as JSON for automation/AI parsing:
504
+
505
+ ```bash
506
+ rqmd --status proposed --json
507
+ ```
508
+
509
+ Filter JSON includes requirement body content and line metadata by default:
510
+
511
+ ```bash
512
+ rqmd --status proposed --json
513
+ ```
514
+
515
+ Use compact output without bodies:
516
+
517
+ ```bash
518
+ rqmd --status proposed --json --no-requirement-body
519
+ ```
520
+
521
+ Summary/check/set JSON examples:
522
+
523
+ ```bash
524
+ rqmd --json --no-walk
525
+ rqmd --verify-summaries --json --no-walk
526
+ rqmd --update-id AC-EXAMPLE-001 --update-status verified --json
527
+ rqmd --totals --json --no-walk
528
+ ```
529
+
530
+ ### JSON contract (stable keys)
531
+
532
+ When `--json` is used, top-level keys are stable by mode.
533
+ All JSON payloads include `schema_version` (current value: `1.0.0`) and follow semantic versioning (`major.minor.patch`).
534
+
535
+ - `summary`: `mode`, `schema_version`, `criteria_dir`, `changed_files`, `totals`, `files`, `ok`
536
+ - `check`: `mode`, `schema_version`, `criteria_dir`, `changed_files`, `totals`, `files`, `ok`
537
+ - `set` / `set-priority` / `set-flagged`: `mode`, `schema_version`, `criteria_dir`, `changed_files`, `totals`, `files`, `updates`
538
+ - `filter-status`: `mode`, `schema_version`, `status`, `criteria_dir`, `total`, `files`
539
+ - `filter-priority`: `mode`, `schema_version`, `priority`, `criteria_dir`, `total`, `files`
540
+ - `filter-flagged`: `mode`, `schema_version`, `flagged`, `criteria_dir`, `total`, `files`
541
+ - `filter-sub-domain`: `mode`, `schema_version`, `sub_domain`, `criteria_dir`, `total`, `files`
542
+ - `filter-combined`: `mode`, `schema_version`, `filters`, `criteria_dir`, `total`, `files`
543
+ - `filter-targets`: `mode`, `schema_version`, `targets`, `criteria_dir`, `total`, `files`
544
+ - `rollup`: `mode`, `schema_version`, `criteria_dir`, `file_count`, `totals`, optional `rollup_source`, optional `rollup_columns`
545
+ - `init`: `mode`, `schema_version`, `criteria_dir`, `starter_prefix`, `created_files`, `created_count`
546
+ - `init-priorities`: `mode`, `schema_version`, `criteria_dir`, `default_priority`, `changed_files`, `changed_count`
547
+
548
+ Filter payloads return `files` ordered by path and requirement entries ordered by requirement ID.
549
+ By default, filter JSON includes `body.markdown` and line metadata; pass `--no-requirement-body` to omit bodies.
550
+ Each requirement entry includes `sub_domain` (string or `null`), and each file entry includes `sub_sections` with subsection names and requirement counts.
551
+
552
+ ### Exit codes
553
+
554
+ RQMD uses this exit-code matrix for automation:
555
+
556
+ - `0`: Success (including successful no-op runs)
557
+ - `1`: Validation or contract failure (for example `--verify-summaries` found out-of-sync summaries, invalid input, missing docs, ambiguity, or other `ClickException` errors)
558
+ - `130`: Interrupted by user (`Ctrl+C`)
559
+
560
+ Explicit global roll-up totals:
561
+
562
+ ```bash
563
+ rqmd --totals --no-walk
564
+ ```
565
+
566
+ Custom roll-up columns from CLI equations:
567
+
568
+ ```bash
569
+ rqmd --totals --totals-map "C1=I+V" --totals-map "C2=P" --no-walk
570
+ ```
571
+
572
+ Custom roll-up columns from config (`.json`, `.yml`, `.yaml`):
573
+
574
+ ```bash
575
+ rqmd --totals --totals-config .rqmd.yml --json --no-walk
576
+ ```
577
+
578
+ Example project config for a repo that defines a custom status catalog and wants RQMD-ROLLUP-007 roll-up buckets:
579
+
580
+ ```yaml
581
+ # .rqmd.yml
582
+ statuses:
583
+ - name: Proposed
584
+ shortcode: P
585
+ emoji: "💡"
586
+ - name: Implemented
587
+ shortcode: I
588
+ emoji: "🔧"
589
+ - name: Desktop-Verified
590
+ shortcode: DV
591
+ emoji: "💻"
592
+ - name: VR-Verified
593
+ shortcode: VV
594
+ emoji: "🎮"
595
+ - name: Done
596
+ shortcode: D
597
+ emoji: "✅"
598
+ - name: Blocked
599
+ shortcode: B
600
+ emoji: "⛔"
601
+ - name: Deprecated
602
+ shortcode: X
603
+ emoji: "🗑️"
604
+
605
+ rollup_map:
606
+ Proposed: [proposed]
607
+ Build-Ready: [implemented, desktop-verified]
608
+ Complete: [vr-verified, done]
609
+ Parked: [blocked, deprecated]
610
+ ```
611
+
612
+ That example yields these roll-up families:
613
+
614
+ - `Blocked + Deprecated` roll up together in `Parked`
615
+ - `Implemented + Desktop-Verified` roll up together in `Build-Ready`
616
+ - `VR-Verified + Done` roll up together in `Complete`
617
+
618
+ When no CLI map/config is passed, rqmd resolves roll-up mappings with this precedence:
619
+
620
+ 1. `--totals-map` CLI equations
621
+ 2. project config (`.rqmd.yml|.rqmd.yaml` in `--project-root`)
622
+ 3. user config (`~/.config/rqmd/rollup.json|yaml|yml`)
623
+ 4. built-in canonical status totals
624
+
625
+ ## Tests
626
+
627
+ Run full pytest suite from this folder:
628
+
629
+ ```bash
630
+ uv run --extra dev pytest
631
+ ```
632
+
633
+ Run a specific test module:
634
+
635
+ ```bash
636
+ uv run --extra dev pytest tests/test_core_engine.py
637
+ ```
638
+
639
+ One-command shell smoke check (no make required):
640
+
641
+ ```bash
642
+ bash scripts/local-smoke.sh
643
+ ```
644
+
645
+ The test suite is organized to validate implemented acceptance-requirements behavior for:
646
+ - core engine parsing and summary sync
647
+ - interactive menu/color behavior
648
+ - non-interactive automation flows
649
+ - portability and packaging contracts
650
+
651
+ Detailed coverage mapping is documented in `docs/testing.md`.
652
+
653
+ ## Changelog
654
+
655
+ Notable project changes are tracked in `CHANGELOG.md` using the Keep a Changelog format.
656
+
657
+ ## CI
658
+
659
+ This package includes GitHub Actions workflows:
660
+
661
+ - `.github/workflows/pytest.yml`
662
+ - Triggers on push and pull_request.
663
+ - Installs project dependencies with `uv sync --extra dev`.
664
+ - Runs `bash scripts/local-smoke.sh --skip-install`.
665
+
666
+ - `.github/workflows/publish-pypi.yml`
667
+ - Triggers when a GitHub release is published.
668
+ - Validates that the release tag is a stable semver tag or `rc` prerelease tag matching `project.version`.
669
+ - Builds with `python -m build` and publishes with GitHub Actions trusted publishing.
670
+
671
+ ## Project portability
672
+
673
+ By default, rqmd auto-discovers `--project-root` by searching from the current working directory upward.
674
+ The nearest ancestor with a supported marker wins.
675
+
676
+ Marker priority within each directory is deterministic:
677
+
678
+ 1. `.rqmd.yml`, `.rqmd.yaml`, `.rqmd.json`
679
+ 2. `docs/requirements/`
680
+ 3. `requirements/`
681
+
682
+ If no marker is found, rqmd falls back to current working directory.
683
+ When auto-discovery is used, rqmd reports the discovered root and source marker.
684
+
685
+ Passing explicit `--project-root` bypasses auto-discovery.
686
+
687
+ When `--docs-dir` is omitted, rqmd auto-detects requirement docs by scanning from the current working path.
688
+
689
+ Auto-detect preference is deterministic:
690
+
691
+ 1. `docs/requirements/README.md`
692
+ 2. `requirements/README.md`
693
+
694
+ You can override both:
695
+
696
+ ```bash
697
+ rqmd --project-root /path/to/project --docs-dir docs/requirements
698
+ ```
699
+
700
+ `--docs-dir` can be absolute or relative to `--project-root`.
701
+ When auto-detection is used, rqmd reports which index path it selected.
702
+
703
+ Filtered walkthrough resume state is configurable with `--session-state-dir`:
704
+
705
+ - `system-temp` (default): OS temp directory.
706
+ - `project-local`: `<repo-root>/tmp/rqmd`.
707
+ - custom path: absolute or relative to `--project-root`.
708
+
709
+ Requirement header prefixes are configurable with `--id-namespace`.
710
+ When omitted, rqmd auto-detects prefixes by reading the selected `README.md` requirements index and linked domain docs when available.
711
+ If no prefixes are discovered, it falls back to `AC-`, `R-`, and `RQMD-`.
712
+
713
+ ### Project configuration file
714
+
715
+ To avoid repeating CLI flags across team members, use a single project config file at the project root: `.rqmd.yml` (preferred).
716
+ Accepted extensions are `.rqmd.yml`, `.rqmd.yaml`, or `.rqmd.json`.
717
+ `rqmd init --scaffold` and `rqmd-ai init --write` now create `.rqmd.yml` by default so the repository's requirements path, ID prefix, and canonical status/priority catalogs are explicit from day one.
718
+
719
+ Example:
720
+
721
+ ```yaml
722
+ {
723
+ requirements_dir: docs/requirements
724
+ id_prefix: PROJ
725
+ sort_strategy: status-focus
726
+ state_dir: project-local
727
+ }
728
+ ```
729
+
730
+ Supported keys:
731
+
732
+ - `requirements_dir`: Default requirements directory (relative to repo root)
733
+ - `id_prefix`: Default ID prefix for requirement headers
734
+ - `sort_strategy`: Default sort strategy for interactive mode (standard, status-focus, alpha-asc)
735
+ - `state_dir`: Default state directory for filtered walk resume (system-temp, project-local, or custom path)
736
+
737
+ CLI flags always override config file values. When `.rqmd.yml` (or `.rqmd.yaml` / `.rqmd.json`) is present, rqmd loads it automatically; no additional flag is needed.
738
+
739
+ ## Recommended docs recipe for projects
740
+
741
+ 1. Keep an index doc at `docs/requirements/README.md` or `requirements/README.md`.
742
+ 2. Keep domain files in that same directory.
743
+ 3. Ensure each requirement has exactly one status line directly under the `### <PREFIX>-...` header.
744
+ 4. Run `rqmd --verify-summaries` in CI to prevent stale summary blocks.
745
+ 5. Use non-interactive `--update`/`--update-file` in automation.
746
+
747
+ ## Packaging notes
748
+
749
+ - Package name: `rqmd`
750
+ - Console script entrypoint: `rqmd`
751
+ - Source package: `src/rqmd`
752
+
753
+ When ready for PyPI:
754
+
755
+ 1. Follow semantic versioning policy in `docs/SEMVER.md`.
756
+ 2. Follow the release checklist in `docs/releasing.md`.
757
+ 3. Create and publish a GitHub Release with a matching tag such as `v0.1.0` or `v0.1.0rc1`.
758
+ 4. Let `.github/workflows/publish-pypi.yml` publish through trusted publishing.