@wildorder/nightshift 0.11.1 → 0.13.0
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.
- package/dist/author.d.ts.map +1 -1
- package/dist/author.js +43 -0
- package/dist/author.js.map +1 -1
- package/dist/cli.js +86 -3
- package/dist/cli.js.map +1 -1
- package/dist/commit-plan.d.ts +40 -0
- package/dist/commit-plan.d.ts.map +1 -0
- package/dist/commit-plan.js +154 -0
- package/dist/commit-plan.js.map +1 -0
- package/dist/decision-ledger.d.ts +10 -0
- package/dist/decision-ledger.d.ts.map +1 -1
- package/dist/decision-ledger.js +7 -0
- package/dist/decision-ledger.js.map +1 -1
- package/dist/exit-codes.d.ts +16 -2
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +17 -2
- package/dist/exit-codes.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/install-skills.d.ts +1 -1
- package/dist/install-skills.d.ts.map +1 -1
- package/dist/install-skills.js +5 -1
- package/dist/install-skills.js.map +1 -1
- package/dist/manifest.d.ts +47 -13
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +80 -11
- package/dist/manifest.js.map +1 -1
- package/dist/preflight.d.ts +73 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +225 -0
- package/dist/preflight.js.map +1 -0
- package/dist/publish.d.ts +36 -0
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +185 -0
- package/dist/publish.js.map +1 -1
- package/dist/run-program.d.ts +35 -1
- package/dist/run-program.d.ts.map +1 -1
- package/dist/run-program.js +224 -10
- package/dist/run-program.js.map +1 -1
- package/dist/skill-roots.d.ts +11 -3
- package/dist/skill-roots.d.ts.map +1 -1
- package/dist/skill-roots.js +59 -12
- package/dist/skill-roots.js.map +1 -1
- package/package.json +2 -2
- package/skills/backlog-capture/SKILL.md +182 -0
- package/skills/plan-program/SKILL.md +221 -5
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backlog-capture
|
|
3
|
+
description: Capture a discovered-but-deferred feature or larger piece of work as a durable backlog item, written now from the current session's context, so a future planning session starts warm. Use the moment you hit something bigger than the task at hand and want to remember why — in an interactive session with a human present. Do not use during an unattended or automated agent run.
|
|
4
|
+
argument-hint: "[what you discovered]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Capture a backlog item
|
|
8
|
+
|
|
9
|
+
A coding session routinely stumbles on something that is really a larger
|
|
10
|
+
feature: too big to absorb into the task at hand, valuable enough to become
|
|
11
|
+
future work. The expensive part of that moment is the context — which files
|
|
12
|
+
constrain the design, which approach was already tried and rejected and why,
|
|
13
|
+
what the naive version breaks. That context is gone by tomorrow. This skill
|
|
14
|
+
gives it a durable, repo-tracked home, written while you still hold it.
|
|
15
|
+
|
|
16
|
+
## When this fires
|
|
17
|
+
|
|
18
|
+
Fire this yourself, the moment you recognize the discovery, without waiting
|
|
19
|
+
for a human to ask for it. If capture waits until someone notices and
|
|
20
|
+
requests it, the context has already started to fade — the entire point is
|
|
21
|
+
to record it while it is still live.
|
|
22
|
+
|
|
23
|
+
Use this only in an interactive session with a human present to see what
|
|
24
|
+
gets written. Decline to use it during an unattended or automated agent
|
|
25
|
+
run — there is nobody there to review the capture, and this skill is not a
|
|
26
|
+
substitute for whatever that run already does with its own findings. If you
|
|
27
|
+
cannot tell whether a human is present for this session, do not use this
|
|
28
|
+
skill.
|
|
29
|
+
|
|
30
|
+
## The item format
|
|
31
|
+
|
|
32
|
+
This is the one canonical definition of a backlog item. Nowhere else in this
|
|
33
|
+
project restates it — if you find another description of the item format
|
|
34
|
+
elsewhere, this one wins.
|
|
35
|
+
|
|
36
|
+
An item is one file at `docs/backlog/{slug}.md`. One item per file, never
|
|
37
|
+
several discoveries folded into one file. The slug is the item's title,
|
|
38
|
+
lowercased and converted to kebab-case; do not invent a separate slug that
|
|
39
|
+
diverges from the title.
|
|
40
|
+
|
|
41
|
+
### Frontmatter
|
|
42
|
+
|
|
43
|
+
Frontmatter carries only the facts a later reader needs to act on
|
|
44
|
+
mechanically. Everything else belongs in the body as prose.
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
---
|
|
48
|
+
status: captured
|
|
49
|
+
captured: 2026-09-03
|
|
50
|
+
---
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- `status` — one of `captured | planned | done | declined`. A fresh capture
|
|
54
|
+
is always `captured`.
|
|
55
|
+
- `captured` — the date of capture, as `YYYY-MM-DD`.
|
|
56
|
+
- `planned-into` — the id of the program (the future piece of work) that
|
|
57
|
+
absorbed this item. **Absent until planned.** Do not write this field when
|
|
58
|
+
you capture an item; it is added later, by whatever later reads this
|
|
59
|
+
backlog as planning input, only at the moment this item's status becomes
|
|
60
|
+
`planned`.
|
|
61
|
+
|
|
62
|
+
Do not add a `title` or `slug` field. The title lives in the H1 heading and
|
|
63
|
+
the slug in the filename; duplicating either into frontmatter would give the
|
|
64
|
+
same fact two homes that can drift apart.
|
|
65
|
+
|
|
66
|
+
### Body — narrative sections
|
|
67
|
+
|
|
68
|
+
Write the body as prose, for a human reading it cold, months from now, with
|
|
69
|
+
none of this session's context. Use these named sections. Each one earns its
|
|
70
|
+
keep for a specific reason — fill it from what you actually know right now,
|
|
71
|
+
not from what you imagine you might discover later:
|
|
72
|
+
|
|
73
|
+
- **What the session hit and where** — the concrete trigger: file paths, the
|
|
74
|
+
task the session was actually doing, the symptom or realization that
|
|
75
|
+
surfaced this.
|
|
76
|
+
- **Why it is bigger than this session** — what makes this a future piece of
|
|
77
|
+
work rather than something to fold into the current task.
|
|
78
|
+
- **Constraints discovered** — the expensive knowledge: what a design here
|
|
79
|
+
must respect, what the existing code already forces, anything that would
|
|
80
|
+
otherwise have to be rediscovered the hard way.
|
|
81
|
+
- **Approaches considered or rejected, and why** — so whoever picks this up
|
|
82
|
+
does not re-walk a dead end you already ruled out.
|
|
83
|
+
- **Pointers** — branches, commits, related items (link them by slug or
|
|
84
|
+
path), anything else that helps someone orient.
|
|
85
|
+
|
|
86
|
+
This is prose in, prose out. Nothing grades or validates what you write here
|
|
87
|
+
— a thin capture with only one or two sections filled in is still worth far
|
|
88
|
+
more than no capture at all. Write what you actually know; do not pad
|
|
89
|
+
sections with speculation to look complete.
|
|
90
|
+
|
|
91
|
+
## Capture behavior
|
|
92
|
+
|
|
93
|
+
- **Write it now, in full, from this session's live context.** Do not leave
|
|
94
|
+
a one-line stub or a TODO to flesh out later — by the time anyone returns
|
|
95
|
+
to flesh it out, the context this skill exists to preserve is already
|
|
96
|
+
gone. This is the central instruction; everything else here supports it.
|
|
97
|
+
- **Check `docs/backlog/` first for an item that already covers this
|
|
98
|
+
ground.** If one exists, enrich it with what this session adds instead of
|
|
99
|
+
creating a near-duplicate file.
|
|
100
|
+
- **Create `docs/backlog/` if it does not exist yet.** Nothing scaffolds
|
|
101
|
+
this directory in advance; the first real capture creates it.
|
|
102
|
+
- **Never modify anything outside `docs/backlog/`.** This skill is strictly
|
|
103
|
+
additive and scoped to that one directory.
|
|
104
|
+
- **Never overwrite an unrelated file already in `docs/backlog/`.** If a
|
|
105
|
+
file there was not written by this skill and does not cover the same
|
|
106
|
+
discovery, leave it alone and create a new item instead.
|
|
107
|
+
- **Say nothing about how any particular tool or program consumes this
|
|
108
|
+
backlog later.** This skill only describes the item and how to write it;
|
|
109
|
+
it does not depend on, and must not reference, any specific downstream
|
|
110
|
+
tooling or process. It works the same way in any repository that has it
|
|
111
|
+
installed.
|
|
112
|
+
- **Capture `HEAD` before committing.** Before staging anything, record the
|
|
113
|
+
pre-commit baseline with `git rev-parse HEAD`. In a brand-new repository
|
|
114
|
+
with no commits yet, `HEAD` is unborn and this fails — that failure is
|
|
115
|
+
itself the baseline (it means "no commit exists yet"); treat it as a
|
|
116
|
+
sentinel rather than an error, and do not let it block the commit attempt
|
|
117
|
+
below. This captured value (or the unborn sentinel) is what the
|
|
118
|
+
post-commit confirmation below compares against — without it, "confirm
|
|
119
|
+
`HEAD` moved" has nothing to move *from*.
|
|
120
|
+
- **Commit the item the moment it is written, in a repository that uses
|
|
121
|
+
git.** Immediately after writing `docs/backlog/{slug}.md`, make one commit
|
|
122
|
+
that contains only that file — stage exactly it and commit only it, so
|
|
123
|
+
nothing else already sitting in the tree rides along. Use the kebab-case
|
|
124
|
+
`{slug}` in the commit message, not the human title: the slug is
|
|
125
|
+
constrained to `[a-z0-9-]`, so it is safe to interpolate into the command,
|
|
126
|
+
while a title can carry a quote, backtick, `$(...)`, or other shell
|
|
127
|
+
metacharacter that could truncate, alter, or execute the command on common
|
|
128
|
+
shells.
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
git add -- docs/backlog/{slug}.md
|
|
132
|
+
git commit -m "backlog: capture {slug}" -- docs/backlog/{slug}.md
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- **Confirm the commit actually landed before reporting anything about
|
|
136
|
+
it, by comparing against the `HEAD` you captured before committing.** A
|
|
137
|
+
commit can fail for reasons beyond "no git repository" — unset git
|
|
138
|
+
identity, a failing pre-commit hook, a signing failure, no write
|
|
139
|
+
permission, or nothing new to commit. After committing, run
|
|
140
|
+
`git rev-parse HEAD` again and confirm it differs from the pre-commit
|
|
141
|
+
value you captured above (or, if the pre-commit capture was the unborn
|
|
142
|
+
sentinel, confirm `HEAD` now resolves at all — either case is "a new
|
|
143
|
+
commit now exists that did not before"), and that this new commit's one
|
|
144
|
+
changed file is `docs/backlog/{slug}.md`, before reading any branch or SHA
|
|
145
|
+
from it. Checking only "the current commit's diff is exactly this file"
|
|
146
|
+
without that prior-`HEAD` comparison is not sufficient: a bare
|
|
147
|
+
`git rev-parse HEAD` run after a *failed* commit still resolves and names
|
|
148
|
+
an older, unrelated commit, and reporting that as the landing SHA hands
|
|
149
|
+
the human a false rescue command; the captured pre-commit value is what
|
|
150
|
+
lets you tell that older commit apart from a genuinely new one. If the
|
|
151
|
+
commit did not land, do the opposite of reporting: say plainly that the
|
|
152
|
+
item could not be committed and why (surface git's message), note that
|
|
153
|
+
the item file is written to disk regardless — the durable capture is the
|
|
154
|
+
point and stands whether or not the commit succeeded — and leave
|
|
155
|
+
committing to the human. **Do not name a branch, a SHA, or a
|
|
156
|
+
cherry-pick/rescue command on this path** — there is no confirmed commit
|
|
157
|
+
for any of those to describe, and offering one anyway (even one built
|
|
158
|
+
from the pre-commit `HEAD`) hands the human a rescue command for a commit
|
|
159
|
+
that does not exist.
|
|
160
|
+
- **Report which branch the confirmed commit landed on.** Read the current
|
|
161
|
+
branch with plain git (for example `git branch --show-current`) and tell
|
|
162
|
+
the human; do not switch branches to check.
|
|
163
|
+
- **Flag a branch unlikely to reach the trunk, and hand over the exact
|
|
164
|
+
rescue command.** If the confirmed landing branch looks like a scratch or
|
|
165
|
+
experiment branch — a throwaway unlikely ever to be merged into the
|
|
166
|
+
repository's default branch — say so plainly, so the human can decide
|
|
167
|
+
whether to re-home the item. When you raise that flag, include the exact
|
|
168
|
+
rescue command with the real, confirmed commit SHA — `git cherry-pick
|
|
169
|
+
<sha>` (read via `git rev-parse HEAD` only after confirming the commit
|
|
170
|
+
landed above), run from the default branch — so re-homing is one paste,
|
|
171
|
+
not a later investigation. The only-the-item-file staging boundary above
|
|
172
|
+
**isolates** that cherry-pick from unrelated files, because the commit
|
|
173
|
+
touches only the one new item file — it does **not** guarantee a clean
|
|
174
|
+
apply in every case (the default branch may already carry the same path
|
|
175
|
+
or a divergent version of it), so present cherry-pick as the convenience
|
|
176
|
+
and tell the human to fall back to merging the branch if it conflicts.
|
|
177
|
+
Never switch branches, cherry-pick, or move the item yourself; commit
|
|
178
|
+
where the session already stands, name the branch, flag the risk, hand
|
|
179
|
+
over the command, and leave relocation to the human.
|
|
180
|
+
- **When there is no git repository, the commit simply cannot happen.**
|
|
181
|
+
Write the item and say so; the durable file on disk is still the point,
|
|
182
|
+
whether or not this repository uses git.
|
|
@@ -26,12 +26,80 @@ Read:
|
|
|
26
26
|
present.
|
|
27
27
|
- When re-planning after a run, the program's run report and decision ledger
|
|
28
28
|
under `docs/programs/` — a prior run's parked workstreams, risk-accepted
|
|
29
|
-
findings,
|
|
29
|
+
findings, recorded decisions, and **unmet human prerequisites** are
|
|
30
|
+
planning input, not noise. A prior run's workstreams left `awaiting_human`,
|
|
31
|
+
and the `prerequisites` entries still `pending` that they reference, name
|
|
32
|
+
work a human has not yet done. Preserve every prerequisite record that any
|
|
33
|
+
incomplete workstream still references — verbatim, with its stored
|
|
34
|
+
`status` unchanged, including a `satisfied` record a live workstream still
|
|
35
|
+
points at; do not drop it merely because it is satisfied, or the workstream
|
|
36
|
+
would reference an id the manifest no longer defines. Only a record whose
|
|
37
|
+
stored status is already `satisfied` may be treated as settled
|
|
38
|
+
infrastructure, and only because a prior run's preflight flipped it — never
|
|
39
|
+
because the planner judged the human's work done. A record still marked
|
|
40
|
+
`pending` stays `pending` even when the human reports having done the
|
|
41
|
+
action: the planner never flips a prerequisite's status; only the
|
|
42
|
+
deterministic preflight satisfies one, on the next run. Plan from
|
|
30
43
|
the repository state that exists now, not from the original pre-program
|
|
31
44
|
design; treat work a prior run verified and committed as current
|
|
32
45
|
architecture rather than scheduling it again, and give replacement work new
|
|
33
46
|
workstream IDs and task-file paths so nothing overwrites the historical
|
|
34
47
|
record.
|
|
48
|
+
- `docs/backlog/`, when it exists. Treat its `captured` items as planning
|
|
49
|
+
input on equal footing with the vision and as-built, and surface the ones
|
|
50
|
+
relevant to the phase being planned before decomposing work in the next
|
|
51
|
+
step — a backlog item is prior context someone already paid for, not a
|
|
52
|
+
file to skim past. If `docs/backlog/` does not exist, proceed without
|
|
53
|
+
comment; an absent or empty backlog changes nothing about how this skill
|
|
54
|
+
runs.
|
|
55
|
+
|
|
56
|
+
Also look past the working tree: because captures commit where the
|
|
57
|
+
session stands, an item can sit on an unmerged branch and be entirely
|
|
58
|
+
invisible to this listing. In a git repository, enumerate ref tips,
|
|
59
|
+
read-only: list the candidate refs (`git for-each-ref --format='%(refname)'
|
|
60
|
+
refs/heads refs/remotes`), and for each one list the `docs/backlog/*.md`
|
|
61
|
+
paths present **at that ref's tip tree**
|
|
62
|
+
(`git ls-tree -r --name-only <ref> -- docs/backlog/`) — not a history
|
|
63
|
+
scan; a bare `git log --diff-filter=A -- docs/backlog/` or
|
|
64
|
+
`git branch --contains` proves only that a commit was once added or is an
|
|
65
|
+
ancestor somewhere, not that the file still exists at any ref's tip today,
|
|
66
|
+
and would misreport an item deleted from every branch as awaiting-merge.
|
|
67
|
+
Union the tip-tree paths across refs and subtract this working tree's own
|
|
68
|
+
`docs/backlog/` listing; what remains are candidates.
|
|
69
|
+
|
|
70
|
+
A candidate is not automatically "not yet merged": a branch can have been
|
|
71
|
+
fully merged and kept around while the item was later deleted here on
|
|
72
|
+
purpose, and tip-tree subtraction alone cannot tell the two apart. So for
|
|
73
|
+
each candidate, resolve the commit that most recently added it on its ref
|
|
74
|
+
(`git log -1 --diff-filter=A --format=%H <ref> -- <path>`) and check
|
|
75
|
+
whether that commit is already reachable from `HEAD`
|
|
76
|
+
(`git merge-base --is-ancestor <commit> HEAD`). A reachable add-commit
|
|
77
|
+
means this content already made it into the current branch's history at
|
|
78
|
+
some point and its absence now is a deliberate removal, not unmerged
|
|
79
|
+
work — drop that candidate rather than resurrecting it as planning input.
|
|
80
|
+
Only an unreachable add-commit is genuinely **awaiting-merge** input; name
|
|
81
|
+
it to the human as living on that branch, not yet merged. When no single
|
|
82
|
+
add-commit can be resolved at all (for example, the path arrived on that
|
|
83
|
+
ref by a rename), do not assert unmerged with confidence — still name the
|
|
84
|
+
item, but say its provenance could not be confirmed and ask the human to
|
|
85
|
+
check it is not already-handled content before treating it as new work.
|
|
86
|
+
|
|
87
|
+
Before naming the cherry-pick option, inspect the resolved add-commit's
|
|
88
|
+
complete changed-path set. Offer `git cherry-pick` of that commit only
|
|
89
|
+
when the set is exactly the one backlog item path — that is what makes
|
|
90
|
+
the only-the-item-file boundary actually isolate the cherry-pick from
|
|
91
|
+
unrelated files; a multi-file add-commit (a legacy, manually captured, or
|
|
92
|
+
renamed item) breaks that isolation despite looking like a single-item
|
|
93
|
+
capture. In every other case — a multi-file add-commit, an unresolved
|
|
94
|
+
add-commit, or an item later modified on its ref (which makes the
|
|
95
|
+
add-commit alone stale) — recommend merging the branch instead, the safer
|
|
96
|
+
default regardless. Either way, the item can only be **absorbed** — its
|
|
97
|
+
frontmatter flipped in §4.5 — once its file is actually present on the
|
|
98
|
+
planning branch, so this step only surfaces the candidate and explains how
|
|
99
|
+
to bring it over; it never merges, cherry-picks, or edits an off-tree item
|
|
100
|
+
itself. Outside a git repository, or when no other ref carries an item
|
|
101
|
+
this working tree lacks, say nothing — the same proceed-without-comment
|
|
102
|
+
tolerance as an absent backlog.
|
|
35
103
|
|
|
36
104
|
If no vision document exists at the resolved path, stop. Explain that it
|
|
37
105
|
should contain the product description, architecture, target users, API
|
|
@@ -88,6 +156,88 @@ npx --yes @wildorder/nightshift branch "{program-id}"
|
|
|
88
156
|
This skill composes no git of its own — the command above owns branch
|
|
89
157
|
selection, and the packaged runner owns every commit that follows.
|
|
90
158
|
|
|
159
|
+
## 2.7. Run the actor audit
|
|
160
|
+
|
|
161
|
+
Before drafting either artifact, walk the phase's work and ask one question of
|
|
162
|
+
each unit: *what credential or access does this step consume, and does the
|
|
163
|
+
crew hold it?* This audit **discovers** human-only steps; it never blocks the
|
|
164
|
+
plan. A phase with no human-only actions produces an empty audit, and the
|
|
165
|
+
skill proceeds exactly as it does today — no `prerequisites` entries, no Human
|
|
166
|
+
Prerequisites section, no friction. There is no rule that a plan must declare
|
|
167
|
+
a prerequisite; there is only a question worth asking before the work is
|
|
168
|
+
scheduled.
|
|
169
|
+
|
|
170
|
+
The roster does not exist yet at this point — §3 and §4 haven't drafted it —
|
|
171
|
+
so audit a **provisional decomposition**: the candidate units of work the
|
|
172
|
+
phase breaks into, the same decomposition §3 and §4 will formalize into
|
|
173
|
+
workstreams. If drafting the final roster later **adds, removes, splits, or
|
|
174
|
+
moves a workstream**, re-check the hoist-and-batch assignment below against
|
|
175
|
+
the new roster, so every eventual unit of work has been audited and every
|
|
176
|
+
prerequisite lands on the workstream that actually consumes it.
|
|
177
|
+
|
|
178
|
+
**The enumerable tells** — the concrete signals a unit of work needs a human:
|
|
179
|
+
|
|
180
|
+
- cloud or organisation **admin credentials** the crew is not given;
|
|
181
|
+
- **console-only actions** with no API the agent can call;
|
|
182
|
+
- **trust anchors** — OIDC providers, state backends, signing keys — that a
|
|
183
|
+
human must establish before anything can authenticate against them;
|
|
184
|
+
- **secrets the agent may not set** (a repository or environment secret the
|
|
185
|
+
crew must never hold);
|
|
186
|
+
- **third-party account creation**;
|
|
187
|
+
- **DNS** records and delegations.
|
|
188
|
+
|
|
189
|
+
**A prerequisite is an action the crew *cannot* perform — never one that is
|
|
190
|
+
merely hard, slow, or annoying.** The audit's test is "does the crew hold
|
|
191
|
+
this?", never "is this unpleasant?" Work an agent can do, even tediously, is
|
|
192
|
+
not a prerequisite; declaring it as one manufactures an intermission and hands
|
|
193
|
+
the human work the run could have done itself.
|
|
194
|
+
|
|
195
|
+
**Convert each hit into a prerequisite** with:
|
|
196
|
+
|
|
197
|
+
- a stable **id**, conventionally `HP-01`, `HP-02`, …;
|
|
198
|
+
- a human-facing **description** of the action only a human can perform;
|
|
199
|
+
- a **remediation** written as the exact commands or console steps the human
|
|
200
|
+
runs — a runbook, not a hint (for example, a repository-settings change like
|
|
201
|
+
configuring branch protection in the hosting provider's settings, described
|
|
202
|
+
as console steps, not as a version-control command);
|
|
203
|
+
- a **verifyCommand**: a shell command that exits zero iff the action is done,
|
|
204
|
+
which the runner executes itself as a deterministic subprocess — never a
|
|
205
|
+
model's judgment. The observable must be one the headless runner can
|
|
206
|
+
actually query: non-interactive, reading no stdin, emitting no prompt, and
|
|
207
|
+
using only credentials the *runner* holds. This is the trap turned back on
|
|
208
|
+
itself — the prerequisite exists because the crew lacks a credential, and
|
|
209
|
+
the obvious way to verify the action often needs that same missing
|
|
210
|
+
privilege. Distinguish permission to **perform** the action (which the crew
|
|
211
|
+
lacks — that is why it is a prerequisite) from permission to **observe**
|
|
212
|
+
its completion (which the runner must have). If the only observable needs
|
|
213
|
+
the human-only privilege, pick a different observable the runner can reach
|
|
214
|
+
— a downstream effect, a read-only or verification-scoped credential
|
|
215
|
+
provisioned for the purpose — rather than shipping a command the runner
|
|
216
|
+
cannot execute. The `verifyCommand` is executed verbatim by the runner, the
|
|
217
|
+
same trust class as the verify commands in `nightshift.config.json` — it is
|
|
218
|
+
reviewed at planning time precisely because it will be run.
|
|
219
|
+
|
|
220
|
+
**Hoist and batch.** Human actions are expensive handoffs. Hoist each human
|
|
221
|
+
action to a workstream boundary rather than burying it mid-workstream, batch
|
|
222
|
+
independent human actions into the fewest handoffs (ideally one), and
|
|
223
|
+
sequence agent-doable work ahead of the first unmet prerequisite so a run
|
|
224
|
+
gets as far as it can before it must wait. A workstream that consumes a
|
|
225
|
+
prerequisite lists it in that workstream's `prerequisites`.
|
|
226
|
+
|
|
227
|
+
An empty audit is the normal outcome for a program that touches no
|
|
228
|
+
infrastructure — write no `prerequisites`, add no Human Prerequisites
|
|
229
|
+
section, and move on. But an infrastructure-touching program that emerges
|
|
230
|
+
from the audit with an empty prerequisites list is worth re-checking during
|
|
231
|
+
review: it usually means a human seam was missed, not that none exists. This
|
|
232
|
+
is guidance for a second look, not a rule the plan must pass.
|
|
233
|
+
|
|
234
|
+
**What this step does not do.** The audit produces manifest entries and
|
|
235
|
+
program-document prose. It never runs a `verifyCommand`, never verifies
|
|
236
|
+
whether a human has acted, and never changes a workstream's or a
|
|
237
|
+
prerequisite's `status` — that is the runner's job, at run time. It never
|
|
238
|
+
makes prerequisite declaration mandatory, never blocks a plan, and never adds
|
|
239
|
+
a step the plan must pass. An empty result is a complete, valid plan.
|
|
240
|
+
|
|
91
241
|
## 3. Draft the program document
|
|
92
242
|
|
|
93
243
|
Inspect `docs/programs/` for an existing `*-program.md`. Match its structure
|
|
@@ -110,6 +260,13 @@ when one exists. Otherwise use:
|
|
|
110
260
|
## Architecture Changes
|
|
111
261
|
[Changes from the system in as-built.md. For the first program, describe the full architecture.]
|
|
112
262
|
|
|
263
|
+
## Human Prerequisites
|
|
264
|
+
[Only when the actor audit found human-only actions. One short paragraph or a
|
|
265
|
+
few bullets naming each prerequisite by id (HP-xx) and what it unblocks — which
|
|
266
|
+
workstreams wait on it and why the crew cannot perform it. Reference ids only;
|
|
267
|
+
the remediation, verifyCommand, and status live in the manifest, never here.
|
|
268
|
+
Omit this section entirely when the audit found no prerequisites.]
|
|
269
|
+
|
|
113
270
|
## Technology Choices
|
|
114
271
|
[Only new choices. If none: "No new technology — uses existing stack."]
|
|
115
272
|
|
|
@@ -133,10 +290,13 @@ and never restates their text.
|
|
|
133
290
|
The program document carries only what the manifest cannot: narrative
|
|
134
291
|
architecture, causal reasoning, anticipated decisions, and risks. Success
|
|
135
292
|
criteria, the workstream table, the dependency graph, and scope in/out lists
|
|
136
|
-
are manifest data — do not reproduce them here.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
293
|
+
are manifest data — do not reproduce them here. Human Prerequisites follows
|
|
294
|
+
the same rule: reference HP ids only, never their description, remediation,
|
|
295
|
+
verifyCommand, or status, all of which are manifest data. Two copies of the
|
|
296
|
+
same fact drift apart; one canonical home per fact is a founding rule of this
|
|
297
|
+
system. When this section's rule and an older program document's structure
|
|
298
|
+
conflict, this rule wins: delete the duplicated sections rather than matching
|
|
299
|
+
them.
|
|
140
300
|
|
|
141
301
|
Write the draft directly to `docs/programs/{program-id}-program.md`. Do not
|
|
142
302
|
paste the document into the conversation or ask for approval before saving —
|
|
@@ -162,6 +322,15 @@ exactly. Otherwise use:
|
|
|
162
322
|
"successCriteria": [
|
|
163
323
|
{ "id": "SC-01", "description": "{verifiable outcome}" }
|
|
164
324
|
],
|
|
325
|
+
"prerequisites": [
|
|
326
|
+
{
|
|
327
|
+
"id": "HP-01",
|
|
328
|
+
"description": "{the action only a human can perform}",
|
|
329
|
+
"remediation": "{the exact commands or console steps the human runs}",
|
|
330
|
+
"verifyCommand": "{a shell command that exits zero iff the action is done}",
|
|
331
|
+
"status": "pending"
|
|
332
|
+
}
|
|
333
|
+
],
|
|
165
334
|
"packages": [
|
|
166
335
|
{
|
|
167
336
|
"name": "{package-name}",
|
|
@@ -182,6 +351,7 @@ exactly. Otherwise use:
|
|
|
182
351
|
"excludes": ["{specific thing it deliberately does not cover}"]
|
|
183
352
|
},
|
|
184
353
|
"dependencies": [],
|
|
354
|
+
"prerequisites": [],
|
|
185
355
|
"packages": []
|
|
186
356
|
}
|
|
187
357
|
],
|
|
@@ -189,6 +359,11 @@ exactly. Otherwise use:
|
|
|
189
359
|
}
|
|
190
360
|
```
|
|
191
361
|
|
|
362
|
+
The root `prerequisites` array and each workstream's `prerequisites` id list
|
|
363
|
+
come from the actor audit (§2.7). Omit the root array, or leave it empty, when
|
|
364
|
+
the audit found nothing — the schema defaults it to `[]`, so a
|
|
365
|
+
prerequisite-free manifest is byte-for-byte what the skill emits today.
|
|
366
|
+
|
|
192
367
|
Save it directly to `docs/programs/{program-id}-manifest.json`.
|
|
193
368
|
Keep the manifest, program document, and every referenced `taskFile`
|
|
194
369
|
trackable by Git — nightshift tags decisions to commits and replays roll back
|
|
@@ -248,6 +423,47 @@ For a shared contract migration, prefer an explicit sequence:
|
|
|
248
423
|
The destructive cleanup depends on every migration workstream. Do not place
|
|
249
424
|
foundational deletion first merely because it is conceptually central.
|
|
250
425
|
|
|
426
|
+
## 4.5. Absorb backlog items
|
|
427
|
+
|
|
428
|
+
When any part of this program's scope came from an item captured under
|
|
429
|
+
`docs/backlog/`, close the loop before handing off:
|
|
430
|
+
|
|
431
|
+
- Flip that item's `status` to `planned` and write this program's id into
|
|
432
|
+
its `planned-into` field. Edit only those two fields — do not restate or
|
|
433
|
+
reshape the rest of the item.
|
|
434
|
+
- Carry that item's captured constraints into both the program document
|
|
435
|
+
narrative and the manifest's `planningInput`, instead of re-deriving
|
|
436
|
+
them — the reason to read the backlog in step 1 is so this plan starts
|
|
437
|
+
from knowledge a prior session already paid for, not to re-research it.
|
|
438
|
+
- Leave every item this program does not draw on untouched at `captured`.
|
|
439
|
+
|
|
440
|
+
This is the planner exercising judgment interactively, in the moment a
|
|
441
|
+
program is being shaped — not an automated transition. Statuses beyond
|
|
442
|
+
`planned` (`done`, `declined`) are closed out separately, by a human editing
|
|
443
|
+
the item file directly; no skill advances them.
|
|
444
|
+
|
|
445
|
+
## 4.6. Commit the plan
|
|
446
|
+
|
|
447
|
+
The plan is committed now, on this program's branch, so it never sits
|
|
448
|
+
untracked where a different program's run could sweep it up. Run exactly
|
|
449
|
+
this command and nothing else:
|
|
450
|
+
|
|
451
|
+
```sh
|
|
452
|
+
npx --yes @wildorder/nightshift commit-plan "{program-id}"
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
This skill composes no git of its own — the command above owns staging and
|
|
456
|
+
committing the plan (the program document, the manifest, and any backlog
|
|
457
|
+
items absorbed in the previous step), and the packaged runner owns every
|
|
458
|
+
commit that follows. If the command exits nonzero — no git repository, or
|
|
459
|
+
HEAD is not this program's branch — surface its message to the human as a
|
|
460
|
+
warning and proceed to the handoff below anyway; do not treat it as a hard
|
|
461
|
+
stop. The artifacts already exist on disk regardless, and every refusal the
|
|
462
|
+
command can raise is a "could not commit here" a human can resolve (init a
|
|
463
|
+
repository, or run the branch step). A clean no-op — the plan is already
|
|
464
|
+
committed and unchanged — ends this step the same way a fresh commit does:
|
|
465
|
+
move on.
|
|
466
|
+
|
|
251
467
|
## 5. Hand off for review
|
|
252
468
|
|
|
253
469
|
Both files now exist on disk. Reply with a short summary only — program
|