heinzel-issues 0.2.0__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 (46) hide show
  1. heinzel_issues-0.2.0/.copier-answers.yml +5 -0
  2. heinzel_issues-0.2.0/.gitignore +11 -0
  3. heinzel_issues-0.2.0/AGENTS.md +39 -0
  4. heinzel_issues-0.2.0/CHANGELOG.md +40 -0
  5. heinzel_issues-0.2.0/CLAUDE.md +1 -0
  6. heinzel_issues-0.2.0/LICENSE +21 -0
  7. heinzel_issues-0.2.0/Makefile +19 -0
  8. heinzel_issues-0.2.0/PKG-INFO +131 -0
  9. heinzel_issues-0.2.0/README.md +118 -0
  10. heinzel_issues-0.2.0/docs/CONTRACT.md +51 -0
  11. heinzel_issues-0.2.0/docs/SCREENSHOTS.md +10 -0
  12. heinzel_issues-0.2.0/docs/SCREENSHOT_STORY.md +44 -0
  13. heinzel_issues-0.2.0/docs/assets/screenshots/capture.json +84 -0
  14. heinzel_issues-0.2.0/docs/assets/screenshots/cli-list.png +0 -0
  15. heinzel_issues-0.2.0/docs/assets/screenshots/cli-list.txt +7 -0
  16. heinzel_issues-0.2.0/docs/assets/screenshots/index.html +1 -0
  17. heinzel_issues-0.2.0/docs/assets/screenshots/issues-page.png +0 -0
  18. heinzel_issues-0.2.0/docs/assets/screenshots/issues-page.txt +42 -0
  19. heinzel_issues-0.2.0/docs/assets/screenshots/report-history.png +0 -0
  20. heinzel_issues-0.2.0/docs/assets/screenshots/report-history.txt +55 -0
  21. heinzel_issues-0.2.0/docs/assets/screenshots/source-story.md +44 -0
  22. heinzel_issues-0.2.0/docs/assets/screenshots/today-open-reports.png +0 -0
  23. heinzel_issues-0.2.0/docs/assets/screenshots/today-open-reports.txt +34 -0
  24. heinzel_issues-0.2.0/docs/screenshot-definition.json +7 -0
  25. heinzel_issues-0.2.0/docs/screenshot_fixture.py +106 -0
  26. heinzel_issues-0.2.0/docs/screenshots.toml +72 -0
  27. heinzel_issues-0.2.0/plugin-lock.json +41 -0
  28. heinzel_issues-0.2.0/pyproject.toml +90 -0
  29. heinzel_issues-0.2.0/requirements.lock +1168 -0
  30. heinzel_issues-0.2.0/src/heinzel_issues/__init__.py +251 -0
  31. heinzel_issues-0.2.0/src/heinzel_issues/_beads.py +513 -0
  32. heinzel_issues-0.2.0/src/heinzel_issues/_contract.py +110 -0
  33. heinzel_issues-0.2.0/src/heinzel_issues/_releases.py +190 -0
  34. heinzel_issues-0.2.0/src/heinzel_issues/_service.py +541 -0
  35. heinzel_issues-0.2.0/src/heinzel_issues/py.typed +0 -0
  36. heinzel_issues-0.2.0/src/heinzel_issues/views/index.js +186 -0
  37. heinzel_issues-0.2.0/src/heinzel_issues/views/style.css +30 -0
  38. heinzel_issues-0.2.0/tests/acceptance/install_test.py +39 -0
  39. heinzel_issues-0.2.0/tests/conftest.py +242 -0
  40. heinzel_issues-0.2.0/tests/e2e/beads_test.py +43 -0
  41. heinzel_issues-0.2.0/tests/fake_bd.py +80 -0
  42. heinzel_issues-0.2.0/tests/integration/beads_test.py +68 -0
  43. heinzel_issues-0.2.0/tests/integration/heads_test.py +219 -0
  44. heinzel_issues-0.2.0/tests/integration/tracker_test.py +111 -0
  45. heinzel_issues-0.2.0/tests/unit/issues_test.py +390 -0
  46. heinzel_issues-0.2.0/tests/unit/view_test.py +184 -0
@@ -0,0 +1,5 @@
1
+ # Generated by Copier. Keep this file so the template can be updated.
2
+ _commit: v0.9.26
3
+ _src_path: gh:helmut-hoffer-von-ankershoffen/heinzel
4
+ plugin_name: issues
5
+ plugin_summary: Report a problem or request something, and see when it is worked on, done and released.
@@ -0,0 +1,11 @@
1
+ .venv/
2
+ .acceptance/
3
+ .preview/
4
+ dist/
5
+ release-dist/
6
+ __pycache__/
7
+ .pytest_cache/
8
+ .mypy_cache/
9
+ .coverage*
10
+ *.egg-info/
11
+ .ruff_cache/
@@ -0,0 +1,39 @@
1
+ # heinzel-issues
2
+
3
+ Read [README.md](README.md). Edit the feature in `src/heinzel_issues/` and its tests; use the public `heinzel`
4
+ and `heinzel.kernel` API. One `@module.operation` supplies CLI, MCP and REST. Add a service or model when the
5
+ feature needs it; neither is required for a small operation. Never import a plugin implementation or core internals.
6
+
7
+ Run from this plugin's directory:
8
+ ```sh
9
+ make setup
10
+ make check-fast
11
+ make check
12
+ make build
13
+ make acceptance
14
+ make preview
15
+ make lock # after changing dependencies
16
+ make release # preview only
17
+ ```
18
+
19
+ Keep all feature changes in this directory. Setup never initializes Git for a collection plugin. The owning
20
+ Makefile works even when the parent repository builds something else. A parent that provides collection commands
21
+ also accepts `NAME=heinzel-issues` from its root. Publication uses the parent's generic plugin release workflow;
22
+ do not copy a nested `.github/` or edit a parent registry.
23
+
24
+
25
+ Each pytest file declares exactly one level: `unit`, `integration` or `e2e`. Write a behavior test for a change.
26
+ Run the fast loop while editing and the owning full/installed-wheel checks before release. These commands install
27
+ a compatible core wheel; they never run the core suite. `CORE=<wheel>` explicitly selects a candidate SDK.
28
+
29
+ The source operation in the starter shows the minimum abstraction. Use the contributions preset or
30
+ [extension guide](https://github.com/helmut-hoffer-von-ankershoffen/heinzel/blob/main/docs/PLUGINS.md) for views,
31
+ priorities, Today widgets, notifications and shared contracts. Ordinary dependencies belong in this project's
32
+ `pyproject.toml`; regenerate its own lock. Use conventional commits and review nontrivial changes.
33
+
34
+ Publishing requires a merged commit, this plugin's version and configured GitHub/PyPI publishing. Local
35
+ `release` only checks/builds and previews; `publish` dispatches the protected workflow. Never upload a different
36
+ rebuild under an existing version. See the README's release steps.
37
+ Private sources use private GitHub releases and the installing person's `gh` login. PyPI is public; do not publish
38
+ private sources there. The [custom plugin guide](https://github.com/helmut-hoffer-von-ankershoffen/heinzel/blob/main/docs/PLUGIN_AUTHORING.md)
39
+ documents separate repositories, catalog discovery and both release paths.
@@ -0,0 +1,40 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0
4
+
5
+ Everything works in the app now; no step needs a terminal.
6
+
7
+ - Set up in the app: the Issues page asks for the folder with the Beads database, checks that it answers, and saves
8
+ it (`connect`). Nothing is saved when the check fails. The app and the daemon follow the saved settings at their
9
+ next use, without a restart.
10
+ - Open a report to read what you sent, the files you sent with it and its history: Sent, Being worked on, Done,
11
+ Released in.
12
+ - Send a screenshot or a text file with a report from the app (up to 2 MiB), with Heinzel 0.9.45 or newer; the
13
+ confirmation shows the file shortened. An older Heinzel offers text only.
14
+ - More labels: `issues.beads.extra_labels` (the "More labels" field in the setup form) gives every new report further
15
+ labels, so a team's intake queue sees it.
16
+ - Your reports only: Issues lists and shows only items with the Issues label that were sent under your login name,
17
+ and changes only items with the Issues label. `list` and `show` are private operations now, so they need your
18
+ sign-in on the network interfaces.
19
+ - What you type can never be read by the tracker program as an option: every value goes as `--name=value`.
20
+ - The form says under which login name and with which labels a report is stored, before you send.
21
+ - The view opens no terminal any more: the `hz setup issues` and `hz issues submit` buttons are gone, and messages
22
+ the app shows name no command.
23
+
24
+ ## 0.1.1
25
+
26
+ Relock for Heinzel Core 0.9.40 (its AI extra adds pyjwt) and refresh the gallery.
27
+
28
+ ## 0.1.0
29
+
30
+ - First release: report a problem or request something from the app or `hz issues submit`, and see it as
31
+ Received, Being worked on or Done, with the release that shipped it.
32
+ - A task-tracking contract (submit, list, get, changes) with a built-in Beads connector; other trackers plug in
33
+ through the `heinzel_issues.connectors` entry point.
34
+ - A notice when a report is being worked on, is done, or is released; open reports on Today.
35
+ - Send from the app: the view's form uses the typed-input `send` action (Heinzel 0.9.30+), confirmed before it
36
+ runs; an older Heinzel gets the terminal command instead.
37
+ - Beads writes go through the methods of Heinzel's `Tracker` contract (core ADR 0141) with the sender as actor;
38
+ no capability adapter is registered, so other trackers stay bound. Requires Heinzel 0.9.31.
39
+ - Opt-in only: in no standard set, and it says how to set it up until a reachable tracker is configured.
40
+ - Structured `issues.submit.*` and `issues.watch.*` log events, never with the typed text.
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Plugin authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,19 @@
1
+ .DEFAULT_GOAL := help
2
+ TOOLING ?= heinzel-plugin-tools @ https://github.com/helmut-hoffer-von-ankershoffen/heinzel-plugins/releases/download/tools-v0.3.7/heinzel_plugin_tools-0.3.7-py3-none-any.whl\#sha256=ac959c164e3726f86311c86fa9d3b4a3cbc82a6b4f81fae8bf462ee8103bd359
3
+ unexport TOOLING CORE TAG REGISTRY
4
+ export HZ_PLUGIN_TOOLING := $(value TOOLING)
5
+ export PLUGIN_CORE := $(value CORE)
6
+ export PLUGIN_TAG := $(value TAG)
7
+ export PLUGIN_REGISTRY := $(value REGISTRY)
8
+ MAKEOVERRIDES =
9
+ PLUGIN := uv run --quiet --no-project --with "$$HZ_PLUGIN_TOOLING" hz-plugin
10
+
11
+ .PHONY: help setup fix check-fast check test lock preview build acceptance audit release preflight publish
12
+ help:
13
+ @echo 'make setup; make check-fast; make check; make preview; make build; make acceptance'
14
+ @echo 'make lock refreshes this plugin dependency lock; CORE=<wheel> selects a candidate SDK.'
15
+ @echo 'make release previews; make publish dispatches the protected release workflow.'
16
+ setup fix check-fast check test lock preview build acceptance audit release preflight:
17
+ @$(PLUGIN) $@
18
+ publish:
19
+ @$(PLUGIN) publish
@@ -0,0 +1,131 @@
1
+ Metadata-Version: 2.5
2
+ Name: heinzel-issues
3
+ Version: 0.2.0
4
+ Summary: Report a problem or request something, and see when it is done and released; needs a Beads database you can write to.
5
+ Project-URL: Source, https://github.com/helmut-hoffer-von-ankershoffen/heinzel-plugins/tree/main/plugins/heinzel-issues
6
+ Project-URL: Changelog, https://github.com/helmut-hoffer-von-ankershoffen/heinzel-plugins/blob/main/plugins/heinzel-issues/CHANGELOG.md
7
+ Project-URL: Issues, https://github.com/helmut-hoffer-von-ankershoffen/heinzel-plugins/issues
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.12
11
+ Requires-Dist: heinzel<0.10,>=0.9.31
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Issues
15
+
16
+ Report a problem or request something, then see where it stands: **Received**, **Being worked on** or **Done**, and
17
+ once it ships, **Released in 0.9.27 on 7 Nov 2026**. You never see the tracker behind it: no statuses of its own,
18
+ no ids, no pull requests, unless you ask for the details.
19
+
20
+ It is not installed, bundled or recommended by default: it needs a Beads database you can write to (today the
21
+ private management repository). Add it with `hz system plugin add issues --confirm`.
22
+ Until a tracker is set up the Issues page shows **Issue tracking is not set up** with a short form, never an error.
23
+ Everything after that happens in the app; no step needs a terminal.
24
+
25
+ ## Use it
26
+
27
+ - **In the app:** open **Issues** in the sidebar. The list shows each report with its state as a word and a mark
28
+ (○ Received, ◐ Being worked on, ✓ Done), never colour alone. Type what happened or what you would like and
29
+ press **Send**; the app shows what it will send and asks first. With Heinzel 0.9.45 or newer you can add a
30
+ screenshot or a text file (PNG, JPEG or text, up to 2 MiB). Select a report to read what you sent and its history:
31
+ Sent, Being worked on, Done, Released in. Your open reports also appear on Today.
32
+ - **In a terminal:**
33
+
34
+ ```sh
35
+ hz issues submit "The footer clock jumps by a pixel every minute"
36
+ hz issues submit "Here is what I saw" --attachment shot.png
37
+ hz issues list
38
+ ```
39
+
40
+ `hz issues list --json` adds the details for agents and experts: the tracker, its id and status, and each pull
41
+ request with its release. `hz issues show <id>` shows one.
42
+ - **Notices:** every five minutes the daemon looks for changes and tells you when a report is being worked on, is
43
+ done, and when it is released. The first check after turning Issues on only remembers what is there.
44
+
45
+ When nothing is set up, the app says **Issue tracking is not set up** and asks for the tracker folder;
46
+ `hz issues list` says the same and names `hz setup issues`.
47
+
48
+ <!-- screenshots:start -->
49
+ ## Screenshots
50
+
51
+ <img src="docs/assets/screenshots/issues-page.png" alt="Three fictional reports: received, being worked on, and released in 0.9.27 — with a form to send another" width="960">
52
+
53
+ Three fictional reports: received, being worked on, and released in 0.9.27 — with a form to send another
54
+
55
+ <img src="docs/assets/screenshots/report-history.png" alt="A fictional report opened: what was sent, the file sent with it, and its history up to the release" width="960">
56
+
57
+ A fictional report opened: what was sent, the file sent with it, and its history up to the release
58
+
59
+ <img src="docs/assets/screenshots/today-open-reports.png" alt="Your open fictional reports and requests on Today, in dark mode; done ones leave the list" width="960">
60
+
61
+ Your open fictional reports and requests on Today, in dark mode; done ones leave the list
62
+
63
+ <details>
64
+ <summary>Command line</summary>
65
+
66
+ <img src="docs/assets/screenshots/cli-list.png" alt="The same fictional reports and their plain states through the real CLI" width="960">
67
+
68
+ The same fictional reports and their plain states through the real CLI
69
+
70
+ </details>
71
+
72
+ [Open the screenshot gallery](docs/assets/screenshots/index.html).
73
+ <!-- screenshots:end -->
74
+
75
+ ## Set it up
76
+
77
+ In the app, open **Issues**, enter the folder that holds the Beads database and press **Set up issue tracking**.
78
+ Issues checks that the database answers before it saves anything, and works at once, without a restart. Under
79
+ **More options** you can name more labels for every new report (emptying the field clears them) and git clones
80
+ whose tags are releases.
81
+
82
+ In a terminal, `hz setup issues` asks the same. Or set it directly:
83
+
84
+ ```toml
85
+ [issues]
86
+ tracker = "beads"
87
+
88
+ [issues.beads]
89
+ path = "~/Code/team-board" # the folder with the .beads database
90
+ label = "heinzel-issues" # what Issues gives each report, and the items it shows
91
+ extra_labels = ["intake"] # optional: more labels for every new report, e.g. the one your team's queue reads
92
+
93
+ [[issues.releases]]
94
+ path = "~/Code/harbor" # a clone on this computer; read, never fetched
95
+ names = ["core"] # how notes name it: "core #12"
96
+ ref = "origin/main"
97
+ tags = "v*"
98
+ ```
99
+
100
+ `hz system doctor` reports Issues as up while it is off, and as down with the reason when a chosen tracker does
101
+ not answer.
102
+
103
+ ## How "Released in" is found
104
+
105
+ Whoever works on a report notes the pull request in the tracker: `Fixed in #562`, `gh-562`, `plugins #38` or a
106
+ pull request link. Issues finds the merge commit whose subject ends in `(#562)` on the configured branch, then the
107
+ oldest release tag matching the pattern that contains it. A report with several pull requests is released when the
108
+ last of them is. The clone is only read; keep it fetched as you normally do.
109
+
110
+ ## Trackers
111
+
112
+ Beads is built in: Issues runs `bd ... --json` in the configured folder, on this computer, and never syncs,
113
+ pushes or publishes. Other trackers (Linear, Jira, GitHub issues, cards in git) plug in behind the same contract,
114
+ described in [docs/CONTRACT.md](docs/CONTRACT.md), without a change to Issues or to Heinzel's core.
115
+
116
+ Issues writes to Beads through the methods of Heinzel's `Tracker` contract (core ADR 0141): each write runs
117
+ `bd --actor`, and a claim is Beads' atomic `--claim`. It registers no `tracker` capability adapter, so installing it
118
+ never unbinds or replaces the tracker other plugins (GitHub, Atlassian) use.
119
+
120
+ ## Privacy
121
+
122
+ What you send stays in the tracker you chose. Each report is stored there with your login name on this computer and
123
+ the labels that are set up; the form says both before you send. Issues shows and reads only the reports you sent
124
+ under that login name: other work in the same database, and other people's reports, never appear, by list or by id.
125
+ Reading and sending need your sign-in to the app; nothing is open on the network interfaces without it. Issues stores only what it has already told you, under Heinzel's
126
+ state folder, readable by you only. Notices are local, like every Heinzel notice.
127
+
128
+ ## Develop
129
+
130
+ From this directory: `make setup`, `make check-fast`, `make check`, `make build`, `make acceptance`. The
131
+ integration tests create a temporary Beads database and need `bd` installed; they are skipped without it.
@@ -0,0 +1,118 @@
1
+ # Issues
2
+
3
+ Report a problem or request something, then see where it stands: **Received**, **Being worked on** or **Done**, and
4
+ once it ships, **Released in 0.9.27 on 7 Nov 2026**. You never see the tracker behind it: no statuses of its own,
5
+ no ids, no pull requests, unless you ask for the details.
6
+
7
+ It is not installed, bundled or recommended by default: it needs a Beads database you can write to (today the
8
+ private management repository). Add it with `hz system plugin add issues --confirm`.
9
+ Until a tracker is set up the Issues page shows **Issue tracking is not set up** with a short form, never an error.
10
+ Everything after that happens in the app; no step needs a terminal.
11
+
12
+ ## Use it
13
+
14
+ - **In the app:** open **Issues** in the sidebar. The list shows each report with its state as a word and a mark
15
+ (○ Received, ◐ Being worked on, ✓ Done), never colour alone. Type what happened or what you would like and
16
+ press **Send**; the app shows what it will send and asks first. With Heinzel 0.9.45 or newer you can add a
17
+ screenshot or a text file (PNG, JPEG or text, up to 2 MiB). Select a report to read what you sent and its history:
18
+ Sent, Being worked on, Done, Released in. Your open reports also appear on Today.
19
+ - **In a terminal:**
20
+
21
+ ```sh
22
+ hz issues submit "The footer clock jumps by a pixel every minute"
23
+ hz issues submit "Here is what I saw" --attachment shot.png
24
+ hz issues list
25
+ ```
26
+
27
+ `hz issues list --json` adds the details for agents and experts: the tracker, its id and status, and each pull
28
+ request with its release. `hz issues show <id>` shows one.
29
+ - **Notices:** every five minutes the daemon looks for changes and tells you when a report is being worked on, is
30
+ done, and when it is released. The first check after turning Issues on only remembers what is there.
31
+
32
+ When nothing is set up, the app says **Issue tracking is not set up** and asks for the tracker folder;
33
+ `hz issues list` says the same and names `hz setup issues`.
34
+
35
+ <!-- screenshots:start -->
36
+ ## Screenshots
37
+
38
+ <img src="docs/assets/screenshots/issues-page.png" alt="Three fictional reports: received, being worked on, and released in 0.9.27 — with a form to send another" width="960">
39
+
40
+ Three fictional reports: received, being worked on, and released in 0.9.27 — with a form to send another
41
+
42
+ <img src="docs/assets/screenshots/report-history.png" alt="A fictional report opened: what was sent, the file sent with it, and its history up to the release" width="960">
43
+
44
+ A fictional report opened: what was sent, the file sent with it, and its history up to the release
45
+
46
+ <img src="docs/assets/screenshots/today-open-reports.png" alt="Your open fictional reports and requests on Today, in dark mode; done ones leave the list" width="960">
47
+
48
+ Your open fictional reports and requests on Today, in dark mode; done ones leave the list
49
+
50
+ <details>
51
+ <summary>Command line</summary>
52
+
53
+ <img src="docs/assets/screenshots/cli-list.png" alt="The same fictional reports and their plain states through the real CLI" width="960">
54
+
55
+ The same fictional reports and their plain states through the real CLI
56
+
57
+ </details>
58
+
59
+ [Open the screenshot gallery](docs/assets/screenshots/index.html).
60
+ <!-- screenshots:end -->
61
+
62
+ ## Set it up
63
+
64
+ In the app, open **Issues**, enter the folder that holds the Beads database and press **Set up issue tracking**.
65
+ Issues checks that the database answers before it saves anything, and works at once, without a restart. Under
66
+ **More options** you can name more labels for every new report (emptying the field clears them) and git clones
67
+ whose tags are releases.
68
+
69
+ In a terminal, `hz setup issues` asks the same. Or set it directly:
70
+
71
+ ```toml
72
+ [issues]
73
+ tracker = "beads"
74
+
75
+ [issues.beads]
76
+ path = "~/Code/team-board" # the folder with the .beads database
77
+ label = "heinzel-issues" # what Issues gives each report, and the items it shows
78
+ extra_labels = ["intake"] # optional: more labels for every new report, e.g. the one your team's queue reads
79
+
80
+ [[issues.releases]]
81
+ path = "~/Code/harbor" # a clone on this computer; read, never fetched
82
+ names = ["core"] # how notes name it: "core #12"
83
+ ref = "origin/main"
84
+ tags = "v*"
85
+ ```
86
+
87
+ `hz system doctor` reports Issues as up while it is off, and as down with the reason when a chosen tracker does
88
+ not answer.
89
+
90
+ ## How "Released in" is found
91
+
92
+ Whoever works on a report notes the pull request in the tracker: `Fixed in #562`, `gh-562`, `plugins #38` or a
93
+ pull request link. Issues finds the merge commit whose subject ends in `(#562)` on the configured branch, then the
94
+ oldest release tag matching the pattern that contains it. A report with several pull requests is released when the
95
+ last of them is. The clone is only read; keep it fetched as you normally do.
96
+
97
+ ## Trackers
98
+
99
+ Beads is built in: Issues runs `bd ... --json` in the configured folder, on this computer, and never syncs,
100
+ pushes or publishes. Other trackers (Linear, Jira, GitHub issues, cards in git) plug in behind the same contract,
101
+ described in [docs/CONTRACT.md](docs/CONTRACT.md), without a change to Issues or to Heinzel's core.
102
+
103
+ Issues writes to Beads through the methods of Heinzel's `Tracker` contract (core ADR 0141): each write runs
104
+ `bd --actor`, and a claim is Beads' atomic `--claim`. It registers no `tracker` capability adapter, so installing it
105
+ never unbinds or replaces the tracker other plugins (GitHub, Atlassian) use.
106
+
107
+ ## Privacy
108
+
109
+ What you send stays in the tracker you chose. Each report is stored there with your login name on this computer and
110
+ the labels that are set up; the form says both before you send. Issues shows and reads only the reports you sent
111
+ under that login name: other work in the same database, and other people's reports, never appear, by list or by id.
112
+ Reading and sending need your sign-in to the app; nothing is open on the network interfaces without it. Issues stores only what it has already told you, under Heinzel's
113
+ state folder, readable by you only. Notices are local, like every Heinzel notice.
114
+
115
+ ## Develop
116
+
117
+ From this directory: `make setup`, `make check-fast`, `make check`, `make build`, `make acceptance`. The
118
+ integration tests create a temporary Beads database and need `bd` installed; they are skipped without it.
@@ -0,0 +1,51 @@
1
+ # The task-tracking contract
2
+
3
+ Issues talks to a tracker only through `TaskTracker` in `heinzel_issues._contract`. A connector implements four
4
+ operations and maps the tracker's own statuses onto three states; everything else stays inside the connector.
5
+
6
+ | Operation | What it does |
7
+ |---|---|
8
+ | `submit(title, body, attachments)` | Create an item from a person's report; it starts as `received`. |
9
+ | `list()` | Every item submitted through Issues, newest first. |
10
+ | `get(task_id)` | One item by the tracker's id. |
11
+ | `changes(since)` | Items changed after `since` (all for `None`); the daemon's watch calls it every five minutes. |
12
+
13
+ Each returns `Task`s: `id`, `title`, `body`, `state` (`received`, `working`, `done`), the tracker's own `status`,
14
+ `created_at`, `updated_at`, `closed_at`, and `references`: text written by whoever works on the item (notes, links,
15
+ close reason) where pull request numbers are found. Never put the submitter's own text in `references`.
16
+ Optional: `started_at`, when someone started on it, and `attachments`, the names of the files sent with it; the
17
+ opened report shows both, in its history and under what was sent.
18
+
19
+ A connector raises `TrackerError` with a plain sentence that says what to do; Issues shows it as it is.
20
+
21
+ ## Adding a connector
22
+
23
+ Register a factory in your package under the `heinzel_issues.connectors` entry point group:
24
+
25
+ ```toml
26
+ [project.entry-points."heinzel_issues.connectors"]
27
+ linear = "harbor_linear.issues:connect"
28
+ ```
29
+
30
+ The factory receives the settings table `issues.connectors.<name>` and returns a `TaskTracker`. People choose it
31
+ with `issues.tracker = "linear"`. A connector that fails to load is skipped; a built-in name always wins.
32
+
33
+ ## The Beads connector
34
+
35
+ | Beads status | State |
36
+ |---|---|
37
+ | `open`, `deferred`, `pinned`, any custom status | Received |
38
+ | `in_progress`, `blocked`, `hooked` | Being worked on |
39
+ | `closed` | Done |
40
+
41
+ It runs `bd create|list|show|update --json` in `issues.beads.path` with `BD_NON_INTERACTIVE=1`, labels every
42
+ report with `issues.beads.label`, lists only items with that label, and copies attachments to
43
+ `.beads/attachments/<id>/` next to the database, noting their path on the item.
44
+
45
+ ## Heinzel's Tracker contract
46
+
47
+ `BeadsBoard` implements core's `Tracker` protocol (ADR 0141) over the same database: `issues_updated`, `create`,
48
+ `claim`, `transition`, `note`, `attach` and `close`. A project is a Beads label. Every write runs
49
+ `bd ... --actor <actor>`; `claim` is Beads' atomic `--claim` and refuses an item another actor holds. `hz issues
50
+ submit` writes through it; listing and the watch read through the connector above. Issues registers no capability
51
+ adapter, so it never changes which tracker other plugins are bound to.
@@ -0,0 +1,10 @@
1
+ # Screenshot gallery
2
+
3
+ From the collection root, run `make screenshots NAME=heinzel-issues OPEN=1`.
4
+ Review the [contact sheet](assets/screenshots/index.html) before committing.
5
+ The [scene plan](screenshots.toml) describes the real UI and CLI captures.
6
+ `make screenshots-check NAME=heinzel-issues` verifies freshness offline.
7
+
8
+ Captures use a temporary fictional profile without connected accounts and an in-memory tracker with three
9
+ fictional reports (`screenshot_fixture.py`); no Beads database is read or written.
10
+ See the [author guide](../../../docs/SCREENSHOT_AUTHORING.md) for human and agent commands.
@@ -0,0 +1,44 @@
1
+ ## Audience
2
+ People who use Heinzel and want to report a problem or request something without leaving the app, then follow it to the release that shipped it. Maintainers also need to know that the built-in tracker is a Beads database on this computer that they can write to; the plugin is optional and off until a tracker is set up (`README.md`, `[tool.heinzel.catalog]` in `pyproject.toml`).
3
+
4
+ ## Outcome
5
+ The tracker is usable from within the app, with no terminal step: set it up, send a report, read the list with plain states, open one report for what was sent and its history, and see open reports on Today. The gallery shows the real plugin view and Core's Today with fictional data only. It must not claim that anything was sent: the demonstration tracker refuses sending.
6
+
7
+ ## The UI flows in the source
8
+ All of this is one view, `src/heinzel_issues/views/index.js`, at the route `/?panel=issues:requests` (`ROUTE` in `_service.py`), reached from the sidebar entry Issues (`module.nav`, `module.action`, `module.view(name="requests", source="list")` in `__init__.py`).
9
+
10
+ 1. **Setup form.** While `data.ready` is false the view renders the form "Set up issue tracking": the status line "Issue tracking is not set up." (or the tracker's own problem text), the required field "Tracker folder", and under "More options" the fields "More labels" and "Release clones". The button "Set up issue tracking" runs the view action `connect` (operation `connect`), which checks that the folder holds a Beads database and that it answers before anything is saved, then works without a restart. The form says "Checking the folder…", then "Issue tracking is set up." or the reason nothing was saved.
11
+ 2. **Submit with confirm.** When ready, the composer "Report or request" has a text area ("What happened, or what would you like?"), an optional chooser "Screenshot or file (optional)" for a PNG, JPEG or text file up to 2 MiB, a line that says how it is stored ("Sent to the tracker under your login name …, with the labels …"), and the button Send. Send runs the view action `send` (operation `submit`, declared `read_only=False`, `private=True`). Core shows the call and asks before it runs; that confirmation is Core-rendered, not plugin UI. Cancelling keeps the typed text ("Not sent; your text is still here."); success says "Received. You will see here when someone is on it." The chooser appears only when Core reports the SDK feature `form-long-values`.
12
+ 3. **List with states.** The list "Your reports and requests" has one row per report: its title, and its state as a mark and a word, never colour alone: ○ Received, ◐ Being worked on, ✓ Done, or ✓ Released in 0.9.27 on 7 Nov 2026 once a release is found. An empty tracker shows "Nothing reported yet."
13
+ 4. **Detail and history.** A row is a button; selecting it expands the text sent after the title, "Sent with:" and the attachment names, and the ordered list "History": Sent, Being worked on, Done, Released in, each with its day.
14
+ 5. **Today cards.** `@module.widget(source="list")` puts a list card "Your reports and requests" on Core's Today at `/` with up to eight reports that are not done, each with its state and a link to the Issues page. It is absent while tracking is off or everything is done.
15
+
16
+ Beyond the app: the CLI commands `hz issues list`, `submit`, `show` and `connect`, the prompted `hz setup issues`, a Doctor check `tracker`, and a five-minute job that emits Core notices on a state change or release. These are Core or terminal surfaces, not further plugin pages. No external provider UI is declared; Beads is reached through a local command and releases through local git clones.
17
+
18
+ ## Scenes
19
+ 1. **issues-page (UI, light):** flows 2 and 3 at rest. Three fictional reports, one per state, the done one as "Released in 0.9.27 on 7 Nov 2026", above the composer with its storage line and Send. The caption's "a form to send another" is accurate for the form being present; it is not a sent report.
20
+ 2. **report-history (UI, light):** flow 4. The fictional weather report is opened: its text, "Sent with: today-rain.png", and the history Sent 4 Nov 2026, Being worked on 4 Nov 2026, Done 5 Nov 2026, Released in 0.9.27 7 Nov 2026. A meaningful expanded state of the same real view.
21
+ 3. **today-open-reports (UI, dark):** flow 5. Core's Today with the two open fictional reports; the released one is absent.
22
+ 4. **cli-list (CLI):** `hz issues list` as a table with the columns Report or request, Status and Sent, for the same three reports. A real CLI result, not a substitute for the UI.
23
+
24
+ What the plan does not capture: the setup form (flow 1) and Core's confirmation or a successful send (the rest of flow 2). The fixture forces a ready tracker and its `submit` raises "Sending is off in this demonstration.", so neither can be shown by this plan and no caption may imply them. Showing them needs further scenes with a fixture state that is not set up and a plan step that presses Send; that is a change to the plan and needs a new definition.
25
+
26
+ ## Fictional fixtures
27
+ `docs/screenshot_fixture.py` replaces the built-in tracker with one in memory holding three fictional tasks (demo-1 to demo-3), one fictional attachment name with no file behind it, and a temporary local git clone with empty commits and the tags v0.9.26 and v0.9.27, so that "Fixed in #7" resolves to 0.9.27 on 7 Nov 2026. It sets the tracker and the release clone through environment settings and then runs the real app. No Beads database is read or written and nothing is sent anywhere. Browser time is fixed at 8 Nov 2026.
28
+
29
+ ## Privacy pitfalls
30
+ - The composer prints the login name of whoever runs the capture (`reporter()` in `_beads.py` reads the operating system's login name) together with the label `heinzel-issues`. The image is acceptable only if that name is the capture profile's fictional one; a real login name on scenes 1 or 2 is a rejection.
31
+ - The release clone lives in a temporary folder whose path is in the settings. It must not appear in any image or transcript; the list and the table do not print it, the JSON output would.
32
+ - The setup form's "Tracker folder" is prefilled from settings and would show a real path if it were ever captured from a real profile.
33
+ - Report titles, body and the attachment name must be exactly the fixture's; any text from a real tracker, a real bead id or a pull request of a real repository is a rejection. The view and the table do not print tracker ids.
34
+ - Core chrome around the view (sidebar, account name, version, Doctor card, footer, notices, chat) comes from the capture profile; check it for real names, host names, paths, e-mail addresses and tokens. The toolkit's own presentation mapping is limited to the owning interpreter path shown as `/demo-profile/.venv` and the Doctor hostname shown as `demo-host`; neither is a privacy acceptance.
35
+
36
+ ## Acceptance criteria
37
+ - Four distinct captures from the real app and CLI through the fixture; no forged HTML, duplicates or caption-only variants. Scenes 1 and 2 are genuine feature UI states, scene 3 is a Core feature surface fed by the plugin, scene 4 is identified as CLI.
38
+ - Scene 1 shows all three rows with mark and word, and the composer; scene 2 shows the body text, "Sent with: today-rain.png" and all four history steps with dates; scene 3 shows exactly the two open reports in an applied dark appearance; scene 4 lists the same three with the same states.
39
+ - Light and dark are actually applied. Text is readable, nothing clipped, the state marks are visible.
40
+ - Do not describe the file chooser as shown unless it is in the image; it depends on the captured Core.
41
+ - Captions say the data is fictional and claim nothing about setup, confirmation or a successful send.
42
+ - An independent reviewer opens every image and reads every transcript for privacy and accuracy before publication.
43
+
44
+ This analysis read the staged source, README, plan and fixture; it ran no plugin code and captured nothing.
@@ -0,0 +1,84 @@
1
+ {
2
+ "format": 1,
3
+ "plugin": "heinzel-issues",
4
+ "core_version": "0.9.42",
5
+ "inputs_sha256": "df95a9d4a53cb16aa0a3572bc04b88332dfbb102fdf4ff439bb1d309ecf099a2",
6
+ "images": {
7
+ "docs/assets/screenshots/issues-page.png": "4172860cdbf81d5b9b907a47a73641889cefcd3bcc185b43bd9d46815c09f126",
8
+ "docs/assets/screenshots/report-history.png": "7605e12edddcf1dc7524c801850c6138605b430853a3aa81ff46064b8cde0691",
9
+ "docs/assets/screenshots/today-open-reports.png": "f7e36260487c7a30574122f5a6705732edee045cd720d0b7717fc4b307ead56e",
10
+ "docs/assets/screenshots/cli-list.png": "e8a2c412a35760cf9eb4725826c6b6ac075d532ddc910392a48e23af56b563bc"
11
+ },
12
+ "review_bundle": {
13
+ "format": 2,
14
+ "source_story": {
15
+ "path": "source-story.md",
16
+ "sha256": "baac94e327f1dbec7633b9b7e4b9de5fb398f2d57c1d8f8a3ce68984bc511401"
17
+ },
18
+ "definition": {
19
+ "format": 1,
20
+ "reviewer": "fable-issues-story",
21
+ "source_sha256": "f69054b3ab966d5ca2aea6e080b3ebfd43c5d210379e3f8005829ce6da54860c",
22
+ "plan_sha256": "e7395659d00a341e8c5fcf62a26cc2765e7812e405390baa9fe1ae815fab2710",
23
+ "story_sha256": "baac94e327f1dbec7633b9b7e4b9de5fb398f2d57c1d8f8a3ce68984bc511401"
24
+ },
25
+ "plugin": "heinzel-issues",
26
+ "core_version": "0.9.42",
27
+ "inputs_sha256": "df95a9d4a53cb16aa0a3572bc04b88332dfbb102fdf4ff439bb1d309ecf099a2",
28
+ "screenshots": [
29
+ {
30
+ "path": "docs/assets/screenshots/issues-page.png",
31
+ "surface": "ui",
32
+ "caption": "Three fictional reports: received, being worked on, and released in 0.9.27 \u2014 with a form to send another"
33
+ },
34
+ {
35
+ "path": "docs/assets/screenshots/report-history.png",
36
+ "surface": "ui",
37
+ "caption": "A fictional report opened: what was sent, the file sent with it, and its history up to the release"
38
+ },
39
+ {
40
+ "path": "docs/assets/screenshots/today-open-reports.png",
41
+ "surface": "ui",
42
+ "caption": "Your open fictional reports and requests on Today, in dark mode; done ones leave the list"
43
+ },
44
+ {
45
+ "path": "docs/assets/screenshots/cli-list.png",
46
+ "surface": "cli",
47
+ "caption": "The same fictional reports and their plain states through the real CLI"
48
+ }
49
+ ],
50
+ "images": {
51
+ "issues-page.png": "4172860cdbf81d5b9b907a47a73641889cefcd3bcc185b43bd9d46815c09f126",
52
+ "report-history.png": "7605e12edddcf1dc7524c801850c6138605b430853a3aa81ff46064b8cde0691",
53
+ "today-open-reports.png": "f7e36260487c7a30574122f5a6705732edee045cd720d0b7717fc4b307ead56e",
54
+ "cli-list.png": "e8a2c412a35760cf9eb4725826c6b6ac075d532ddc910392a48e23af56b563bc"
55
+ },
56
+ "transcripts": {
57
+ "issues-page.txt": "4e32e4e6bbcd79d9c69b679b75de3a51130bc0e01a66473d1c26e2ebc32d2cca",
58
+ "report-history.txt": "8464fe38ca16fca424081cc011998033d16ffe8b3494dd40f9d2c3311f02ea15",
59
+ "today-open-reports.txt": "530b3b464fd7c0d108890cb6c4b44a076913134d933868e6c93aadb66e4144e0",
60
+ "cli-list.txt": "d0eac2c0b1b435cac45b7f7052b732fe1e8f619035e7778e11b8f6e6101ff08f"
61
+ },
62
+ "bundle_sha256": "89e1f1751c8683837e61b7ee48b26b60e15ed4991e2de7fab1dbc096281a2668"
63
+ },
64
+ "privacy_review": {
65
+ "format": 1,
66
+ "bundle_sha256": "89e1f1751c8683837e61b7ee48b26b60e15ed4991e2de7fab1dbc096281a2668",
67
+ "reviewer": "fable-issues-story",
68
+ "decision": "approve",
69
+ "checked_images": [
70
+ "issues-page.png",
71
+ "report-history.png",
72
+ "today-open-reports.png",
73
+ "cli-list.png"
74
+ ],
75
+ "checks": {
76
+ "tokens_absent": true,
77
+ "personal_data_absent": true,
78
+ "feature_relevant": true,
79
+ "multiple_ui_scenes": true,
80
+ "captions_accurate": true
81
+ },
82
+ "findings": []
83
+ }
84
+ }
@@ -0,0 +1,7 @@
1
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓
2
+ ┃ Report or request ┃ Status ┃ Sent ┃
3
+ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩
4
+ │ Add a dark theme to the printed agenda │ Received │ 08 Nov 2026 │
5
+ │ The footer clock jumps by a pixel every minute │ Being worked on │ 06 Nov 2026 │
6
+ │ Weather shows yesterday's rain after waking up │ Released in 0.9.27 on 7 Nov 2026 │ 04 Nov 2026 │
7
+ └────────────────────────────────────────────────┴──────────────────────────────────┴─────────────┘
@@ -0,0 +1 @@
1
+ <!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>heinzel-issues screenshots</title><style>body{font:16px/1.6 system-ui;margin:2rem;background:#faf8f3;color:#263b32}main{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr));gap:1rem}figure{margin:0;padding:1rem;background:white;border:1px solid #d8ddd3;border-radius:12px}img{width:100%;height:auto}figcaption{margin-top:.75rem}a:focus-visible{outline:3px solid #a64028}</style><h1>heinzel-issues</h1><p>Isolated demonstration profile · Core 0.9.42 · Review these captures before committing. Click an image to inspect it at full size.</p><main><figure><a href="issues-page.png"><img src="issues-page.png" alt="Three fictional reports: received, being worked on, and released in 0.9.27 — with a form to send another"></a><figcaption>UI · Three fictional reports: received, being worked on, and released in 0.9.27 — with a form to send another</figcaption></figure><figure><a href="report-history.png"><img src="report-history.png" alt="A fictional report opened: what was sent, the file sent with it, and its history up to the release"></a><figcaption>UI · A fictional report opened: what was sent, the file sent with it, and its history up to the release</figcaption></figure><figure><a href="today-open-reports.png"><img src="today-open-reports.png" alt="Your open fictional reports and requests on Today, in dark mode; done ones leave the list"></a><figcaption>UI · Your open fictional reports and requests on Today, in dark mode; done ones leave the list</figcaption></figure><figure><a href="cli-list.png"><img src="cli-list.png" alt="The same fictional reports and their plain states through the real CLI"></a><figcaption>CLI · The same fictional reports and their plain states through the real CLI</figcaption></figure></main></html>