You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
9.1 KiB
208 lines
9.1 KiB
|
2 months ago
|
---
|
||
|
|
name: lights-out
|
||
|
|
description: Use when the user is going to bed, going away, or wants unattended overnight coding work; says "lights out", "run this overnight", "keep working while I sleep", or names gnhf; asks to check on, steer, or stop a running overnight job; asks "how did last night's run go", says "good morning", or wants a morning review of an agent run; or gives review findings on the results of an overnight run.
|
||
|
|
---
|
||
|
|
|
||
|
|
# Lights Out
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Lights Out delegates a long-running coding objective to `gnhf`, which loops a coding agent until a
|
||
|
|
natural-language stop condition is met. Scout prepares and supervises the run; **gnhf executes it**.
|
||
|
|
|
||
|
|
Core rule: **you orchestrate, gnhf implements.** Do not hand-edit files inside a scope a live gnhf
|
||
|
|
worker owns. If the work needs correcting, launch a new bounded run rather than taking over.
|
||
|
|
|
||
|
|
Second rule: **a stop condition being met is not acceptance.** "Stopped" only means the worker
|
||
|
|
stopped. Compare the result against the user's actual request and your own fresh verification.
|
||
|
|
|
||
|
|
## Why a wrapper instead of running gnhf directly
|
||
|
|
|
||
|
|
The Scout session that starts a night run is usually gone before it ends — the app gets closed, the
|
||
|
|
machine is left alone. So anything that must happen at exit cannot live in the conversation.
|
||
|
|
|
||
|
|
| Tier | Runs as | Guaranteed | Responsibility |
|
||
|
|
|---|---|---|---|
|
||
|
|
| Finalize | PowerShell, inside the detached worker | Always | Capture commits, diff, end-state, re-run verification, write the vault note |
|
||
|
|
| Judgment | You, on demand | When asked | Assess quality, decide merge vs follow-up, fill in the Assessment section |
|
||
|
|
| Push | One-shot automation | Opt-in | Morning Teams digest |
|
||
|
|
|
||
|
|
Never promise the user a summary that depends on this session still being alive.
|
||
|
|
|
||
|
|
## Scripts
|
||
|
|
|
||
|
|
Always go through these. Never invoke `gnhf` directly — the preflight is the entire point.
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
$LO = "$env:USERPROFILE\.scout\m-skills\lights-out\scripts"
|
||
|
|
```
|
||
|
|
|
||
|
|
| Script | Use |
|
||
|
|
|---|---|
|
||
|
|
| `$LO\start-run.ps1` | Preflight, launch detached, register the run |
|
||
|
|
| `$LO\check-run.ps1` | Reconstruct state: polling, morning review, "what happened" |
|
||
|
|
|
||
|
|
State registry: `~\.scout\lights-out\runs.json`. **This is the handoff file.** A brand-new session
|
||
|
|
with no memory of the launch conversation finds every run here. Read it before saying you don't know
|
||
|
|
about a run.
|
||
|
|
|
||
|
|
## gnhf is vendored
|
||
|
|
|
||
|
|
The skill ships its own pinned copy of gnhf at `vendor\node_modules\gnhf\`, so it does not depend on
|
||
|
|
a global `npm install -g gnhf` and cannot be broken by someone uninstalling or upgrading one.
|
||
|
|
Resolution order:
|
||
|
|
|
||
|
|
1. `$env:LIGHTS_OUT_GNHF` — explicit override (used by the test suite)
|
||
|
|
2. the vendored copy, run as `node vendor\node_modules\gnhf\dist\cli.mjs`
|
||
|
|
3. `gnhf` on PATH — fallback only
|
||
|
|
|
||
|
|
Only `node` needs to be on PATH. Every run records which one it used (`gnhfKind`, `gnhfVersion`) in
|
||
|
|
the registry and the vault note, so a behavior change after an upgrade is traceable.
|
||
|
|
|
||
|
|
To update the pinned copy:
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
npm install gnhf --prefix "$env:USERPROFILE\.scout\m-skills\lights-out\vendor"
|
||
|
|
pwsh -NoProfile -File "$env:USERPROFILE\.scout\m-skills\lights-out\scripts\test\e2e.ps1"
|
||
|
|
```
|
||
|
|
|
||
|
|
Re-run the suite after upgrading — it asserts the flags the wrapper passes still exist.
|
||
|
|
|
||
|
|
## Launch
|
||
|
|
|
||
|
|
Gather these before launching. Ask for anything missing rather than guessing:
|
||
|
|
|
||
|
|
- **Repo path** — must be a git repo with a clean tree.
|
||
|
|
- **Objective** — one concrete outcome.
|
||
|
|
- **Stop condition** — observable. "Looks good" is not one; "`npm test` exits 0 and no files outside
|
||
|
|
`src/utils` changed" is.
|
||
|
|
- **Verification command** — how success is checked. Must actually exist on this machine.
|
||
|
|
- **Agent** — default `copilot`. Others: `claude`, `codex`, `cursor`, `opencode`, `rovodev`, `pi`,
|
||
|
|
`acp:<target>`.
|
||
|
|
- **Mode** — Hands-Off or Companion (below).
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
& "$LO\start-run.ps1" `
|
||
|
|
-RepoPath 'D:\Repos\myapp' `
|
||
|
|
-Prompt '<worker prompt — see references\prompts.md>' `
|
||
|
|
-Title 'Short Title For The Vault Folder' `
|
||
|
|
-StopWhen '<observable condition>' `
|
||
|
|
-VerifyCommand 'npm test' `
|
||
|
|
-Agent copilot `
|
||
|
|
-MaxIterations 40 `
|
||
|
|
-Mode hands-off
|
||
|
|
```
|
||
|
|
|
||
|
|
Returns JSON. If `ok` is `false`, **report the `problems` list to the user and stop.** Do not try to
|
||
|
|
work around a failed preflight — each check maps to a way the night silently dies:
|
||
|
|
|
||
|
|
| Check | What it prevents |
|
||
|
|
|---|---|
|
||
|
|
| gnhf unresolvable | Vendored copy deleted and no global install — nothing to run |
|
||
|
|
| Empty prompt | gnhf blocks forever reading stdin with no TTY |
|
||
|
|
| Dirty working tree | gnhf refuses to start |
|
||
|
|
| Already on a `gnhf/*` branch | Triggers an interactive overwrite prompt that hard-fails without a TTY |
|
||
|
|
| Agent CLI missing | Run dies on iteration 1 at 2am |
|
||
|
|
| Verify command not on PATH | The classic: docs say `pnpm`, machine only has `npm` |
|
||
|
|
|
||
|
|
Pass `-Worktree` to run alongside other work, `-CurrentBranch` to commit on the current branch, and
|
||
|
|
`-Push` to push after each successful iteration.
|
||
|
|
|
||
|
|
## Modes
|
||
|
|
|
||
|
|
**Hands-Off** — bounded task, clear verification, user is asleep. Launch, report the run id, stop.
|
||
|
|
Intervene only for hard failure or destructive behavior.
|
||
|
|
|
||
|
|
**Companion** — uncertain, exploratory, or design-heavy work; the user is around and wants steering.
|
||
|
|
Default to Companion when the user asks to iterate until satisfied, supplies review findings, or
|
||
|
|
asks for supervision. Poll with `check-run.ps1` between iterations.
|
||
|
|
|
||
|
|
## Steer
|
||
|
|
|
||
|
|
In Companion mode, judge each poll:
|
||
|
|
|
||
|
|
| Signal | Action |
|
||
|
|
|---|---|
|
||
|
|
| Real blocker found | Stop; relaunch with blocker-specific instructions |
|
||
|
|
| Good partial slice | Let it run, or tighten the next stop condition |
|
||
|
|
| Skipped requested research | Relaunch with research as the explicit first deliverable |
|
||
|
|
| Touching unrelated files | Stop and review before continuing |
|
||
|
|
| Claims success, verification disagrees | Review now; relaunch only with an evidence-based stop condition |
|
||
|
|
| User says not good enough | Relaunch with that finding as the sole bounded correction |
|
||
|
|
|
||
|
|
Steering means a **new bounded run**, not editing the files yourself.
|
||
|
|
|
||
|
|
## Morning Review
|
||
|
|
|
||
|
|
Triggered by "good morning", "how did it go", or any post-run check-in. **Never answer from memory
|
||
|
|
and never ask the user what to review.** Reconstruct:
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
& "$LO\check-run.ps1" -Since 2
|
||
|
|
```
|
||
|
|
|
||
|
|
Then:
|
||
|
|
|
||
|
|
1. If `status` is `running`, say so first — it is still working; report progress, don't judge it.
|
||
|
|
2. If `status` is `orphaned`, the worker died without finalizing (reboot, kill, power loss). Say
|
||
|
|
that plainly; the vault note will be missing and artifacts may be partial.
|
||
|
|
3. Read `vaultNote`, `notesTail`, and the commits. Treat gnhf's notes as **claims, not evidence**.
|
||
|
|
4. Run independent verification yourself — the recorded `verifyExitCodeAfter` is a starting point,
|
||
|
|
not a substitute for looking at the diff.
|
||
|
|
5. Compare against the stop condition *and* what the user originally asked for.
|
||
|
|
6. Decide: **Mergeable**, **Needs follow-up run**, or **Do not merge**.
|
||
|
|
|
||
|
|
Then write the judgment back into the vault note (below). Do not merge unless explicitly authorized.
|
||
|
|
|
||
|
|
## Writing the assessment back
|
||
|
|
|
||
|
|
The wrapper leaves `## Assessment` as a stub. Complete it:
|
||
|
|
|
||
|
|
1. Open the `vaultNote` path from `check-run.ps1`.
|
||
|
|
2. Replace the Assessment section with your findings and verdict.
|
||
|
|
3. Set `status: active` in frontmatter, swap the `status/draft` tag for `status/active`, bump
|
||
|
|
`updated:`.
|
||
|
|
4. Leave every other file in the folder untouched — they are raw artifacts (vault rule 4).
|
||
|
|
|
||
|
|
## Findings
|
||
|
|
|
||
|
|
When the user says "that's not right", "scope drift", "you missed X", or "why did it stop":
|
||
|
|
|
||
|
|
1. Treat the run as Companion from now on.
|
||
|
|
2. Convert each finding into one observable correction, preserving the user's wording and scope.
|
||
|
|
3. Relaunch on the same repo with a bounded prompt (see `references\prompts.md`).
|
||
|
|
4. Review again. Repeat until no blocking findings remain or a real blocker surfaces.
|
||
|
|
|
||
|
|
## Optional morning digest
|
||
|
|
|
||
|
|
Only if the user wants a phone ping. Offer it at launch; never create it silently. Use a **one-shot**
|
||
|
|
automation so it auto-disables and does not accumulate:
|
||
|
|
|
||
|
|
```
|
||
|
|
m_create_automation(
|
||
|
|
name: "Lights Out digest — <run id>",
|
||
|
|
schedule: "every day at 7am", // the next morning
|
||
|
|
oneShot: true,
|
||
|
|
teamsNotify: "always",
|
||
|
|
prompt: "Run the lights-out Morning Review for run <run id>: execute
|
||
|
|
$env:USERPROFILE\\.scout\\m-skills\\lights-out\\scripts\\check-run.ps1 -Id <run id>,
|
||
|
|
assess the result, write the assessment back into the vault note, and send a short digest."
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
The digest is a convenience. The artifacts land on disk with or without it.
|
||
|
|
|
||
|
|
## Safety
|
||
|
|
|
||
|
|
- Never run destructive git commands to tidy a gnhf branch. The branch *is* the night's work.
|
||
|
|
- Never present a worker's success summary as verified fact.
|
||
|
|
- If the user is away, produce branches and a report — not merges, not pushes to shared branches,
|
||
|
|
unless they explicitly authorized it beforehand.
|
||
|
|
- A run left on `status: running` with a dead worker is `orphaned`, not successful. Say so.
|
||
|
|
- Stop conditions must be observable. Rewrite vague ones before launching.
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- `references\prompts.md` — worker, steering, and findings prompt templates.
|
||
|
|
- `references\cli.md` — gnhf flags and agent roster (a cache; `gnhf --help` is the source of truth).
|