Repository navigation
feat(app-control): fill the threads capture row for JVM, .NET, Go and native #9490
Description
Scope now (narrowed 2026-10-27)
#9532 / #9542 shipped the threads kind with py-spy dump, the analyze-profile direct-read branch, the elevated route and the ## Next routing. Pid-binding and eval follow-ups are #9546. This issue now covers only the remaining Format rows below: the JVM, .NET, Go and native (gdb) cells, and Node.js n/a. The decision record in the comments carries the criteria. Correction to that record: the browser-page cell and macOS (sample) are out of scope; leave them as they are.
Problem
/app-control:drive has no capture kind for a hung process, a stack sample of every thread. Its control-skill table maps jank and hang to the one trace kind, but they use different tools per runtime: for example JFR for jank and jcmd thread dump for hang. That breaks drive's one-tool-per-kind rule. PR #9328 left the hang row as a capability gap after four review rounds on a threads kind kept finding gaps (commits df1a6eb through 7d2a3f4 on that branch hold the attempt).
What a threads kind needs (from those reviews)
- Analysis path: analyze-profile's flow sends every artifact to an exporter and then queries SQLite (
analyze-profile/SKILL.md:60-62). A thread dump is text read directly, so the skill needs a direct-read branch for it, with an eval that reads a real dump. - Pid binding: a pid-targeting tool (py-spy dump,
jcmd, dotnet-stack, gdb) may capture only the pid this run launched. Drive must record that pid and check it before each capture. A name lookup such aspgrep -f nodecould otherwise reach a process the person owns, unattended included. - Elevation: a launched-process capture that needs elevation goes through drive's shown-script route, and needs an eval.
- Format rows: py-spy dump,
jcmdthread dump, dotnet-stack, goroutine dump and gdbthread apply all bt, each with an anchored manual pointer, an as-of date and a recheck trigger. Node.js has no file-writing all-thread dump, so its cell is n/a. A Go dump through SIGQUIT exits the process, so preferdebug/pprof/goroutine?debug=2. - Routing: drive's
## Nextsends a threads artifact to analyze-profile.
Activity
refactor(app-control): move the threads capture kind out to #9490
github-actions commentedon Oct 26, 2026
The triage sweep dispatched intake triage for this issue (attempt 1 of 2).
github-actions commentedon Oct 26, 2026
Proposed work class: work-class: scoped
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Low
Uncertainty: Known
Flags: none
Blocked by: none
I read this as: fill the remaining
threads(hang) cells inplugins/app-control/reference/control-skill.md. The JVM, .NET and gdb cells already read as filled on main, each with a manual pointer, as-of date and recheck trigger. The Go cell still reads "not yet". It needs the goroutine dump command (debug/pprof/goroutine?debug=2) and its pointer, as-of date and recheck trigger. Beyond that, check the.changes/app-control/fragment and the "not yet" in the macOS half of the Native cell. The narrowed scope leaves macOS and the browser page as they are.Nothing is missing. I found no duplicate. Pid binding, elevation and evals stay with #9546.
Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Oct 26, 2026
Not admitted to the issue lane: no trusted-human acceptance criteria: a listed human must put the confirmed
- [ ]criteria in the body or post them as their own comment, or, on an issue a listed human filed, intake's newest refinement comment must hold them unedited. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).melodic-automation-lanes commentedon Oct 26, 2026
The latest triage verdict holds nothing: the issue is at
status: ready.melodic-automation-lanes commentedon Oct 26, 2026
Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.
Intended outcome: Close as done for the threads kind with py-spy dump; track the remaining runtime rows (jcmd, dotnet-stack, goroutine, gdb, Node n/a) in a narrower issue if wanted.
Related work
Open questions
RECOMMENDED: Yes. Close it and open a narrower issue for the per-runtime format rows only. Basis: plugins/app-control/reference/control-skill.md:60 shows only py-spy dump filled in and the other runtimes marked 'not yet'; plugins/app-control/CHANGELOG.md:61 says the other runtimes read 'not yet'.
RECOMMENDED: Yes. Leave those bullets to #9546. Basis: plugins/app-control/skills/drive/SKILL.md:133-152 already has the pid binding and the elevated route; #9546 is open for the remaining gaps.
Sources read
Automated refinement by the lanes App. Answer with a comment whose first line is
**Decision recorded.**.[-]feat(app-control): add a threads capture kind for hung processes[/-][+]feat(app-control): fill the threads capture row for JVM, .NET, Go and native[/+]5 remaining items
melodic-automation-lanes commentedon Oct 27, 2026
The lanes App's pull request #10497 merged with
Refs:, so this issue stays open and nothing starts the lane on it again. work-unblock removedstatus: readyandagent-ready, so the hourly triage sweep sends it back to intake triage, which decides what work is left and admits it again.melodic-automation-lanes commentedon Oct 28, 2026
Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.
Intended outcome: Fill the remaining Go cell of the hang (
threads) row in the control-skill reference with the pprof goroutine dump, add its manual pointer, as-of date and recheck trigger, and add a changelog fragment.Acceptance criteria
goroutine?debug=2endpoint, replacing 'not yet'.samplemanual note is not edited.Dependencies
Related work
Sources read
<pid>placeholder and no elevation prefix.Automated refinement by the lanes App. Admission counts only criteria a listed human wrote: to confirm these, post them as your own comment whose first line is
**Decision recorded.**, which sends the issue back through intake.melodic-automation-lanes commentedon Oct 28, 2026
The work-resolve-issue run that
agent-readystarted failed or was cancelled before it reported, or it stopped or the token broker refused it because its workflow files differ from main's. work-unblock removed and addedagent-readyback to start a fresh run on main's workflow files. If this run ends the same way, it re-fires the issue again, waiting longer each time.melodic-automation-lanes commentedon Oct 28, 2026
The work-resolve-issue lane stopped partway through this issue and needs a person.
Why, in the run's own words:
What the run says it did not do:
Run: https://github.com/melodic-software/claude-code-plugins/actions/runs/40628910072
To retry, remove
needs-humanand addagent-readyagain.kyle-sexton commentedon Oct 29, 2026
Re-triage: done, with Go left as "not yet" by design. This takes option (a) from the lane's stop (#9490 (comment)). Option (a) is the only one that keeps drive's pid-bound
threadsdesign. Option (b) would change that design and option (c) would change the capture contract, so neither fits this issue.Shipped: the JVM (
jcmd <pid> Thread.print), .NET (dotnet-stack report -p <pid>) and Linux native (gdb -p <pid> -batch -ex 'thread apply all bt') cells, plus Node.js n/a. They landed in #10497 (merged 2026-10-27, e278f34) and are atplugins/app-control/reference/control-skill.md:64on main at 489fb55. The macOS half and the browser page were already out of scope (see "Scope now" in the body).Why Go stays "not yet":
goroutine?debug=2is served by an HTTP endpoint the app starts, at an address the app picks. Nothing binds it to the launched pid, and drive allows athreadscapture only through the pid recheck (plugins/app-control/skills/drive/reference/pid-binding.md:44-57).dlv attach <pid>, thengoroutines -tandexit -d: https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_attach.md and https://github.com/go-delve/delve/blob/master/Documentation/cli/README.md#exit). Run without a terminal, though, it needs those commands on stdin (--allow-non-terminal-interactive) or in an--initfile. The capture contract allows only the<pid>and output<file>placeholders (control-skill.md:73-75), and the builder passes the command as plain arguments (pid-binding.md:48). An input file would be a contract change.Reopen if drive's capture contract gains an input-file placeholder, or if Go ships a pid-targeted goroutine dump that writes to stdout or a file.