| name | dev-issue-unattended |
| description | Run one or more GitHub issues through their full lifecycle end-to-end with NO pauses for user input — investigate, decide the approach, gather test context, and run the CI/review loop entirely autonomously, documenting every judgment call for after-the-fact review instead of asking. Accepts a single issue, a batch of issue numbers/URLs, or an unfiled bug/request described in plain text. Use ONLY when the user has explicitly said they will be unreachable (away from the computer, asleep, offline) and wants the issue(s) shipped as mergeable PR(s) without them. Do not use this for normal work — use dev-issue instead, which asks for input at the same points this skill auto-resolves.
|
| argument-hint | [issue-number|issue-url][, issue-number|issue-url ...] | problem description |
Full Issue Lifecycle, Unattended (HMIS)
This is dev-issue with every input-gate replaced by an autonomous,
evidence-documented decision. dev-issue itself is unchanged and remains
the default — use it whenever the user is actually present. Reach for this
skill only when the user has told you up front they won't be reachable.
Invoking this skill is explicit authorization for every commit/push/PR/issue
step below, including filing the GitHub issue itself if none exists yet — do
not re-ask before any of them.
0. Parse input
Accept a comma/space/newline-separated list mixing bare issue numbers
(23100) and full GitHub issue URLs. Accept only bare numeric tokens or a
URL matching exactly ^https://github.com/hmislk/hmis/issues/(\d+)/?$ —
any other host or repo path (e.g. a URL pointing at a fork or a different
project) is an invalid token, not a source of an issue number for this
repo. Report invalid tokens rather than guessing at what they meant.
- Dedupe the resulting set of valid numbers.
- Validate each with
gh issue view <n> --repo hmislk/hmis --json title.
Only drop-and-continue when GitHub itself confirms the issue doesn't
exist (a clean "not found" from gh) or the token was invalid per the
URL rule above — note "could not resolve issue #N" (or the raw invalid
token) for the final summary (step 15) and move on. Any other failure
from this command — auth, permission, rate-limit, network/transport
errors — is not evidence the issue doesn't exist; it's the "true
whole-batch abort" case from the Hard limits section below (gh itself
is unreachable/broken), since it will affect every remaining issue the
same way. Stop and report it rather than silently dropping issues one by
one.
- Process the remaining issues one at a time, lowest issue number
first. Steps 1–14 below are the per-issue body of this loop: each issue
gets its own branch (via
start-issue), its own commits, its own PR, and
its own review loop, exactly as if dev-issue-unattended had been run
solo on just that issue.
- If an issue hits any stop — an existing hard limit, the "insufficient
issue description" flag (see Hard limits below), or the "could not
resolve" case above — record the outcome for that issue and move on to
the next one. The batch is done once every issue in the list has been
attempted.
- A single free-text problem description with no issue number (the
existing "if given only a problem description" mode in step 1) is
unchanged and is not part of batch mode — it still handles exactly one ad
hoc request per run.
Hard limits — never bypassed, no matter how confident
These are not judgment calls. If one of these is required to proceed, STOP,
post the blocker as a comment on the issue (creating one first if needed),
and end the run — do not guess. "End the run," here and everywhere else
in this skill, is always scoped to the current issue: in batch mode
(step 0), it means stop work on this issue, record its outcome, and
continue the batch with the next one — never abort the whole batch.
Reserve a true whole-batch abort for a failure that isn't scoped to one
issue at all (e.g. gh itself is unreachable) — that's outside anything
documented here, and warrants stopping and asking rather than guessing.
- Never merge a PR, and never push directly to
development, master, or
any production branch — everything goes through a PR.
- Never touch anything outside this repo (plus its
../hmis.wiki sibling,
needed for step 10's documentation publishing), the local Payara/MySQL dev
environment, and the GitHub API for this repo — no remote/production hosts.
- Never write a security-privilege or access-control change autonomously.
- Never write, apply, or execute a database schema/migration change
autonomously — if the fix needs one, stop and describe what's needed
instead of designing it unsupervised. Step 5a's DDL regeneration is the one
narrow exception, and only as far as
generate-ddl itself goes:
generating the tmp/createDDL.jdbc artifact for a column that's a direct,
evidence-backed part of the approved fix. Applying that DDL to any
database — even local — stays a human's call via the admin UI's "Add
Missing..." page, same as it always is; this skill never runs it.
- Never write to a remote database — production, staging, or anything
reached over an SSH tunnel. Read-only there, always, no exceptions.
A local database (localhost, no tunnel) is a disposable test
environment: no development environment is ever set up on a hosting
server, so "the database is local" is a reliable proxy for "this is safe
to modify freely". Confirm it genuinely is local before the first write —
the JNDI name in
persistence.xml plus a localhost host with no active
tunnel on the DB port. If a datasource points anywhere else, treat it as
remote and stop. Create, mutate, and abandon local test data as needed —
do not revert it afterwards or treat local rows as precious.
Preferring to generate data through the app still applies as guidance
(playwright-e2e
§15),
because a fixture that bypasses the app's own validation can pass a test
while proving nothing — but locally that is a judgement call, not a hard
limit, and direct SQL is fine when it is simply the faster route. See
step 4.
- Never put institution names, patient/doctor names, or credentials in any
GitHub issue, PR, or comment (same rule as
dev-issue, non-negotiable here
too since there's no human proofreading before it posts).
- Never resolve genuinely ambiguous behavior — where the codebase, git
history, and related issues give no clear signal either way — by picking an
option silently. That is exactly the "stop and flag" case in steps 3 and 14.
Insufficient issue description — hand back to the reporter, don't just stop
Two flavors of stop below get a different resolution than the rest of this
section — this one and "Cannot reproduce with adequate information" further
down. This one: when a stop at step 2, 2a, or 3 traces back to the
issue's own description being inadequate — not a code-architecture
question, not a schema/security limit — hand it back to whoever filed it
instead of posting a bare blocker comment.
This is a judgment call at runtime, same as any other step-3 decision:
document the reasoning. When genuinely unclear whether a stop is a
description problem or an architecture problem, default to the plain hard
limit above (post a blocker comment and stop) — don't reassign work to a
reporter who can't actually resolve a code-level question.
When it does fire:
-
Look up the issue's creator first, before composing anything:
gh issue view <n> --repo hmislk/hmis --json author --jq '.author.login'.
If this fails or returns an empty login, stop here — do not post the
comment, edit the assignee, or touch the project board with a broken or
missing @mention. Record this issue's outcome as "stopped — could not
resolve issue creator" for the batch summary (step 15) and continue to
the next issue.
-
Post a comment on the issue that opens with @<creator-login> and asks
only for what actually stalled this run — drawn from, not a fixed
template dumped every time:
- the exact page/screen: URL or menu breadcrumb (
Menu > Submenu > Page)
- a clear description of current vs. expected behavior
- for report/analytics requests: desired filters, columns, grouping
- repro steps that pin down the scenario without a real record
identifier — ask for a redacted/synthetic example (e.g. "a BHT like
the one in this scenario, with any real patient/bill numbers replaced")
rather than a real BHT or bill number, same "no patient-linked
identifiers in a GitHub comment" rule as the hard limits above
- screenshot(s) of the current behavior or desired layout
Ground the ask in what was actually tried, e.g. "Searched for a page
matching this description under Inward and Reports; couldn't identify
which screen this refers to. Could you share the URL or navigation
path?" — not a bare template.
-
gh issue edit <n> --repo hmislk/hmis --add-assignee <creator-login> —
added alongside buddhika75, never replacing them.
-
Set the project-board (#11) Status field back to Backlog (same
GraphQL mutation pattern start-issue step 5 uses to set it forward to
"In Progress" — same field, different target option).
-
Check each of steps 2–4 actually succeeded (non-error gh/API output)
before calling this "needs info" — if one failed partway (e.g. the
comment posted but the assignee edit errored), don't silently record it
as fully done; note exactly which parts succeeded in the batch summary
(step 15) so it's clear what still needs finishing by hand.
-
Record this issue's outcome as "needs info" for the batch summary (step
15), then continue to the next issue in the batch (step 0).
Cannot reproduce with adequate information — close and invite discussion
The second special-cased flavor: step 2a's bug genuinely does not reproduce
under a reasonable, documented attempt, and the issue already gave
enough to work with — this is distinct from the missing-specifics case
above, which stays on the "ask for more info, keep open" path. Here, more
async back-and-forth isn't likely to help; close the issue instead of
leaving it open indefinitely with just a blocker comment, and let the
reporter bring it back with a live discussion if it's still happening.
- Look up the issue's creator first, same as the Insufficient issue
description flow above — including its failure guard: if the lookup
fails or returns an empty login, stop here without posting or closing.
Record "stopped — could not resolve issue creator" for the batch summary
(step 15) and continue to the next issue.
- Post a comment that opens with
@<creator-login>: what was tried, what
didn't reproduce, and an explicit invite to discuss rather than reopen
async — e.g. "Attempted to reproduce via ; did not
observe the described behavior. Closing for now — if this is still
occurring, let's discuss and file a fresh issue with updated repro
details."
gh issue close <n> --repo hmislk/hmis --reason "not planned".
- Check that both the comment and the close actually succeeded before
calling this outcome final — if the close command errors after the
comment posted, note that in the batch summary rather than assuming the
issue is closed.
- Record this issue's outcome as "closed — could not reproduce" for the
batch summary (step 15), then continue to the next issue.
1. Setup
If given an issue number: run the start-issue skill for it, as
dev-issue step 1 does.
If given only a problem description (no issue number): do step 2's
investigation first, using gh issue list --search to check for an existing
duplicate. If none exists, file the issue yourself with gh issue create —
structure it like a normal bug/feature issue (Problem / Root cause found /
Proposed fix / Acceptance criteria), then run start-issue on the number you
just created. Filing the issue is not optional busywork — it's what makes the
rest of this run auditable later. Redact before filing — the supplied
problem description may itself contain an institution/patient name; strip it
per the hard limit below before it becomes the public issue body.
2. Investigate
Same as dev-issue step 2: read the issue, explore the code (Explore agent
for anything spanning more than a few files), identify the entities/pages
involved and the existing patterns to follow. For bug issues, try to pin down
root cause by reading code — git archaeology (git log -p -S<term>,
git blame, related closed issues/PRs) is often decisive here and costs
nothing to try before falling back to live reproduction.
If this investigation — including the git archaeology above — cannot
identify which entities/services/pages are even involved, that's the
Insufficient issue description case from the Hard limits section, not
a reason to guess. Route there instead of continuing to step 2a/3.
2a. Reproduce the bug (bug issues only, root cause still unconfirmed)
Skip for feature/enhancement issues and for bugs where step 2 already found a
confirmed root cause from code + history alone.
- Prefer non-mutating reproduction first (read-only navigation, API
GETs)
against existing data.
- If reproduction needs a record that doesn't exist in the local DB, do
not ask which one to use — auto-discover the closest real match with a
read-only query, and only fall back to generating one through the app (see
step 4) if nothing suitable exists.
- If it still doesn't reproduce under a reasonable, documented attempt: stop
rather than guessing at a fix for a bug you couldn't observe. If the reason
it didn't reproduce is missing specifics from the issue itself (no concrete
example record, no repro steps, an ambiguous "sometimes it fails" with no
stated conditions), that's the Insufficient issue description case —
route there. If instead the issue gave enough to try and it genuinely
doesn't reproduce, that's the Cannot reproduce with adequate
information case — close it and invite a discussion instead of leaving
a blocker comment open indefinitely. This is a hard limit either way, not
a style preference — an unverified fix for an unreproduced bug is worse
than no fix.
3. Decide the approach (no Plan Mode pause)
Where dev-issue enters Plan Mode and waits for approval, instead:
- Gather the same evidence a plan would need — related issues/PRs, git
history of the affected code, in-code comments explaining prior intent
(e.g. this is how issue #22931's fix found and extended the intent behind
the original #19963 design instead of guessing at a new one).
- Pick the option best supported by that evidence. When two options are
both plausible and the evidence doesn't clearly favor one, that is
"genuinely ambiguous" — stop, but which stop depends on why it's
ambiguous: if the codebase itself gives conflicting signals (two
existing patterns both plausible), use the plain hard limit above (post
a blocker comment and stop). If the ambiguity is instead about what
the reporter wants — e.g. a report request with no filters/columns/grouping
specified, a feature request with no acceptance criteria — that's the
Insufficient issue description case; route there instead.
- Write the reasoning down now, in a form that survives to the PR
description (step 13) and, for any non-obvious interpretation, an issue
comment — not just in conversation. The user is reviewing this after the
fact instead of before, so the trail has to carry the weight a Plan Mode
approval normally would.
4. Gather test context (no AskUserQuestion pause)
Where dev-issue step 4 asks for department/records/environment, instead
query the local DB yourself for something real and relevant:
SELECT ... FROM <entity-table> WHERE <feature-relevant condition>
ORDER BY <recency> LIMIT 5;
- Prefer an existing record over creating one — it's already representative.
- If nothing suitable exists, generate it through the app (per
playwright-e2e
§15:
create a purchase before a return, a shift-start before a shift-end, etc.)
instead of asking which record to use. Going through the app is preferred
because it exercises the same validation and business logic the fix has to
survive.
- If the app can't get you there (the path is blocked by unrelated broken
data, or needs a second user session you don't have credentials for),
write the local database directly —
INSERT/UPDATE is fine on a
local DB. Say so in the PR, and be aware of what a hand-built fixture
skips: if it bypasses the very validation the fix depends on, the test
proves less, so prefer the app route when the difference matters.
- Never do any of this against a remote/tunnelled database (see Hard
limits). Locally, don't revert or clean up test data afterwards — a local
DB is disposable and the next run can reset it.
- Environment is local Payara unless the issue explicitly requires otherwise
— never assume a remote/production environment unattended (hard limit).
5. Develop
Same as dev-issue step 5 — delegate by file type (java-backend-developer,
jsf-frontend-dev), review each agent's actual diff before moving on.
5a. Regenerate the DDL if the schema changed
Same as dev-issue step 5a — but see the hard limit above: this covers
generating DDL for a column that's a direct, already-decided part of the
fix, not designing new schema unsupervised and not applying/executing the
generated script against any database.
6. Build and local redeploy
Same as dev-issue step 6 (adapt the exact commands to whichever machine
this session is running on — see the playwright-e2e skill and this
project's local-environment memory for the current host's paths/ports).
Check the server log for deploy errors before moving on.
7. Test with Playwright + verify in DB
Same as dev-issue step 7: exercise the feature with the department/records
from step 4, screenshot each meaningful stage into tmp/, verify in the DB.
If step 4 generated new records through the app, this is also where you
confirm the fix's actual effect on them (e.g. confirm a bypassed guard left
a pending record untouched rather than silently resolving it).
8. Iterate
Same as dev-issue step 8 — fix, rebuild, retest until it passes end-to-end.
If 3+ fix attempts don't converge, that's the systematic-debugging
architecture-question trigger, not a reason to keep guessing: stop, post
findings, end the run.
9. Record learnings
Same as dev-issue step 9 — append new Playwright/dev gotchas to
developer_docs/testing/playwright-e2e-workflow.md if any surfaced.
10. Publish evidence and update the wiki
Same as dev-issue step 10 — including its required wiki-page update
(find the page, embed the screenshots, replace outdated images, correct any
text the change makes wrong, or create/skip the page with the reason stated),
and linking the updated page(s) in the issue comment. Publishing an image
without wiring it into a page leaves it orphaned; that is not a completed
step 10.
Two additions for unattended runs:
-
Extra weight on redaction, since no human reviews the screenshots
before they're published: when in doubt about a screenshot, crop tighter or
drop it rather than publish it uncertain. This applies to the wiki page too
— a page edit is as public as an issue comment.
-
Wiki prose: only publish what you can verify. A wrong page edit is
public the moment it's pushed, and noting it in the PR afterwards doesn't
unpublish it. So the test is not "am I confident?" but "can I point at the
code, or at evidence from this run, that shows the current text is wrong?"
- Publish — inserting verified screenshots, and correcting text that
demonstrably contradicts the code or the behaviour you just verified.
Cite the evidence in the PR (e.g. "page documented room discharge via
roomDischargeDateTime; hasActiveRoom() deliberately stopped using
that field in #21935").
- Leave it and flag it — anything you'd be inferring: prose that
merely reads as unclear or outdated, claims about behaviour outside what
this run touched, or restructuring a page's scope. Note it in the PR as a
documentation issue for a human, rather than rewriting it unattended.
Record every prose change either way in the "Decisions made without
approval" section of the PR (step 13).
11. Pre-push check
Same as dev-issue step 11 — restore persistence.xml placeholders before
staging.
12. Commit and push
Same as dev-issue step 12 (commit format per
Commit Conventions,
restore local JNDI unstaged after push) — and fold step 3's documented
reasoning into the commit body so it's not only in the PR description. A
commit body is published the moment it's pushed: redact it per the hard
limit above before writing it, same as an issue or PR body.
13. Create the PR
Same as dev-issue step 13 — including its required Documentation
section linking the wiki page(s) updated in step 10 (or stating that none was
needed, and why) — plus a "Decisions made without approval" section up
front listing every step-3 judgment call in one place, so the user can scan
exactly what to double-check first. Any wiki prose you rewrote belongs in
that list. Redact this body per the hard limit above too — same as every
other publication point.
14. Review loop (until mergeable) — waiting without the user present
Repeat, up to 3 cycles:
- Use
Monitor (poll gh pr checks <PR#> --json name,bucket, emit each
newly-resolved check) to wait for CI instead of a synchronous watch. Use
ScheduleWakeup as a fallback heartbeat (~20 min) in case the monitor is
missed, per this project's autonomous-session pattern.
- If checks fail: investigate, fix, push, go to 1.
- Once checks pass: run the
review-pr skill. Auto-apply fixes matching its
documented false-positive/valid-fix patterns.
- A genuinely ambiguous review comment is a hard-limit stop, same as step 3
— post your assessment as a reply and end the run rather than guess.
- Checks passing and no unresolved comments are necessary but not
sufficient. Confirm mergeability itself:
gh pr view <PR#> --json mergeable,mergeStateStatus,isDraft,reviewDecision
— done only once mergeable: MERGEABLE, mergeStateStatus: CLEAN,
isDraft: false, and reviewDecision isn't blocking (e.g. not
CHANGES_REQUESTED). A required-approval reviewDecision with no
reviewer assigned isn't something this skill can resolve — that's normal
(a human still has to approve/merge, see step 15), not a stop condition.
3 cycles without convergence → stop, summarize the sticking point, end the
run (same as dev-issue).
15. Notify
Produce one skimmable summary covering every issue in the batch (a
single issue is just a batch of one), one line each:
#N — shipped as PR #M (link to the PR)
#N — needs info from reporter (link to the comment posted in the
Insufficient issue description flow)
#N — closed, could not reproduce (link to the closing comment)
#N — stopped: <short reason> (link to the blocker comment)
#N — could not resolve issue number/URL
For issues that shipped, include what was found, every decision made and
why (from step 3/13), what was verified and how, and links to the
issue/PR/wiki — same depth as a solo run. For issues that didn't ship, the
link to the comment is enough; don't re-summarize what's already written
there. Never merge.