@nonameolsson/nightjar 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +405 -2
- package/dist/account.d.ts +12 -0
- package/dist/account.js +57 -0
- package/dist/account.js.map +1 -0
- package/dist/adapter-module.d.ts +18 -0
- package/dist/adapter-module.js +83 -0
- package/dist/adapter-module.js.map +1 -0
- package/dist/adapters.d.ts +15 -0
- package/dist/adapters.js +160 -0
- package/dist/adapters.js.map +1 -0
- package/dist/args.d.ts +13 -0
- package/dist/args.js +84 -0
- package/dist/args.js.map +1 -0
- package/dist/ask.d.ts +6 -0
- package/dist/ask.js +27 -0
- package/dist/ask.js.map +1 -0
- package/dist/azure-devops/api.d.ts +34 -0
- package/dist/azure-devops/api.js +98 -0
- package/dist/azure-devops/api.js.map +1 -0
- package/dist/azure-devops/code-host.d.ts +36 -0
- package/dist/azure-devops/code-host.js +185 -0
- package/dist/azure-devops/code-host.js.map +1 -0
- package/dist/azure-devops/fake-azure-devops.d.ts +90 -0
- package/dist/azure-devops/fake-azure-devops.js +728 -0
- package/dist/azure-devops/fake-azure-devops.js.map +1 -0
- package/dist/azure-devops/index.d.ts +8 -0
- package/dist/azure-devops/index.js +11 -0
- package/dist/azure-devops/index.js.map +1 -0
- package/dist/azure-devops/sign-in.d.ts +11 -0
- package/dist/azure-devops/sign-in.js +68 -0
- package/dist/azure-devops/sign-in.js.map +1 -0
- package/dist/azure-devops/text.d.ts +1 -0
- package/dist/azure-devops/text.js +41 -0
- package/dist/azure-devops/text.js.map +1 -0
- package/dist/azure-devops/tracker.d.ts +44 -0
- package/dist/azure-devops/tracker.js +333 -0
- package/dist/azure-devops/tracker.js.map +1 -0
- package/dist/build.d.ts +75 -0
- package/dist/build.js +698 -0
- package/dist/build.js.map +1 -0
- package/dist/check.d.ts +8 -0
- package/dist/check.js +25 -0
- package/dist/check.js.map +1 -0
- package/dist/checks.d.ts +45 -0
- package/dist/checks.js +243 -0
- package/dist/checks.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +11 -0
- package/dist/cli.js.map +1 -0
- package/dist/code-host.d.ts +19 -0
- package/dist/code-host.js +2 -0
- package/dist/code-host.js.map +1 -0
- package/dist/config.d.ts +86 -0
- package/dist/config.js +294 -0
- package/dist/config.js.map +1 -0
- package/dist/contract/case.d.ts +4 -0
- package/dist/contract/case.js +2 -0
- package/dist/contract/case.js.map +1 -0
- package/dist/contract/code-host.d.ts +24 -0
- package/dist/contract/code-host.js +108 -0
- package/dist/contract/code-host.js.map +1 -0
- package/dist/contract/command.d.ts +2 -0
- package/dist/contract/command.js +36 -0
- package/dist/contract/command.js.map +1 -0
- package/dist/contract/feature-writer.d.ts +3 -0
- package/dist/contract/feature-writer.js +101 -0
- package/dist/contract/feature-writer.js.map +1 -0
- package/dist/contract/run.d.ts +18 -0
- package/dist/contract/run.js +89 -0
- package/dist/contract/run.js.map +1 -0
- package/dist/contract/tracker.d.ts +30 -0
- package/dist/contract/tracker.js +250 -0
- package/dist/contract/tracker.js.map +1 -0
- package/dist/create.d.ts +9 -0
- package/dist/create.js +112 -0
- package/dist/create.js.map +1 -0
- package/dist/doctor.d.ts +4 -0
- package/dist/doctor.js +42 -0
- package/dist/doctor.js.map +1 -0
- package/dist/fakes/code-host.d.ts +21 -0
- package/dist/fakes/code-host.js +42 -0
- package/dist/fakes/code-host.js.map +1 -0
- package/dist/fakes/harness.d.ts +7 -0
- package/dist/fakes/harness.js +68 -0
- package/dist/fakes/harness.js.map +1 -0
- package/dist/fakes/machine.d.ts +11 -0
- package/dist/fakes/machine.js +101 -0
- package/dist/fakes/machine.js.map +1 -0
- package/dist/fakes/tracker.d.ts +40 -0
- package/dist/fakes/tracker.js +116 -0
- package/dist/fakes/tracker.js.map +1 -0
- package/dist/feature-file.d.ts +12 -0
- package/dist/feature-file.js +84 -0
- package/dist/feature-file.js.map +1 -0
- package/dist/git.d.ts +9 -0
- package/dist/git.js +12 -0
- package/dist/git.js.map +1 -0
- package/dist/github/api.d.ts +37 -0
- package/dist/github/api.js +66 -0
- package/dist/github/api.js.map +1 -0
- package/dist/github/code-host.d.ts +19 -0
- package/dist/github/code-host.js +105 -0
- package/dist/github/code-host.js.map +1 -0
- package/dist/github/fake-gh.d.ts +17 -0
- package/dist/github/fake-gh.js +51 -0
- package/dist/github/fake-gh.js.map +1 -0
- package/dist/github/fake-github.d.ts +58 -0
- package/dist/github/fake-github.js +285 -0
- package/dist/github/fake-github.js.map +1 -0
- package/dist/github/labels.d.ts +3 -0
- package/dist/github/labels.js +44 -0
- package/dist/github/labels.js.map +1 -0
- package/dist/github/tracker.d.ts +28 -0
- package/dist/github/tracker.js +208 -0
- package/dist/github/tracker.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +19 -0
- package/dist/init.js +225 -0
- package/dist/init.js.map +1 -0
- package/dist/ledger.d.ts +13 -0
- package/dist/ledger.js +49 -0
- package/dist/ledger.js.map +1 -0
- package/dist/main.d.ts +11 -0
- package/dist/main.js +215 -0
- package/dist/main.js.map +1 -0
- package/dist/person-config.d.ts +9 -0
- package/dist/person-config.js +46 -0
- package/dist/person-config.js.map +1 -0
- package/dist/plan.d.ts +9 -0
- package/dist/plan.js +27 -0
- package/dist/plan.js.map +1 -0
- package/dist/ports.d.ts +16 -0
- package/dist/ports.js +104 -0
- package/dist/ports.js.map +1 -0
- package/dist/prompt.d.ts +166 -0
- package/dist/prompt.js +217 -0
- package/dist/prompt.js.map +1 -0
- package/dist/queue.d.ts +20 -0
- package/dist/queue.js +94 -0
- package/dist/queue.js.map +1 -0
- package/dist/say.d.ts +2 -0
- package/dist/say.js +4 -0
- package/dist/say.js.map +1 -0
- package/dist/serve.d.ts +10 -0
- package/dist/serve.js +85 -0
- package/dist/serve.js.map +1 -0
- package/dist/session.d.ts +39 -0
- package/dist/session.js +144 -0
- package/dist/session.js.map +1 -0
- package/dist/settings.d.ts +10 -0
- package/dist/settings.js +92 -0
- package/dist/settings.js.map +1 -0
- package/dist/signals.d.ts +5 -0
- package/dist/signals.js +13 -0
- package/dist/signals.js.map +1 -0
- package/dist/skills.d.ts +4 -0
- package/dist/skills.js +51 -0
- package/dist/skills.js.map +1 -0
- package/dist/status-shape.d.ts +53 -0
- package/dist/status-shape.js +3 -0
- package/dist/status-shape.js.map +1 -0
- package/dist/status.d.ts +23 -0
- package/dist/status.js +56 -0
- package/dist/status.js.map +1 -0
- package/dist/tracker.d.ts +56 -0
- package/dist/tracker.js +12 -0
- package/dist/tracker.js.map +1 -0
- package/dist/workflow.d.ts +33 -0
- package/dist/workflow.js +53 -0
- package/dist/workflow.js.map +1 -0
- package/dist/worktree.d.ts +44 -0
- package/dist/worktree.js +193 -0
- package/dist/worktree.js.map +1 -0
- package/docs/ticket-contract.md +95 -0
- package/package.json +74 -5
- package/plugin/nightjar-status/.claude-plugin/plugin.json +5 -0
- package/plugin/nightjar-status/hooks/format.ts +48 -0
- package/plugin/nightjar-status/hooks/hooks.json +1 -0
- package/plugin/nightjar-status/hooks/register.ts +51 -0
- package/schema/factory.schema.json +437 -0
- package/skills/nightjar-feature/SKILL.md +73 -0
- package/src/status-shape.ts +44 -0
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"$schema": {
|
|
6
|
+
"type": "string"
|
|
7
|
+
},
|
|
8
|
+
"tracker": {
|
|
9
|
+
"oneOf": [
|
|
10
|
+
{
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"type": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"const": "github"
|
|
16
|
+
},
|
|
17
|
+
"repo": {
|
|
18
|
+
"description": "owner/name on GitHub; when left out, read from the origin remote",
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^[^/\\s]+\\/[^/\\s]+$"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"required": [
|
|
24
|
+
"type"
|
|
25
|
+
],
|
|
26
|
+
"additionalProperties": false,
|
|
27
|
+
"description": "GitHub Issues: a Feature is an issue with sub-issues, its Tickets"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"type": "object",
|
|
31
|
+
"properties": {
|
|
32
|
+
"type": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"const": "azure-devops"
|
|
35
|
+
},
|
|
36
|
+
"organization": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"allOf": [
|
|
39
|
+
{
|
|
40
|
+
"pattern": "\\S"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"pattern": "^[^/\\s:]+$"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"description": "The organization, as in dev.azure.com/<organization>"
|
|
47
|
+
},
|
|
48
|
+
"project": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"pattern": "\\S",
|
|
51
|
+
"description": "The project that holds the Features"
|
|
52
|
+
},
|
|
53
|
+
"featureType": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"pattern": "\\S",
|
|
56
|
+
"description": "The work item type that plays the Feature, such as Feature, Epic or Product Backlog Item"
|
|
57
|
+
},
|
|
58
|
+
"ticketType": {
|
|
59
|
+
"description": "The work item type nightjar create makes each Ticket as, such as User Story, Product Backlog Item or Issue. Left out, nightjar create makes no Tickets.",
|
|
60
|
+
"type": "string",
|
|
61
|
+
"pattern": "\\S"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"required": [
|
|
65
|
+
"type",
|
|
66
|
+
"organization",
|
|
67
|
+
"project",
|
|
68
|
+
"featureType"
|
|
69
|
+
],
|
|
70
|
+
"additionalProperties": false,
|
|
71
|
+
"description": "Azure DevOps Boards: a Feature is a work item of featureType, its child work items its Tickets"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"type": "object",
|
|
75
|
+
"properties": {
|
|
76
|
+
"type": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"const": "module"
|
|
79
|
+
},
|
|
80
|
+
"path": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"pattern": "\\S",
|
|
83
|
+
"description": "The module that builds the Tracker, as a path from the repo's root"
|
|
84
|
+
},
|
|
85
|
+
"options": {
|
|
86
|
+
"description": "Handed to the module as it is, for its own settings",
|
|
87
|
+
"type": "object",
|
|
88
|
+
"propertyNames": {
|
|
89
|
+
"type": "string"
|
|
90
|
+
},
|
|
91
|
+
"additionalProperties": {}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"required": [
|
|
95
|
+
"type",
|
|
96
|
+
"path"
|
|
97
|
+
],
|
|
98
|
+
"additionalProperties": false,
|
|
99
|
+
"description": "A Tracker of the repo's own, built by a module"
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
"description": "Where the Features and Tickets live"
|
|
103
|
+
},
|
|
104
|
+
"codeHost": {
|
|
105
|
+
"oneOf": [
|
|
106
|
+
{
|
|
107
|
+
"type": "object",
|
|
108
|
+
"properties": {
|
|
109
|
+
"type": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"const": "github"
|
|
112
|
+
},
|
|
113
|
+
"repo": {
|
|
114
|
+
"description": "owner/name on GitHub; when left out, read from the origin remote",
|
|
115
|
+
"type": "string",
|
|
116
|
+
"pattern": "^[^/\\s]+\\/[^/\\s]+$"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"required": [
|
|
120
|
+
"type"
|
|
121
|
+
],
|
|
122
|
+
"additionalProperties": false,
|
|
123
|
+
"description": "GitHub: the branch is pushed to origin and a draft pull request opened"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"type": "object",
|
|
127
|
+
"properties": {
|
|
128
|
+
"type": {
|
|
129
|
+
"type": "string",
|
|
130
|
+
"const": "azure-devops"
|
|
131
|
+
},
|
|
132
|
+
"organization": {
|
|
133
|
+
"type": "string",
|
|
134
|
+
"allOf": [
|
|
135
|
+
{
|
|
136
|
+
"pattern": "\\S"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"pattern": "^[^/\\s:]+$"
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
"description": "The organization, as in dev.azure.com/<organization>"
|
|
143
|
+
},
|
|
144
|
+
"project": {
|
|
145
|
+
"type": "string",
|
|
146
|
+
"pattern": "\\S",
|
|
147
|
+
"description": "The project that holds the repo"
|
|
148
|
+
},
|
|
149
|
+
"repo": {
|
|
150
|
+
"type": "string",
|
|
151
|
+
"pattern": "\\S",
|
|
152
|
+
"description": "The Git repo on Azure Repos, by name"
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"required": [
|
|
156
|
+
"type",
|
|
157
|
+
"organization",
|
|
158
|
+
"project",
|
|
159
|
+
"repo"
|
|
160
|
+
],
|
|
161
|
+
"additionalProperties": false,
|
|
162
|
+
"description": "Azure Repos: the branch is pushed to the repo and a draft pull request opened, signed in as for Azure DevOps Boards"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"type": "object",
|
|
166
|
+
"properties": {
|
|
167
|
+
"type": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"const": "module"
|
|
170
|
+
},
|
|
171
|
+
"path": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"pattern": "\\S",
|
|
174
|
+
"description": "The module that builds the Code host, as a path from the repo's root"
|
|
175
|
+
},
|
|
176
|
+
"options": {
|
|
177
|
+
"description": "Handed to the module as it is, for its own settings",
|
|
178
|
+
"type": "object",
|
|
179
|
+
"propertyNames": {
|
|
180
|
+
"type": "string"
|
|
181
|
+
},
|
|
182
|
+
"additionalProperties": {}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"required": [
|
|
186
|
+
"type",
|
|
187
|
+
"path"
|
|
188
|
+
],
|
|
189
|
+
"additionalProperties": false,
|
|
190
|
+
"description": "A Code host of the repo's own, built by a module"
|
|
191
|
+
}
|
|
192
|
+
],
|
|
193
|
+
"description": "Where the branch is pushed and the draft pull request opened"
|
|
194
|
+
},
|
|
195
|
+
"check": {
|
|
196
|
+
"type": "string",
|
|
197
|
+
"pattern": "\\S",
|
|
198
|
+
"description": "The shell command that checks the work in the worktree, run after each Ticket; it fails with a non-zero exit"
|
|
199
|
+
},
|
|
200
|
+
"allowedCommands": {
|
|
201
|
+
"type": "array",
|
|
202
|
+
"items": {
|
|
203
|
+
"type": "string",
|
|
204
|
+
"pattern": "\\S"
|
|
205
|
+
},
|
|
206
|
+
"description": "The commands the agent may run, as Claude Code Bash permission patterns without Bash( ), such as \"make test\" or \"make lint *\". Committing, pushing, switching branches, the network and gh stay denied."
|
|
207
|
+
},
|
|
208
|
+
"rules": {
|
|
209
|
+
"description": "A text file, relative to the repo root, whose text is added to the agent prompt. Conventions normally live in CLAUDE.md or AGENTS.md.",
|
|
210
|
+
"type": "string",
|
|
211
|
+
"pattern": "\\S"
|
|
212
|
+
},
|
|
213
|
+
"model": {
|
|
214
|
+
"description": "The default model of every session; a Ticket's **Model:** line overrides it and --model overrides both",
|
|
215
|
+
"type": "string",
|
|
216
|
+
"pattern": "\\S"
|
|
217
|
+
},
|
|
218
|
+
"effort": {
|
|
219
|
+
"description": "The default effort of every session; a Ticket's **Effort:** line overrides it and --effort overrides both",
|
|
220
|
+
"type": "string",
|
|
221
|
+
"pattern": "\\S"
|
|
222
|
+
},
|
|
223
|
+
"review": {
|
|
224
|
+
"description": "The read-only review of the whole diff, run before the draft pull request opens",
|
|
225
|
+
"type": "object",
|
|
226
|
+
"properties": {
|
|
227
|
+
"enabled": {
|
|
228
|
+
"description": "false switches the review off; on by default",
|
|
229
|
+
"type": "boolean"
|
|
230
|
+
},
|
|
231
|
+
"model": {
|
|
232
|
+
"description": "The review session's own model; else the default model",
|
|
233
|
+
"type": "string",
|
|
234
|
+
"pattern": "\\S"
|
|
235
|
+
},
|
|
236
|
+
"effort": {
|
|
237
|
+
"description": "The review session's own effort; else the default effort",
|
|
238
|
+
"type": "string",
|
|
239
|
+
"pattern": "\\S"
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"additionalProperties": false
|
|
243
|
+
},
|
|
244
|
+
"signals": {
|
|
245
|
+
"description": "The name each Signal has on a Tracker: a label on GitHub, a tag on Azure DevOps. Leave out the ones you do not rename. needs-triage and wontfix are refused.",
|
|
246
|
+
"default": {},
|
|
247
|
+
"type": "object",
|
|
248
|
+
"properties": {
|
|
249
|
+
"go": {
|
|
250
|
+
"default": "factory-go",
|
|
251
|
+
"description": "The Go: put on a Feature assigned to you to have it built. Give it the name of ready to use one mark for both",
|
|
252
|
+
"type": "string",
|
|
253
|
+
"pattern": "\\S"
|
|
254
|
+
},
|
|
255
|
+
"ready": {
|
|
256
|
+
"default": "ready-for-agent",
|
|
257
|
+
"description": "A Ticket that is ready to be built",
|
|
258
|
+
"type": "string",
|
|
259
|
+
"pattern": "\\S"
|
|
260
|
+
},
|
|
261
|
+
"working": {
|
|
262
|
+
"default": "agent-working",
|
|
263
|
+
"description": "Nightjar is working on it",
|
|
264
|
+
"type": "string",
|
|
265
|
+
"pattern": "\\S"
|
|
266
|
+
},
|
|
267
|
+
"needsInfo": {
|
|
268
|
+
"default": "needs-info",
|
|
269
|
+
"description": "Nightjar needs an answer to go on",
|
|
270
|
+
"type": "string",
|
|
271
|
+
"pattern": "\\S"
|
|
272
|
+
},
|
|
273
|
+
"human": {
|
|
274
|
+
"default": "ready-for-human",
|
|
275
|
+
"description": "A person has to take it from here",
|
|
276
|
+
"type": "string",
|
|
277
|
+
"pattern": "\\S"
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"additionalProperties": false
|
|
281
|
+
},
|
|
282
|
+
"workflows": {
|
|
283
|
+
"description": "Work a repo adds to the build loop, by name. A Feature picks one with a **Workflow:** line; Nightjar still keeps the branch, the commits, the Signals and the pull request.",
|
|
284
|
+
"type": "object",
|
|
285
|
+
"propertyNames": {
|
|
286
|
+
"type": "string",
|
|
287
|
+
"pattern": "^[^\\r\\n]*\\S[^\\r\\n]*$"
|
|
288
|
+
},
|
|
289
|
+
"additionalProperties": {
|
|
290
|
+
"type": "object",
|
|
291
|
+
"properties": {
|
|
292
|
+
"steps": {
|
|
293
|
+
"minItems": 1,
|
|
294
|
+
"type": "array",
|
|
295
|
+
"items": {
|
|
296
|
+
"type": "object",
|
|
297
|
+
"properties": {
|
|
298
|
+
"name": {
|
|
299
|
+
"type": "string",
|
|
300
|
+
"pattern": "^[^\\r\\n]*\\S[^\\r\\n]*$",
|
|
301
|
+
"description": "The name of the Step; its commit and the pull request body name it"
|
|
302
|
+
},
|
|
303
|
+
"prompt": {
|
|
304
|
+
"type": "string",
|
|
305
|
+
"pattern": "\\S",
|
|
306
|
+
"description": "What the agent is told to do, such as \"/some-skill critique\"; it may name any skill. Nightjar adds the rule that nobody is at the keyboard."
|
|
307
|
+
},
|
|
308
|
+
"point": {
|
|
309
|
+
"type": "string",
|
|
310
|
+
"enum": [
|
|
311
|
+
"afterEachTicket",
|
|
312
|
+
"afterAllTickets"
|
|
313
|
+
],
|
|
314
|
+
"description": "afterEachTicket runs after each Ticket is built; afterAllTickets runs once, after every Ticket, before the review"
|
|
315
|
+
},
|
|
316
|
+
"model": {
|
|
317
|
+
"description": "The Step's own model; else the default model",
|
|
318
|
+
"type": "string",
|
|
319
|
+
"pattern": "\\S"
|
|
320
|
+
},
|
|
321
|
+
"effort": {
|
|
322
|
+
"description": "The Step's own effort; else the default effort",
|
|
323
|
+
"type": "string",
|
|
324
|
+
"pattern": "\\S"
|
|
325
|
+
},
|
|
326
|
+
"budgetUsd": {
|
|
327
|
+
"description": "The most one run of the Step may cost in dollars; else a Ticket's budget",
|
|
328
|
+
"type": "number",
|
|
329
|
+
"exclusiveMinimum": 0
|
|
330
|
+
},
|
|
331
|
+
"until": {
|
|
332
|
+
"description": "A condition in plain words. After each round the agent reports whether it holds, and Nightjar runs the Step again until it does or maxRounds is reached",
|
|
333
|
+
"type": "string",
|
|
334
|
+
"pattern": "\\S"
|
|
335
|
+
},
|
|
336
|
+
"maxRounds": {
|
|
337
|
+
"description": "The most rounds of a Step with an until; 3 when left out",
|
|
338
|
+
"type": "integer",
|
|
339
|
+
"minimum": 1,
|
|
340
|
+
"maximum": 10
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"required": [
|
|
344
|
+
"name",
|
|
345
|
+
"prompt",
|
|
346
|
+
"point"
|
|
347
|
+
],
|
|
348
|
+
"additionalProperties": false
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
"serve": {
|
|
352
|
+
"description": "A command started in the background in the worktree before the Workflow's Steps and stopped after them, such as a dev server. It reads its port from the variables of ports.env, so it needs ports.",
|
|
353
|
+
"type": "string",
|
|
354
|
+
"pattern": "\\S"
|
|
355
|
+
},
|
|
356
|
+
"allowedCommands": {
|
|
357
|
+
"description": "Commands the Workflow's Steps may run besides the top-level allowedCommands, as Bash permission patterns without Bash( )",
|
|
358
|
+
"type": "array",
|
|
359
|
+
"items": {
|
|
360
|
+
"type": "string",
|
|
361
|
+
"pattern": "\\S"
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
"allowedTools": {
|
|
365
|
+
"description": "Tools the Workflow's Steps may use besides the usual ones, as Claude Code permission rules. Committing, pushing, switching branches, the outside network and gh stay denied.",
|
|
366
|
+
"type": "array",
|
|
367
|
+
"items": {
|
|
368
|
+
"type": "string",
|
|
369
|
+
"pattern": "\\S"
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
"localNetwork": {
|
|
373
|
+
"description": "true lets the Workflow's Steps reach localhost, and nothing else on the network",
|
|
374
|
+
"type": "boolean"
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
"required": [
|
|
378
|
+
"steps"
|
|
379
|
+
],
|
|
380
|
+
"additionalProperties": false,
|
|
381
|
+
"description": "A named list of Steps that a Feature picks with a **Workflow:** line"
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
"defaultWorkflow": {
|
|
385
|
+
"description": "The Workflow of a Feature without a **Workflow:** line; none when left out",
|
|
386
|
+
"type": "string",
|
|
387
|
+
"pattern": "\\S"
|
|
388
|
+
},
|
|
389
|
+
"trusted": {
|
|
390
|
+
"description": "The logins whose comments reach the agent (on Azure DevOps, sign-in names such as ann@contoso.com). When set, it replaces the Tracker default (GitHub: write access; Azure DevOps: the project's Contributors group); leave it out to keep the default.",
|
|
391
|
+
"type": "array",
|
|
392
|
+
"items": {
|
|
393
|
+
"type": "string",
|
|
394
|
+
"pattern": "\\S"
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
"setup": {
|
|
398
|
+
"description": "The shell command run once in each new worktree, before the first session, such as one that installs dependencies. When it fails, the Feature stops with a comment saying why. Left out, nothing is run.",
|
|
399
|
+
"type": "string",
|
|
400
|
+
"pattern": "\\S"
|
|
401
|
+
},
|
|
402
|
+
"ports": {
|
|
403
|
+
"description": "Ports reserved for each run and held for its whole life, so that two runs on one machine never share a port. Left out, no port is held.",
|
|
404
|
+
"type": "object",
|
|
405
|
+
"properties": {
|
|
406
|
+
"count": {
|
|
407
|
+
"type": "integer",
|
|
408
|
+
"minimum": 1,
|
|
409
|
+
"maximum": 100,
|
|
410
|
+
"description": "How many ports to reserve"
|
|
411
|
+
},
|
|
412
|
+
"env": {
|
|
413
|
+
"minItems": 1,
|
|
414
|
+
"type": "array",
|
|
415
|
+
"items": {
|
|
416
|
+
"type": "string",
|
|
417
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
|
|
418
|
+
},
|
|
419
|
+
"description": "The environment variables that carry the ports to every session, the check and the setup command: the first name gets the first reserved port, the next name the next port, and so on"
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
"required": [
|
|
423
|
+
"count",
|
|
424
|
+
"env"
|
|
425
|
+
],
|
|
426
|
+
"additionalProperties": false
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
"required": [
|
|
430
|
+
"tracker",
|
|
431
|
+
"codeHost",
|
|
432
|
+
"check",
|
|
433
|
+
"allowedCommands"
|
|
434
|
+
],
|
|
435
|
+
"additionalProperties": false,
|
|
436
|
+
"title": "Nightjar factory.json"
|
|
437
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nightjar-feature
|
|
3
|
+
description: Write an agreed idea onto the repo's Tracker as a Nightjar Feature and its Tickets, through `nightjar create`. Use when a spec, plan or grilled idea is ready to become a Feature for Nightjar to build.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Write a Feature and its Tickets
|
|
7
|
+
|
|
8
|
+
Turn the idea agreed in this conversation into one Feature file and make it on the Tracker with `nightjar create`. Nightjar builds each Ticket as one commit, in Build order, on one branch.
|
|
9
|
+
|
|
10
|
+
## 1. Read the repo's setup
|
|
11
|
+
|
|
12
|
+
Read `factory.json` at the repo's root. Note the Tracker, and on Azure DevOps whether `tracker.ticketType` is set: without it `nightjar create` refuses, so ask the person which work item type a Ticket is (such as `User Story`) and add it to `factory.json` before step 4. Read the repo's `CLAUDE.md` or `AGENTS.md` and its glossary, if any, so titles use the repo's own words.
|
|
13
|
+
|
|
14
|
+
Done when you know the Tracker and that it can make Tickets.
|
|
15
|
+
|
|
16
|
+
## 2. Slice the idea into Tickets
|
|
17
|
+
|
|
18
|
+
Each Ticket is a **vertical slice**: one change that builds, passes the repo's check command, and is worth a commit on its own. Order them so each one builds on the ones above it. Give each:
|
|
19
|
+
|
|
20
|
+
- a title that says what changes, in the imperative;
|
|
21
|
+
- what to build, enough for an agent with no other context: the files or modules it touches, the behaviour it adds;
|
|
22
|
+
- acceptance criteria an agent can check from the diff and the tests;
|
|
23
|
+
- the Tickets above it that must be built first;
|
|
24
|
+
- `**Model:**` and `**Effort:**` lines only for a Ticket that needs a stronger or a lighter model than the repo's default.
|
|
25
|
+
|
|
26
|
+
Done when every part of the agreed idea lands in exactly one Ticket, and every Ticket has acceptance criteria.
|
|
27
|
+
|
|
28
|
+
## 3. Write the Feature file
|
|
29
|
+
|
|
30
|
+
Write it to `.factory/plans/<short-name>.md`, in exactly this shape:
|
|
31
|
+
|
|
32
|
+
```markdown
|
|
33
|
+
# <Feature title>
|
|
34
|
+
|
|
35
|
+
<The spec: the problem, the solution, the decisions made, and what is out of scope.>
|
|
36
|
+
|
|
37
|
+
## Ticket 1: <title>
|
|
38
|
+
|
|
39
|
+
**Model:** opus
|
|
40
|
+
**Effort:** high
|
|
41
|
+
|
|
42
|
+
<What to build.>
|
|
43
|
+
|
|
44
|
+
### Acceptance criteria
|
|
45
|
+
|
|
46
|
+
- [ ] <a checkable result>
|
|
47
|
+
|
|
48
|
+
## Ticket 2: <title>
|
|
49
|
+
|
|
50
|
+
**Blocked by:** 1
|
|
51
|
+
|
|
52
|
+
<What to build.>
|
|
53
|
+
|
|
54
|
+
### Acceptance criteria
|
|
55
|
+
|
|
56
|
+
- [ ] <a checkable result>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Number the Tickets 1, 2, 3 in build order. `**Blocked by:**` names Tickets above it by number, comma separated.
|
|
60
|
+
|
|
61
|
+
## 4. Check it
|
|
62
|
+
|
|
63
|
+
Run `nightjar create --dry-run .factory/plans/<short-name>.md`. It names every fault with its line; fix them and run it again until it exits 0. Show the person what it says it would make.
|
|
64
|
+
|
|
65
|
+
Done when the dry run exits 0 and the person says to make it.
|
|
66
|
+
|
|
67
|
+
## 5. Make it
|
|
68
|
+
|
|
69
|
+
Run `nightjar create .factory/plans/<short-name>.md`. It makes the Feature with no Signal and each Ticket ready, linked to its blockers, and prints each reference.
|
|
70
|
+
|
|
71
|
+
If it exits 1, it names what it made before the fault: tell the person, and leave those items for them to keep or remove.
|
|
72
|
+
|
|
73
|
+
Report the Feature's reference and its Tickets'. The Go is the person's: tell them to assign the Feature to themselves and give it the Go when they want it built.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// The shape of .factory/status.json, defined once for the writer and the plugin; types only, so the plugin can import it.
|
|
2
|
+
|
|
3
|
+
export type Doing =
|
|
4
|
+
| { readonly kind: 'idle'; readonly nextPollAt: string }
|
|
5
|
+
| {
|
|
6
|
+
readonly kind: 'building';
|
|
7
|
+
readonly feature: string;
|
|
8
|
+
// null while the Feature is set up and reviewed, and during a Step that runs after all Tickets
|
|
9
|
+
readonly ticket: string | null;
|
|
10
|
+
readonly step: 'setup' | 'build' | 'fix' | 'review' | 'step';
|
|
11
|
+
// a build's question round or a fix round, of how many there may be
|
|
12
|
+
readonly round: number | null;
|
|
13
|
+
readonly rounds: number | null;
|
|
14
|
+
readonly session: string | null;
|
|
15
|
+
readonly startedAt: string;
|
|
16
|
+
}
|
|
17
|
+
| { readonly kind: 'paused'; readonly why: string; readonly until: string | null }
|
|
18
|
+
| { readonly kind: 'off' };
|
|
19
|
+
|
|
20
|
+
export type Happened =
|
|
21
|
+
| { readonly kind: 'built'; readonly feature: string; readonly ticket: string }
|
|
22
|
+
| {
|
|
23
|
+
readonly kind: 'needs-info';
|
|
24
|
+
readonly feature: string;
|
|
25
|
+
readonly ticket: string | null;
|
|
26
|
+
readonly why: string;
|
|
27
|
+
}
|
|
28
|
+
| { readonly kind: 'failed'; readonly feature: string; readonly why: string }
|
|
29
|
+
| { readonly kind: 'pull'; readonly feature: string; readonly url: string }
|
|
30
|
+
| { readonly kind: 'stale'; readonly commit: string };
|
|
31
|
+
|
|
32
|
+
export type Event = Happened & { readonly seq: number; readonly at: string };
|
|
33
|
+
|
|
34
|
+
export interface Status {
|
|
35
|
+
readonly at: string;
|
|
36
|
+
readonly pid: number;
|
|
37
|
+
readonly spentTodayUsd: number;
|
|
38
|
+
readonly dailyUsd: number;
|
|
39
|
+
readonly doing: Doing;
|
|
40
|
+
// the last ten, oldest first; a reader toasts each seq it has not seen
|
|
41
|
+
readonly recent: Event[];
|
|
42
|
+
// the commit of newer Nightjar code than the one running; nothing sets it yet, older files lack it
|
|
43
|
+
readonly codeMoved?: string | null;
|
|
44
|
+
}
|