@codetreker/daynight 0.21.2 → 0.21.8

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.
Files changed (48) hide show
  1. package/README.md +1176 -0
  2. package/dist/api/client.js +15 -2
  3. package/dist/api/client.js.map +1 -1
  4. package/dist/api/types.d.ts +1 -0
  5. package/dist/commands/review/instance-lock.js +2 -114
  6. package/dist/commands/review/instance-lock.js.map +1 -1
  7. package/dist/commands/skill/skills/using-daynight/SKILL.md +39 -41
  8. package/dist/commands/skill/skills/using-daynight/references/create-task.md +15 -12
  9. package/dist/commands/skill/skills/using-daynight/references/execute-task-in-managed.md +91 -0
  10. package/dist/commands/skill/skills/using-daynight/references/goal.md +34 -32
  11. package/dist/commands/skill/skills/using-daynight/references/handbook.md +41 -10
  12. package/dist/commands/skill/skills/using-daynight/references/handoff.md +1 -1
  13. package/dist/commands/skill/skills/using-daynight/references/run-task.md +55 -164
  14. package/dist/commands/skill/skills/using-daynight/references/task-content.md +6 -4
  15. package/dist/commands/skill/skills/using-daynight/references/task-execution.md +136 -0
  16. package/dist/commands/task/command.js +13 -1
  17. package/dist/commands/task/command.js.map +1 -1
  18. package/dist/commands/task/definition.js +3 -2
  19. package/dist/commands/task/definition.js.map +1 -1
  20. package/dist/commands/worker/identity.d.ts +2 -0
  21. package/dist/commands/worker/identity.js +41 -0
  22. package/dist/commands/worker/identity.js.map +1 -0
  23. package/dist/commands/worker/instance-lock.d.ts +6 -0
  24. package/dist/commands/worker/instance-lock.js +7 -0
  25. package/dist/commands/worker/instance-lock.js.map +1 -0
  26. package/dist/commands/worker/paths.d.ts +11 -0
  27. package/dist/commands/worker/paths.js +16 -0
  28. package/dist/commands/worker/paths.js.map +1 -0
  29. package/dist/commands/worker/store.d.ts +55 -0
  30. package/dist/commands/worker/store.js +460 -0
  31. package/dist/commands/worker/store.js.map +1 -0
  32. package/dist/commands/worker/types.d.ts +101 -0
  33. package/dist/commands/worker/types.js +2 -0
  34. package/dist/commands/worker/types.js.map +1 -0
  35. package/dist/commands/worker/worktrees.d.ts +29 -0
  36. package/dist/commands/worker/worktrees.js +285 -0
  37. package/dist/commands/worker/worktrees.js.map +1 -0
  38. package/dist/config/document.d.ts +1 -1
  39. package/dist/config/document.js +1 -0
  40. package/dist/config/document.js.map +1 -1
  41. package/dist/platform/instance-lock.d.ts +5 -0
  42. package/dist/platform/instance-lock.js +115 -0
  43. package/dist/platform/instance-lock.js.map +1 -0
  44. package/dist/repository/git.d.ts +2 -0
  45. package/dist/repository/git.js +8 -5
  46. package/dist/repository/git.js.map +1 -1
  47. package/package.json +2 -2
  48. package/dist/commands/skill/skills/using-daynight/references/autopilot.md +0 -136
package/README.md ADDED
@@ -0,0 +1,1176 @@
1
+ # Daynight CLI
2
+
3
+ The `@codetreker/daynight` package provides the `daynight` command and its `dn`
4
+ alias. Use it to manage server-backed projects, tasks and attachments, install
5
+ the `using-daynight` skill for coding agents, and run a local GitHub PR reviewer
6
+ through Copilot CLI. Both command names share configuration and behavior.
7
+
8
+ See the [project overview](../../README.md) for the browser workspace and service,
9
+ and the [development guide](../../docs/development.md) for source builds,
10
+ validation, package versions and npm publication. Each command's `--help` owns
11
+ its exact usage. Review execution additionally requires Git, an authenticated
12
+ GitHub CLI and Copilot CLI on `PATH`.
13
+
14
+ - [Install and update](#install-and-update)
15
+ - [Client commands](#client-commands)
16
+ - [Agent skill installation](#agent-skill-installation)
17
+ - [Shell completion](#shell-completion)
18
+ - [Configuration setup](#configuration-setup)
19
+ - [Project management](#project-management)
20
+ - [Task management](#task-management)
21
+ - [Task deletion](#task-deletion)
22
+ - [Task attachments](#task-attachments)
23
+ - [Review configuration and startup](#review-configuration-and-startup)
24
+ - [Review status listing](#review-status-listing)
25
+ - [Durable review state](#durable-review-state)
26
+ - [GitHub observations](#github-observations)
27
+ - [Repository clones and worktrees](#repository-clones-and-worktrees)
28
+ - [Copilot execution](#copilot-execution)
29
+ - [Coordination and shutdown](#coordination-and-shutdown)
30
+
31
+ ## Install and update
32
+
33
+ Use Node.js 24 LTS. Install the CLI with npm:
34
+
35
+ ```bash
36
+ npm install --global @codetreker/daynight
37
+ dn --version
38
+ ```
39
+
40
+ The installation provides both `daynight` and `dn`; every command works with
41
+ either name, for example `dn task list` or `dn skill install`. Help and diagnostics
42
+ use the canonical `daynight` spelling.
43
+
44
+ Update that npm global installation with:
45
+
46
+ ```bash
47
+ dn update
48
+ ```
49
+
50
+ The command checks `@codetreker/daynight`'s `latest` version in the configured npm
51
+ registry and installs that exact version only when it is newer. It updates the
52
+ installation that is running, even if npm's current default global prefix has
53
+ changed. An equal or newer installed version succeeds without installation or
54
+ downgrade. User and global npm registry/authentication settings apply; the current
55
+ working directory's project `.npmrc` does not select the update source.
56
+
57
+ `daynight update --help` explains the command. Self-update requires an npm-owned
58
+ global package and launcher. Source checkouts, local dependencies, `npx`, pnpm and
59
+ `npm link` installations receive guidance to use their original package manager.
60
+ If an update is needed, run the command from outside its installation directory.
61
+ The installer streams its output, enforces the target's Node.js engine requirement
62
+ and reports permission, network and installation errors. It does not request
63
+ administrator privileges automatically. npm owns replacement and recovery; a
64
+ failed installation is not a promise that every original file remains unchanged.
65
+
66
+ The command verifies the installed manifest, launcher and a fresh invocation's
67
+ version, then refreshes existing `using-daynight` skills from that installed
68
+ package. It checks User destinations and the current Git worktree's Project
69
+ destinations, including calls from subdirectories and linked worktrees. Outside
70
+ Git it checks User destinations only. It does not search other projects or need
71
+ agent launchers on PATH. Missing skills remain uninstalled. The same refresh
72
+ runs when the CLI is already current or ahead, using its installed bundle.
73
+
74
+ Refresh replaces complete skill directories, including local edits and obsolete
75
+ files. Shared physical destinations are written once. Each result identifies
76
+ its agents, scope, path and package version. A skill failure exits nonzero and
77
+ reports the package outcome separately; a successfully installed npm package is
78
+ retained, and rerunning `update` retries the skill refresh. All phases must
79
+ succeed before the command reports success. It requires no review configuration and does
80
+ not open SQLite, modify sessions or restart a running reviewer. The next CLI
81
+ invocation uses the installed version. Restart any running reviewer to use it;
82
+ on Windows, a reviewer holding a native addon open can prevent npm from replacing
83
+ that file and cause the update to fail. The
84
+ [self-update decision](../../.agents/notes/implemented/feature/2026-10-20-cli-self-update.md)
85
+ records installation ownership and verification requirements.
86
+
87
+ ## Client commands
88
+
89
+ ```text
90
+ daynight # Show root help
91
+ daynight --help # Also -h
92
+ daynight --version # Also -v
93
+ daynight update
94
+ daynight login [--no-browser] # Authorize CLI access through the browser
95
+ daynight logout # Revoke and remove the current CLI credential
96
+ daynight review # Show review help
97
+ daynight review run
98
+ daynight review list # Also review ls
99
+ daynight review add-repo <remote> [--path <path>]
100
+ daynight completion # Show completion help
101
+ daynight completion bash
102
+ daynight completion zsh
103
+ daynight completion setup [--shell bash|zsh] [--rc-file <path>]
104
+ daynight skill # Show skill help
105
+ daynight skill install # Select Agents, then User or Project scope
106
+ daynight project
107
+ daynight project create <name> [--repo <repo>]
108
+ daynight project list [--json]
109
+ daynight project show <project-id> [--json]
110
+ daynight task
111
+ daynight task create --title <title> [options]
112
+ daynight task list [--all | --status <status>] [--ready] [--json] [--project <project-id>]
113
+ daynight task ready [--limit <N>] [--json] [--project <project-id>]
114
+ daynight task show <task-id> [--json] [--project <project-id>]
115
+ daynight task update <task-id> [options]
116
+ daynight task set-status <task-id> <status> [--claim-id <claim-id>] [--if-version <version>] [--project <project-id>]
117
+ daynight task delete <task-id> [--remove-depends] [--if-version <version>] [--project <project-id>]
118
+ daynight task graph [--json] [--project <project-id>]
119
+ daynight task attachment
120
+ daynight task attachment put <task-id> <file> [--path <relative-path>] [--project <project-id>]
121
+ daynight task attachment list <task-id> [--tree | --json] [--project <project-id>]
122
+ daynight task attachment read <task-id> <relative-path> [--project <project-id>]
123
+ daynight task attachment remove <task-id> <relative-path> [--project <project-id>]
124
+ ```
125
+
126
+ Groups and operations show help when `--help` or `-h` is their sole argument.
127
+ Help, version and completion generation do not resolve the user home, load review
128
+ configuration, open SQLite or require review tools. `review add-repo` accepts one
129
+ `--path <path>` before or after its remote; `--path=value` and `--` are invalid.
130
+ Unknown commands and invalid arguments exit with status 2; operation failures
131
+ exit with status 1 and retain their cause. The old `--daemon-review` and root
132
+ `add-repo` forms are invalid. The
133
+ [client design](../../docs/design/daynight.md) owns command composition and lazy loading;
134
+ the [composition decision](../../.agents/notes/implemented/architecture/2026-10-20-client-command-composition.md)
135
+ records module ownership and the preserved data layout.
136
+
137
+ ## Agent skill installation
138
+
139
+ The public `using-daynight` skill provides task creation, handoff review and
140
+ execution of one specified task. Ordinary execution reads `run-task.md`.
141
+ Worker-started agents use `execute-task-in-managed` only when their startup
142
+ prompt explicitly names the `worker-managed` environment, the `using-daynight`
143
+ skill and that mode, together with their assignment. `SKILL.md` routes to the
144
+ selected instructions; ordinary execution does not load managed task rules.
145
+ Shared task inputs, delivery and acceptance rules retain one owner in the bundle.
146
+ The worker runtime remains under development.
147
+
148
+ Install the skill through an interactive terminal:
149
+
150
+ ```bash
151
+ daynight skill install
152
+ ```
153
+
154
+ The command detects available codex, copilot and claude launchers without
155
+ starting them or checking login. Select one or more detected Agents with Space,
156
+ then Enter; the initial selection is empty. Next select User or Project,
157
+ with User initially selected. Installation starts after the scope is submitted.
158
+ Repeating the command refreshes the full bundle from the running package.
159
+ `daynight update` automatically refreshes existing User and current-worktree
160
+ Project copies with the same replacement semantics; it also repairs existing
161
+ skill directories whose entrypoint was removed and replaces dangling leaf links.
162
+ A regular file at the expected skill-directory path is an error. See
163
+ [CLI updates](#install-and-update) for package ownership and failure handling.
164
+
165
+ | Agent | User destination | Project destination |
166
+ |---|---|---|
167
+ | Codex | `~/.agents/skills/using-daynight/` | `<worktree>/.agents/skills/using-daynight/` |
168
+ | Copilot CLI | `~/.agents/skills/using-daynight/` | `<worktree>/.agents/skills/using-daynight/` |
169
+ | Claude Code | `~/.claude/skills/using-daynight/` | `<worktree>/.claude/skills/using-daynight/` |
170
+
171
+ User scope works outside Git. Project scope uses the current Git worktree root,
172
+ including calls from subdirectories or linked worktrees, without requiring an
173
+ origin, server configuration or project association. Installing the skill and
174
+ associating a project remain separate operations. Terminal stdin and stderr are
175
+ required; prompts use stderr and installation results use stdout. Help and
176
+ installation do not depend on review configuration or credentials.
177
+
178
+ Each installation replaces the complete using-daynight leaf, including local
179
+ edits and obsolete files. It then removes the legacy daynight leaf in the same
180
+ selected physical skill root. The old name is retained until publication
181
+ succeeds. Other skills, opposite-scope copies and parent-directory links are
182
+ preserved; leaf links are replaced or removed without following their targets.
183
+ Several Agent paths resolving to one physical root share one write. Destructive
184
+ nesting involving an installation or legacy-cleanup path is rejected before
185
+ writing. Discovery paths may be shared with unselected Agents, and host precedence
186
+ continues to govern copies at other scopes.
187
+
188
+ The command reports per-Agent destinations and results. Failure stops later
189
+ targets, retains earlier completed installations and exits nonzero. If legacy
190
+ cleanup fails after publication, the new bundle stays installed and the command
191
+ reports the incomplete migration. Replacement failure after removing an existing
192
+ using-daynight leaf may leave that destination absent; diagnostics preserve the
193
+ actual phase and reason. Rerunning installs the complete packaged bundle.
194
+ Cancellation before publication cleans its stage and newly created empty parents.
195
+
196
+ Codex normally discovers changed skills automatically; restart its session if
197
+ needed. For Copilot CLI run `/skills reload` and inspect
198
+ `/skills info using-daynight`. Claude Code watches existing roots; use
199
+ `/reload-skills` when a top-level skills directory was created during the session.
200
+ The [skill design](../../docs/design/daynight-agent-skill.md) owns mechanisms, routing
201
+ and the simulated-launcher native installation matrix.
202
+
203
+ ## Shell completion
204
+
205
+ Bash 4.2 or newer and zsh have native completion scripts. Install startup
206
+ configuration with:
207
+
208
+ ```bash
209
+ daynight completion setup
210
+ ```
211
+
212
+ Setup detects the calling shell from its direct parent process. If it cannot
213
+ identify Bash or zsh reliably, select one explicitly:
214
+
215
+ ```bash
216
+ daynight completion setup --shell bash
217
+ daynight completion setup --shell zsh
218
+ ```
219
+
220
+ The login-shell preference in `SHELL` does not establish which shell is running.
221
+ For a custom startup file, use `--rc-file`; only that file is managed:
222
+
223
+ ```bash
224
+ daynight completion setup --shell bash --rc-file /path/to/bashrc
225
+ ```
226
+
227
+ Bash setup manages `.bashrc` and the first readable existing login file in the
228
+ order `.bash_profile`, `.bash_login`, `.profile`. It creates `.bash_profile` only
229
+ when none of those files exists; if existing profiles are all unreadable, it
230
+ reports an error. The login block runs only in interactive Bash and can safely
231
+ appear in a `.profile` shared with other POSIX shells. It does not
232
+ make the login shell load the rest of `.bashrc`.
233
+
234
+ zsh setup uses `$ZDOTDIR/.zshrc`, or `$HOME/.zshrc` when `ZDOTDIR` is unset.
235
+ An exported empty `ZDOTDIR` selects `/.zshrc`; setup resolves a relative value
236
+ from its current working directory. A later zsh started in another directory
237
+ resolves that relative value from its own startup directory. A value set only
238
+ inside zsh is not visible to the installer; use `--rc-file` in that case.
239
+ The managed block reuses an initialized completion system or runs `compinit`
240
+ with its normal security checks before loading daynight.
241
+
242
+ Setup recognizes its managed block and the documented standalone manual loading
243
+ statement. Repeating it leaves an installed file unchanged. A managed block
244
+ checks that both `daynight` and `dn` use the expected callable completion
245
+ function before skipping loading. A missing or replaced registration for either
246
+ command reloads the shared script and restores both commands. Complete
247
+ registrations are reused, including when startup files load each other. Preserved
248
+ manual loading statements keep their unconditional behavior: if one runs after a managed block, it generates and loads the script
249
+ again. Existing content, line endings, permissions and startup-file symbolic
250
+ links are retained. Added blocks use LF line endings because a carriage return
251
+ is shell token data. Malformed managed blocks, invalid targets and file access failures produce
252
+ explicit errors. Setup does not migrate blocks from earlier templates. If an
253
+ earlier block is reported as unrecognized, remove its marked section and rerun
254
+ setup, or use the source command below to activate the current script directly.
255
+
256
+ Setup reports the startup files it handled. It installs persistent configuration;
257
+ an ordinary CLI child process cannot inspect or change its parent shell's loaded
258
+ completion functions. Use the existing loading command to enable completion in
259
+ the current session:
260
+
261
+ ```bash
262
+ source <(daynight completion bash)
263
+ ```
264
+
265
+ For zsh, initialize its completion system first if the session has not already
266
+ done so:
267
+
268
+ ```zsh
269
+ autoload -Uz compinit
270
+ compinit
271
+ source <(daynight completion zsh)
272
+ ```
273
+
274
+ The `bash` and `zsh` generation operations write only scripts to stdout and do
275
+ not change startup files. Loading the zsh script without initialized `compinit`
276
+ fails with a diagnostic. The outputs are designed for `source`; using the same
277
+ output directly as an `fpath` autoload file is outside the loading contract.
278
+ Setup checks file contents without executing them. Custom early returns or later
279
+ commands that remove registrations can prevent a startup file from enabling
280
+ completion; verify such configuration by starting the shell.
281
+
282
+ The generated scripts register completion for both `daynight` and `dn`.
283
+ Completion suggests commands, nested operations, aliases, options, shell names
284
+ and local directories for `review add-repo --path`.
285
+ zsh also displays descriptions.
286
+ The scripts run in the shell on each Tab without starting Node or reading review
287
+ configuration, SQLite or the network. Directory suggestions preserve quoted and
288
+ special-character paths; an uncreated target directory remains valid input.
289
+
290
+ New shells generate definitions from the currently installed package. After an
291
+ update, run the applicable `source` command again to refresh an existing shell.
292
+ A saved generated script must be regenerated after updating. The
293
+ [completion design](../../docs/design/daynight-completion.md) explains the shared grammar
294
+ and shell integration. The
295
+ [completion decision](../../.agents/notes/implemented/feature/2026-10-20-shell-completion.md)
296
+ records compatibility and execution trade-offs; the
297
+ [setup decision](../../.agents/notes/implemented/feature/2026-10-21-completion-setup.md)
298
+ records startup-file ownership and installation limits.
299
+
300
+ ## Configuration setup
301
+
302
+ Project and task commands use `https://daynight.cc` when the configuration file or
303
+ `serverUrl` is absent. A production connection needs no server configuration.
304
+ Run `daynight login` to display an authorization code and open the verification
305
+ page. Check that the page's code matches the terminal, confirm the account and
306
+ approve access. The CLI saves the resulting credential without displaying its
307
+ secret. `daynight login --no-browser` displays the URL and code for authorization
308
+ in another browser. The device authorization expires after ten minutes; rejection, expiry and
309
+ cancellation leave an existing saved credential unchanged.
310
+
311
+ The CLI credential is named `Daynight CLI (<hostname>)`, using the machine that
312
+ runs `daynight login`, including when another device approves access. Hostnames
313
+ longer than 85 Unicode characters are shortened to their first 85 characters to
314
+ keep the credential name within 100 characters. The credential never expires by default.
315
+ The Web account's token manager can set a future expiration, restore “Never expires”, or
316
+ revoke it. Changing expiration keeps the same credential, so the saved CLI login
317
+ continues without replacing its secret. Expired or revoked credentials cannot be
318
+ revived. The [token manager mockup](../../packages/daynight-web/tests/mockups/tokens.html)
319
+ shares the production components and styles for creating tokens and editing
320
+ expiration, including conflict and uncertain-result states. A credential
321
+ represents the account's current project permissions. `daynight logout` revokes the current credential and removes
322
+ its local value after a confirmed response; an already invalid credential is
323
+ removed locally. Network or unconfirmed failures remain visible. Configuration
324
+ changes made during login or logout cannot overwrite another service origin or
325
+ another saved credential. A lost successful login response requires a fresh
326
+ login; the account token list can revoke a credential whose response was lost.
327
+
328
+ Without a local credential, a service command fails before dispatch and directs
329
+ the user to `daynight login`. A server `401` gives the same guidance. Business
330
+ commands do not start login, follow redirects with credentials, or automatically
331
+ repeat a write. Reconcile an unconfirmed business mutation before another one.
332
+
333
+ The first `review run`, `review list` or `review ls` asks for a repository when
334
+ the file or `repositories` field is absent. To configure one in advance, run:
335
+
336
+ ```bash
337
+ daynight review add-repo https://github.com/OWNER/REPO.git
338
+ daynight review add-repo git@github.com:OWNER/OTHER.git --path ./review-other
339
+ ```
340
+
341
+ Interactive guidance requires terminal stdin and stderr. Prompts and save
342
+ messages use stderr so stdout retains its normal text or JSON format.
343
+ Noninteractive missing review configuration fails with a `review add-repo`
344
+ command. Shared YAML/schema errors, invalid selected values, explicit empty
345
+ review lists and read failures retain their errors. Unrelated capability values
346
+ remain outside the current command's validation. Help, version, completion,
347
+ update and invalid arguments do not prompt.
348
+
349
+ Test services and noninteractive automation use the existing
350
+ `~/.daynight/config.yml` fields. For a test service, provision its origin before
351
+ running `daynight login`:
352
+
353
+ ```yaml
354
+ serverUrl: http://127.0.0.1:8787
355
+ ```
356
+
357
+ For unattended access, a secret-provisioning process can write `serverToken`
358
+ together with its intended `serverUrl`; omit `serverUrl` only when the credential
359
+ belongs to `https://daynight.cc`. Keep that file private, with mode `0600` on
360
+ POSIX, and never put credentials in command arguments, logs or repository files.
361
+ Provisioners must preserve unrelated settings and pair the origin with its own
362
+ credential. Replacing `serverUrl` manually does not clear an old token; remove
363
+ or replace it before sending another request. External editors and provisioners
364
+ do not participate in the CLI's configuration lock.
365
+
366
+ Tokens are opaque visible ASCII and require HTTPS except for HTTP origins whose
367
+ host is literal `localhost`, a numeric IPv4 address in `127.0.0.0/8`, or `::1`.
368
+ Invalid explicit origins and credentials remain errors. Normal CLI use requires
369
+ no manual PAT creation. There is no top-level `daynight setup` command; shell
370
+ startup installation remains available through `daynight completion setup`.
371
+
372
+ Review guidance collects values before one atomic save under the configuration
373
+ write lock, preserving comments, unrelated settings and completed concurrent
374
+ changes to unrelated fields. A selected review-field conflict requires a fresh
375
+ decision. Login and logout check the observed origin and credential together
376
+ under the same lock. Credential-bearing files use POSIX mode `0600`, including
377
+ review writes; files without a token retain existing permissions. Symlink
378
+ rejection and atomic replacement apply to CLI configuration writers.
379
+ Ctrl+C, termination signals or EOF cancel prompts without partial saves or
380
+ business execution. Human input consumes no business timeout. Review guidance
381
+ saves configuration without network, login or authentication checks; cloning and
382
+ review state initialization belong to the business operation.
383
+
384
+ The [configuration decision](../../.agents/notes/implemented/feature/2026-10-21-guided-configuration-setup.md)
385
+ owns review guidance and persistence; the
386
+ [device-login decision](../../.agents/notes/implemented/architecture/2026-10-25-cli-device-login.md)
387
+ owns the default service, explicit login/logout and credential lifecycle. The
388
+ [top-level setup removal decision](../../.agents/notes/implemented/simplification/2026-10-25-remove-top-level-setup.md)
389
+ records the command removal and configuration-file provisioning boundary.
390
+
391
+ ## Project management
392
+
393
+ After `daynight login`, create, list or inspect projects on `https://daynight.cc`.
394
+ To use a test server, set `serverUrl` in `~/.daynight/config.yml`:
395
+
396
+ ```yaml
397
+ serverUrl: http://127.0.0.1:8787
398
+ ```
399
+
400
+ The origin includes its protocol, host and optional port; the client adds
401
+ `/api/v1`. When changing the origin externally, remove the old `serverToken`
402
+ before logging in to the new service; manual edits do not run CLI credential
403
+ cleanup. Then use the same commands:
404
+
405
+ ```bash
406
+ daynight project create "Example"
407
+ daynight project create "Example" --repo https://github.com/OWNER/REPO.git
408
+ daynight project list
409
+ daynight project list --json
410
+ daynight project show <project-id> --json
411
+ ```
412
+
413
+ Creation requires one positional name; quote names containing spaces. Omit
414
+ `--repo` to use the current Git worktree's effective `origin`, including Git
415
+ `insteadOf` expansion. Supply `--repo` to use that address without inspecting Git;
416
+ this form, listing and details work outside Git repositories. For a name beginning
417
+ with `-`, use `daynight project create -- -name` or put an explicit repository
418
+ option before the terminator: `daynight project create --repo <repo> -- -name`.
419
+ The name is sent unchanged.
420
+
421
+ Creation first scans every project page and compares canonical repository
422
+ identities. With no match it registers the original name and repository address.
423
+ With one match it reports `Project already exists.` and the existing project,
424
+ leaving that project's name and address unchanged. Multiple matches fail with
425
+ their IDs; lookup failures and exhausted command budgets stop before creation.
426
+ This client preflight does not provide atomic uniqueness against concurrent
427
+ creators, and the service continues to allow duplicate repository registrations.
428
+ Project commands do not write repository bindings or ignore rules. Lists traverse
429
+ all pages. Human output uses complete labeled project blocks with visible
430
+ terminal-control escapes. JSON preserves resource fields and nanosecond timestamp
431
+ strings; a later-page failure produces an error with empty stdout. The
432
+ [project/task requirements](../../docs/spec/daynight-project-task.md) own the complete
433
+ behavior and remaining task-command scope.
434
+
435
+ ## Task management
436
+
437
+ Task commands use the same `serverUrl` configuration as project commands:
438
+
439
+ ```bash
440
+ daynight task create --title "Implement sign-in" --description '## Sign-in
441
+
442
+ Implement OAuth sign-in for the web workspace. Deliver the callback flow and
443
+ visible failure recovery; preserve the existing session and provider rules.
444
+ Complete when a valid login opens the workspace and a rejected login can retry.'
445
+ daynight task create --title "Build the sign-in page" --depends-on <design-task-id> --external-depends-on <authentication-task-id>
446
+ daynight task ready
447
+ daynight task ready --limit 5 --json
448
+ daynight task ready --allow-agents true --compatible-platform linux --json
449
+ daynight task list --allow-agents false --ready
450
+ daynight task list --ready
451
+ daynight task list --all --json
452
+ daynight task list --status in_progress --json
453
+ daynight task show <task-id> --json
454
+ daynight task update <task-id> --description=
455
+ daynight task update <task-id> --allow-agents true --if-version <version>
456
+ daynight task create --title "Check Windows build" --required-platform windows
457
+ daynight task update <task-id> --required-platform macos --if-version <version>
458
+ daynight task update <task-id> --clear-required-platform --if-version <version>
459
+ daynight task set-status <task-id> <status> [--claim-id <claim-id>] [--if-version <version>] [--project <project-id>]
460
+ daynight task update <task-id> --depends-on <task-a> --depends-on <task-b>
461
+ daynight task update <task-id> --clear-dependencies
462
+ daynight task graph --json
463
+ ```
464
+
465
+ Every operation accepts `--project <project-id>`, which selects a project for one
466
+ invocation without reading Git or local bindings. Otherwise, the CLI reads the
467
+ current worktree's effective `origin`, normalizes equivalent HTTPS/SSH/SCP
468
+ addresses, and matches the configured server's projects. A missing match fails
469
+ with `Project does not exist`; multiple matches require explicit selection.
470
+ A unique discovery is saved in the worktree's `.daynight/project.yml` with the
471
+ server origin and repository identity, after ensuring `/.daynight/` is effective
472
+ in the root `.gitignore`. A cached binding is verified against the server on each
473
+ use and remains stable if another project later shares that repository.
474
+
475
+ Creation starts in `todo` with `allowAgents=false` and unrestricted
476
+ `requiredPlatform=null` unless explicitly set. `task set-status <id> <status>`
477
+ sets `todo`, `in_progress` or `done`, including reopening and direct completion.
478
+ Every project member may use ordinary status setting. Active worker completion
479
+ requires the current owner and an explicit `--claim-id <claim-id>` with target
480
+ `done`; the CLI uses the existing typed completion operation. The option is
481
+ validated before configuration or network access, is rejected for other targets,
482
+ and is never inferred from a task or environment. Without it, ordinary status
483
+ setting is unchanged. Release and continuation of released work use their protected
484
+ operations. Status does not grant execution or delivery authority. Generic updates cannot write status; old lifecycle commands and routes
485
+ are removed without aliases. `--if-version` uses the exact reviewed int64 value;
486
+ without it, the CLI reads once immediately before submitting. No write retries
487
+ occur. A controller-bounded worker assignment executes its supplied claim in the
488
+ provided worktree, finishes with the explicit claim ID after delivery, and leaves
489
+ system worktree cleanup and next-task selection to its controller. Version is
490
+ checked before same-state handling: current same-state keeps
491
+ version, update time and timing unchanged; actual changes increment once.
492
+
493
+ Entering in_progress or done requires all direct prerequisites, ordinary and
494
+ external, to be done. Reopening done requires no direct in-progress or done
495
+ dependents. Refusals return sorted blocking task IDs without cascading changes.
496
+ The project transaction serializes status and dependency writes and preserves
497
+ materials, properties/PRs, permission, both dependency sets and attachments.
498
+
499
+ Migration `014_task_status_assignment.sql` converts historical proposed rows
500
+ to todo, increments only those versions and updates their update time while
501
+ preserving every other field, including requiredPlatform and historical execution timestamps. Default,
502
+ data, CHECK and ledger change atomically. Other rows and applied migrations remain
503
+ unchanged; restart does not repeat the conversion. Runtime readers reject the old state.
504
+
505
+ Task resources expose required nullable `startedAt` and `completedAt`. Actual entry
506
+ into in_progress starts a new interval and clears the end; return to todo clears
507
+ both. In-progress to done preserves a nullable start and records a real end;
508
+ todo to done records only an end, leaving duration unknown. Metadata and same-state
509
+ writes preserve time. Complete-graph and task-sync responses supply a database
510
+ `observedAt` sample; Web synchronization updates its separate clock without
511
+ rebuilding unchanged graph/index data.
512
+ Read-only timing fields remain in JSON; human CLI output keeps its field choices.
513
+ The [status requirements](../../docs/spec/daynight-task-status.md) and
514
+ [architecture](../../docs/design/daynight-task-status.md) own the complete rules.
515
+
516
+ Task and graph resources also require `externalDependsOn`, a sorted,
517
+ duplicate-free subset of all `dependsOn` IDs. CLI JSON preserves it and the
518
+ shared human dependency block shows `External dependencies (N): ...`. Current
519
+ API dependency fields are independently optional: a dependsOn-only PATCH
520
+ retains classification on surviving edges, while an externalDependsOn-only PATCH
521
+ replaces the exact external subset. CLI --depends-on and --external-depends-on
522
+ compile both complete sets whenever either option is supplied; ordinary-only
523
+ clears the external subset and external-only replaces all relationships. Omit
524
+ both CLI options to preserve them. Metadata and lifecycle actions retain
525
+ unmodified classification. Every edge still participates in blocking and cycles.
526
+
527
+ Every Project resource includes `settings` with an exact positive int64 `version`
528
+ and `executionWarningMinutes` from 1 through 2147483647, initially 60. Project
529
+ create/read/list, the project in graph responses, and a successful settings PATCH
530
+ return this same shape. The member-readable settings page lets administrators
531
+ save or cancel a draft; ordinary members see the saved value without editing.
532
+ The server checks current administrator authority after the project lock, then
533
+ the observed settings version. An equal-value save preserves version and
534
+ `updatedAt`; a real change increments version and updates `updatedAt`. Migration
535
+ preserves historical project timestamps. CLI JSON preserves settings and nested
536
+ versions without rounding; human output keeps its established fields.
537
+
538
+ An unconfirmed settings PATCH response requires a Project and membership reread
539
+ before another write. Failed reconciliation keeps Save blocked and offers read
540
+ retry; network, protocol, 5xx or navigation cancellation never prove rollback.
541
+ Confirmed refusals and unsaved/canceled drafts do not apply local settings.
542
+ Project-only changes update graph metadata while retaining the task index and
543
+ layout when tasks and summary are unchanged. Running known-start tasks subscribe
544
+ to one visible-page ticker; completed duration uses stored endpoints and unknown
545
+ starts show no inferred duration. Warnings use an unrounded strict comparison
546
+ and disappear on completion without changing task status. The server-sample
547
+ clock avoids client wall-clock skew but does not remove network sampling delay.
548
+
549
+
550
+ The Web detail header places a three-item status menu beside the actual task
551
+ title on both tabs. The current item remains selectable. Confirmation names the
552
+ task, current/target states and timing effects; Cancel and Escape send no write.
553
+ Status, **Automatic execution / 自动执行** and platform confirmation share one per-task mutation owner.
554
+ Pending, stale or unknown results block conflicting writes. Current-version same-state responses
555
+ confirm no stored change; actual changes refresh the graph. Unknown outcomes use
556
+ GET-only reconciliation, preserving errors and never attributing the observed
557
+ state to the uncertain request. Closing details does not roll back a submission.
558
+
559
+ Task details use one platform select in the left status group to display the
560
+ confirmed requirement and offer Any platform, Windows, Linux and macOS. Choosing
561
+ a different value opens confirmation showing the current and target platforms;
562
+ only confirmation submits the reviewed exact task version. Choosing the saved
563
+ value, Cancel, close, backdrop dismissal and Escape send no request. Cancellation
564
+ returns focus to the select. The confirmed value remains displayed until success,
565
+ and Any platform clears requiredPlatform. Overview has no separate platform
566
+ editor or Save action. The control stays available on either detail tab, is
567
+ locked during in_progress, and retains shared pending/unknown reconciliation
568
+ across navigation. Rows and graph nodes remain read-only and show each task's
569
+ own requirement; root values do not define chain-wide platform requirements.
570
+ The [confirmed platform control decision](../../.agents/notes/implemented/simplification/2026-10-24-task-platform-confirmation-control.md)
571
+ records its allocation and focus behavior.
572
+
573
+ The permission switch has confirmation in both directions, remains false by
574
+ default and is locked against actual changes while in_progress. It governs
575
+ automatic discovery; explicit task execution may use either value. Rows and graph
576
+ nodes display each task's own permission. Permission does not control worker
577
+ ownership; ordinary status setting cannot release active execution or resume
578
+ released resources. Claim-bound done validates ownership. None of these
579
+ operations stops a remote process or replaces PR review and delivery authority.
580
+ The [status decision](../../.agents/notes/implemented/architecture/2026-10-24-task-status-assignment.md)
581
+ records migration and shared-session trade-offs.
582
+
583
+ `task ready` selects up to 10 actionable tasks by
584
+ default; `--limit <N>` accepts decimal integers from 1 through 100. It makes one
585
+ task-list request with `ready=true`, the chosen limit and optional
586
+ `--allow-agents true|false` and `--compatible-platform windows|linux|macos`
587
+ filters, without fetching later pages. Compatibility includes unrestricted tasks
588
+ and tasks requiring that platform. The service applies all filters before
589
+ pagination and binds them to the cursor. The service orders results by creation time and then task ID, both
590
+ ascending. A ready task is `todo` with all direct dependencies `done`. This
591
+ bounded selection supports choosing the next work without retrieving the whole
592
+ project; `task graph` provides a dependency overview when needed. `task list`
593
+ reads every matching page, including with `--ready`, and excludes `done` by
594
+ default. `--all` includes every status; `--status <status>` selects one status,
595
+ including `done`. These two options conflict. `--ready` intersects the selected
596
+ statuses and can be combined with `--all`. List results place `in_progress`
597
+ first, then ready tasks, other `todo` tasks, and `done`; each group retains
598
+ service order across all pages. This order applies to human and JSON results.
599
+ `task ready` accepts neither `--status` nor `--cursor`. `task list` supports the
600
+ same permission and compatibility filters across every matching page. Both are
601
+ automatic-selection conditions independent of readiness; explicitly designated
602
+ execution retains the manual exception.
603
+
604
+ Updates preserve omitted fields; an empty description clears it. Repeated
605
+ `--depends-on` and `--external-depends-on` declare the complete ordinary and
606
+ external sets. Either option replaces all relationships and classifications;
607
+ ordinary-only makes every supplied edge ordinary, while external-only leaves
608
+ only those external edges. IDs are canonicalized and sorted; malformed and
609
+ case-equivalent duplicate/cross-declared UUIDs fail before configuration or
610
+ network access. `--clear-dependencies` sends two empty sets and conflicts with
611
+ either dependency option. An update needs at least one mutable
612
+ field. `--allow-agents true|false` explicitly changes automatic-execution
613
+ permission; omitted preserves it. Creation rejects the option. Existing tasks
614
+ receive true through migration without changing versions or business timestamps.
615
+ A matching same-value permission PATCH retains version and time, while a stale
616
+ version still conflicts and an actual in-progress toggle fails atomically.
617
+ Create and update accept `--required-platform windows|linux|macos`; update
618
+ accepts `--clear-required-platform` to send null, mutually exclusive with setting
619
+ a platform. Omission preserves an existing requirement. New and migrated tasks
620
+ are unrestricted unless explicitly set. Exact-version equal platform updates
621
+ preserve version and time; stale updates conflict and actual in-progress changes
622
+ are refused atomically. Explicit manual status setting remains available for every
623
+ requirement. The query platform selects candidates; it does not configure or
624
+ prove the environment of a future worker.
625
+ By default the CLI reads the task version before PATCH; `--if-version <n>`
626
+ uses that exact positive int64 version. Conflicts and failed writes are reported
627
+ without automatic retries.
628
+
629
+ Text options accept both separated values and `--option=value`. Inline assignment
630
+ splits at the first equals sign and supports leading dashes, such as
631
+ `--title=-example`; `--description=` is the explicit empty form. Separated values
632
+ starting with a dash are rejected. Directory options, switches and help reject
633
+ inline assignment. Attachment `put` declares its `--path` as text, accepting
634
+ `--path=value`; attachment `put/read/remove` also accept `--` before positional
635
+ paths starting with a dash. Other task operations retain their declared syntax.
636
+
637
+ The internal typed ApiClient accepts optional `workerId` on TaskFilters and
638
+ TaskPageQuery. It requests only the authenticated user/worker active claims and
639
+ validates active state and matching worker ID in responses. `listTasks` returns
640
+ only after every page succeeds; `listTaskPage` remains partial. A workerId-only
641
+ traversal across all relevant projects provides ownership inventory; extra filters
642
+ or incomplete pages cannot authorize cleanup. This field is not a public task CLI
643
+ option.
644
+
645
+ Human task lists use labeled blocks containing ID, project, title, PR references,
646
+ status, readiness, automatic-execution permission, required platform, dependencies and blocking.
647
+ Description, version and timestamps
648
+ remain available in show, ready, create and update output. Graph nodes include
649
+ state, permission, required platform, dependencies, blocking and title-preview truncation flags.
650
+ Task and graph decoders require a boolean `allowAgents`; missing, null or
651
+ nonboolean values are protocol errors. They also require `requiredPlatform`
652
+ as null or one of the three platform enums; missing keys or other values fail
653
+ without a runtime default. Human output uses `Required platform: any` for null
654
+ and the enum otherwise. Queries support
655
+ `--json`: task `list` returns every matching task in one array, omitting only
656
+ `description` while retaining every other API field, including raw PR strings,
657
+ version and timestamps. This applies to the default list and every filter,
658
+ including `--all`. Project lists retain all API fields. Task `ready` returns its
659
+ selected full tasks as an array, details return one full resource, and graphs
660
+ return the complete API object. An empty human ready result is `No ready tasks.`
661
+ and empty JSON is `[]`. Versions remain JSON numbers with full int64 precision.
662
+ Local preparation fails before any task mutation; a lost write response is
663
+ reported as unconfirmed. Installed CLI integration uses the real Go/PostgreSQL
664
+ service; deadline behavior uses short test-only budgets and byte probes retain
665
+ the full production limits. [PR #55](https://github.com/codetreker/daynight/pull/55)
666
+ records the original integration and real-default-budget validation, with its
667
+ historical source identity.
668
+
669
+ ## Task deletion
670
+
671
+ Read the task and use its observed version when deleting it:
672
+
673
+ ```bash
674
+ daynight task show <task-id> --json
675
+ daynight task delete <task-id> --if-version <version>
676
+ ```
677
+
678
+ Deletion removes the task from normal queries and prevents later reads and
679
+ changes. Stored task data, its own prerequisite references and attachment files
680
+ remain. An active worker claim on the target prevents deletion. Without
681
+ `--remove-depends`, an undeleted task depending on the target also prevents it.
682
+
683
+ To explicitly remove every other task's ordinary and external dependencies on
684
+ the target in the same transaction, use:
685
+
686
+ ```bash
687
+ daynight task delete <task-id> --remove-depends --if-version <version>
688
+ ```
689
+
690
+ This includes references added before that transaction executes and may make
691
+ affected tasks ready. Each changed dependency owner receives a new version;
692
+ its status, timing and other data stay unchanged. Deletion requires explicit
693
+ authorization for the target; removing other tasks' dependencies requires that
694
+ additional authorization.
695
+
696
+ Without `--if-version`, the CLI reads the current version immediately before the
697
+ write. Conflicts and failed writes are not retried. After an interrupted or lost
698
+ response, read the task to reconcile before considering another request. An
699
+ authorized read returning `410 task_deleted` confirms deletion; a live resource
700
+ requires a new decision, while a permission or transport failure leaves the
701
+ outcome unknown. The [deletion requirements](../../docs/spec/daynight-task-deletion.md)
702
+ and [design](../../docs/design/daynight-task-deletion.md) own retained history,
703
+ reference removal and cache invalidation.
704
+
705
+ ## Task attachments
706
+
707
+ Attachment commands use the existing project selection and server configuration:
708
+
709
+ ```bash
710
+ daynight task attachment put <task-id> ./design.md --path docs/design.md
711
+ daynight task attachment put <task-id> ./mockup.html --path mockup/index.html
712
+ daynight task attachment list <task-id> --tree
713
+ daynight task attachment list <task-id> --json
714
+ daynight task attachment read <task-id> docs/design.md
715
+ daynight task attachment read <task-id> images/mockup.png > ./mockup.png
716
+ daynight task attachment remove <task-id> docs/design.md
717
+ ```
718
+
719
+ Each upload accepts one local regular file. Without `--path`, its basename is the
720
+ target path; the same complete task-relative path is overwritten. Names preserve
721
+ case and Unicode spelling, with `/` separators and no absolute or dot-segment
722
+ paths. The content type comes from the target path's extension, even when it
723
+ differs from the local filename; unknown extensions use
724
+ `application/octet-stream`. Uploads and deletions affect one file at a time.
725
+
726
+ `list` reads every page before emitting its complete metadata result. `--tree`
727
+ and `--json` select mutually exclusive formats. `read` writes the original bytes
728
+ without labels, decoding or an added newline. Diagnostics remain on stderr;
729
+ a failed transfer can leave incomplete stdout and exits nonzero. File transfers
730
+ stream with backpressure and retain the shared deadlines and cancellation;
731
+ metadata JSON keeps its existing byte budgets. Use `--` for a dash-prefixed
732
+ positional path, for example:
733
+
734
+ ```bash
735
+ daynight task attachment put --project <project-id> <task-id> -- -design.md
736
+ daynight task attachment read --project <project-id> <task-id> -- -design.md
737
+ ```
738
+
739
+ Failed writes are not retried. File storage and PostgreSQL metadata are not
740
+ atomic; an unsuccessful operation may already have changed storage. The
741
+ [attachment requirements](../../docs/spec/daynight-task-attachments.md) define this
742
+ known issue and the trusted same-origin preview model. The
743
+ [authentication architecture](../../docs/design/daynight-auth.md) defines the required
744
+ authentication and project-membership checks for attachment requests. Trusted
745
+ executable HTML retains the application origin. The
746
+ [CLI delivery decision](../../.agents/notes/implemented/feature/2026-10-21-task-attachment-cli.md)
747
+ records binary transport and output ownership.
748
+
749
+ ## Review configuration and startup
750
+
751
+ Register a repository explicitly, or let the first review operation guide registration:
752
+
753
+ ```text
754
+ daynight review add-repo https://github.com/OWNER/REPO.git
755
+ daynight review add-repo git@github.com:OWNER/OTHER.git --path ./review-other
756
+ daynight review run
757
+ ```
758
+
759
+ For a local build, run `pnpm daynight review run` from the repository root.
760
+ These commands select `~/.daynight/config.yml` using the current OS user's home
761
+ directory. `review add-repo`
762
+ creates the configuration when absent. It reads, validates and saves configuration;
763
+ cloning, authentication checks, GitHub calls, SQLite initialization and PR boundary
764
+ selection belong to review startup. An already running reviewer keeps its loaded
765
+ configuration until its next startup.
766
+
767
+ The same YAML also accepts the server client's `serverUrl` and optional
768
+ `serverToken` fields. Review validates its own fields independently of server
769
+ business values. The server projection requires a valid HTTP(S) origin and
770
+ validates any configured token and its transport. The shared parser still rejects
771
+ invalid YAML, duplicate keys and unknown root fields. Registration can add the
772
+ first review repository to a server-only file while preserving its server
773
+ settings and comments.
774
+
775
+ A configuration with an explicit addition root is:
776
+
777
+ ```yaml
778
+ repositoryRoot: ~/daynights
779
+ copilotModel: auto
780
+ copilotReasoningEffort: high
781
+ repositories:
782
+ - remote: https://github.com/OWNER/REPO.git
783
+ path: ../daynights/github.com/owner/repo
784
+ ```
785
+
786
+ `copilotModel` and `copilotReasoningEffort` are independent optional fields for
787
+ all review repositories in the running process. Each configured value must be a
788
+ string containing non-whitespace text and no NUL; null and other value types are
789
+ rejected. Accepted strings are preserved exactly. Copilot owns model availability,
790
+ effort levels and model/effort compatibility; Daynight maintains no static lists.
791
+ `auto` delegates model selection to Copilot. Omitting either field sends no
792
+ corresponding override and preserves Copilot's choice, so neither, either or both
793
+ may be configured. Changes take effect on the next `review run` startup. Guided configuration
794
+ and repository registration preserve both fields and YAML comments. The server
795
+ configuration projection recognizes these shared keys without validating their
796
+ review-owned values.
797
+
798
+ `repositoryRoot` defaults to `~/daynights`. It is used only when `add-repo` has no
799
+ `--path`: the command derives filesystem-safe components from the normalized
800
+ host/owner/name and saves the resulting absolute repository path. A configured
801
+ root may be absolute, config-directory-relative, or begin with `~` for the current
802
+ OS user's home. Other users' tilde forms are rejected. Changing the root affects
803
+ future additions only. An explicit `--path` resolves against the command's working
804
+ directory and is also saved as an absolute path. Manually written repository paths
805
+ remain absolute or config-directory-relative and do not expand `~`; every repository
806
+ entry requires its own `path`.
807
+
808
+ Adding an existing normalized repository without `--path` reuses its saved path
809
+ and succeeds without rewriting configuration, even after the root changes.
810
+ An explicit path to the same actual location is also idempotent; an explicit
811
+ different path for that repository is an error.
812
+ Existing YAML settings and comments survive additions. The command validates the
813
+ complete resulting configuration before replacing the file atomically. Validation
814
+ and pre-replacement write failures preserve the original configuration; cleanup
815
+ errors after replacement remain visible. A separate
816
+ `~/.daynight/config.yml.lock` excludes another configuration writer and fails
817
+ clearly when occupied; it is independent of the review instance lock. After an
818
+ abnormal exit, confirm no configuration writer remains before removing this lock.
819
+ Configuration mutation rejects symlinks and nonregular files. A resulting
820
+ configuration containing `serverToken` uses POSIX mode `0600`; without a token,
821
+ existing file-mode behavior is preserved.
822
+
823
+ Numeric options use the documented [configuration defaults](../../docs/design/daynight-review.md#使用方式与配置)
824
+ when omitted. Explicit invalid values, unsupported fields, duplicate YAML keys and
825
+ malformed documents produce nonzero exits with useful errors. Missing configuration
826
+ triggers the [configuration setup](#configuration-setup) rules before review
827
+ startup. Duplicate repository identities,
828
+ duplicate local paths, paths overlapping the retained state directory, and paths
829
+ with an existing nondirectory component are rejected. Missing clone directories
830
+ remain valid for later repository creation. Existing paths are compared by
831
+ filesystem identity. Missing destinations with the same existing ancestor and
832
+ component count are compared by temporarily creating one candidate's directory
833
+ names inside a unique probe directory there and looking up the other spelling.
834
+ This observes actual case and Unicode rules. Validation removes only the
835
+ directories it created, using nonrecursive removal. Probe permission, inspection,
836
+ or cleanup failures stop validation with an error.
837
+
838
+ The selected retained-state location is `~/.daynight/` for SQLite, sessions,
839
+ locks, logs, cache, and temporary files. PR worktrees belong to each monitored
840
+ repository root's `.worktrees/` directory. `maxConcurrentWorker` limits concurrent
841
+ review preparation and execution. Startup acquires an exclusive instance lock,
842
+ opens SQLite and prepares the configured clones. Each repository is polled
843
+ independently; access failures retain its last complete observation and remain
844
+ visible in diagnostics. The
845
+ [repository registration decision](../../.agents/notes/implemented/feature/2026-10-18-add-repo-configuration.md)
846
+ records the fixed-path and configuration-only choices.
847
+
848
+ ## Review status listing
849
+
850
+ Print the configured repositories' locally tracked open PRs, including Draft PRs:
851
+
852
+ ```text
853
+ daynight review list
854
+ daynight review ls
855
+ ```
856
+
857
+ Both forms use the same persisted-snapshot operation and print repositories in
858
+ configuration order, with PRs ordered numerically. The columns are `PR`,
859
+ `PR STATE`, `REVIEW` and `ATTEMPTS`. Completed or failed reviews remain listed while their PR is open;
860
+ closed PRs and history belonging to removed configuration entries are omitted.
861
+
862
+ The output identifies its local snapshot source and each repository's
863
+ `Last observed` successful complete poll and saved poll error when present.
864
+ PRs at or below the permanent tracking boundary are not stored individually and
865
+ cannot appear in the listing. `No tracked ongoing PRs.` describes an initialized
866
+ repository with no saved open PRs above the boundary; `Not initialized.` describes
867
+ a missing database, an unregistered repository or an incomplete initialization.
868
+ The listing makes no claim about GitHub changes since the saved observation.
869
+
870
+ Review states are `Preparing`, `Running`, `Pending`, `Retry waiting`, `Completed`,
871
+ `Failed`, `Interrupted` and `Paused` for Draft PRs. `Running` is a saved state,
872
+ not proof that a process remains alive. Retry deadlines and saved errors appear
873
+ under the corresponding row. A newer desired revision remains `Pending` while an
874
+ older revision is active; the older revision's recorded state, attempt budget,
875
+ retry deadline and error are printed separately. The current row's attempt count
876
+ always belongs to its own desired revision, head and target branch. A base-tip
877
+ change alone does not invalidate a completed review.
878
+
879
+ Pending worktree cleanup is a separate saved resource barrier, including after a
880
+ PR reopens. Such rows show `Worktree cleanup: Pending` and any saved cleanup error.
881
+ With no current review, an open non-Draft row shows `Pending (cleanup blocked)`;
882
+ Draft remains `Paused`. Older active reviews retain their separate details. The
883
+ listing reports the barrier without attempting cleanup or recovery.
884
+
885
+ The command loads the current configuration and opens an existing SQLite database
886
+ read-only for one consistent transaction. It needs no Git, GitHub CLI or Copilot
887
+ execution, instance lock, clone or review startup. It does not create an absent
888
+ database, migrate a schema, recover interrupted work or update application state.
889
+ SQLite may create or update its WAL coordination sidecar files while reading an
890
+ existing database. Missing or invalid configuration, unreadable or corrupt state,
891
+ and unsupported schema versions fail visibly. The
892
+ [listing decision](../../.agents/notes/implemented/feature/2026-10-18-review-status-listing.md)
893
+ records status attribution and snapshot limits.
894
+
895
+ ## Durable review state
896
+
897
+ The command and source layout preserve existing YAML fields, retained-state
898
+ locations and resource identities. Runtime opening explicitly migrates earlier
899
+ SQLite state to retain verified review publications and conversation follow-ups;
900
+ existing cutoffs, revision budgets, sessions, process evidence and worktrees remain
901
+ owned by their original records. Read-only listing does not migrate state. The
902
+ review module owns its domain types independently of its SQLite implementation.
903
+
904
+ The SQLite module keeps repository identity, the permanent startup PR boundary,
905
+ observed PRs, captured review targets, completion revisions, sessions, worktree
906
+ registration, retry state, and verified GitHub review/thread identities. Repository
907
+ identity includes the GitHub host and stable repository ID. Completing a captured
908
+ revision leaves later observations pending; retries retain their original review
909
+ identity and consumed budget. Each successful comment result arms one durable
910
+ follow-up that is consumed once when conversations are resolved, even at the same
911
+ commit. A verified approval settles its current target; description edits retain
912
+ that approval. Reusing a stored approval to settle a pending target requires a
913
+ fresh snapshot confirming that exact remote review is still `APPROVED`, with the
914
+ captured actor, commit and stable identity. A dismissed historical review cannot
915
+ suppress that pending work.
916
+
917
+ Runtime database opening applies explicit schema migrations and enables WAL with
918
+ FULL synchronization and a bounded busy timeout. The listing reader checks the
919
+ existing schema, accepting versions 1 and 2 without applying migrations. The
920
+ instance lock checks whether its recorded CLI owner still exists; that check does not establish whether its agents
921
+ or tools have stopped. Interrupted reviews and pending cleanup remain blocked
922
+ after automatic lock recovery until process exclusion is explicitly confirmed.
923
+ Database state does not replace physical Git/worktree or session-history
924
+ verification.
925
+
926
+ See the [review architecture](../../docs/design/daynight-review.md) for transitions and the
927
+ [state decision](../../.agents/notes/implemented/architecture/2026-10-17-durable-review-state.md)
928
+ for persistence choices. The coordinator opens this state before scheduling work
929
+ and advances only the revision captured by each completed attempt.
930
+
931
+ ## GitHub observations
932
+
933
+ The GitHub module reads one repository pass through authenticated `gh api` GET
934
+ requests. Initialization scans every page and PR state before committing the
935
+ permanent cutoff. Later passes track open PRs, including Draft, and confirm
936
+ missing tracked PRs individually before recording closure.
937
+
938
+ Failed pages, malformed responses, and failed closure confirmations preserve
939
+ the previous repository observation. A completed pass commits its observations
940
+ and success time atomically. Rate-limit failures expose the server's retry
941
+ deadline and block later same-host calls in that client; the coordinator schedules
942
+ the next pass after the applicable deadline.
943
+ The [observation decision](../../.agents/notes/implemented/architecture/2026-10-17-github-observation.md)
944
+ records pagination and failure handling.
945
+
946
+ CI admission uses a read-only GraphQL query for the current PR head and
947
+ available test-merge commit. It combines GitHub's check/status rollups with
948
+ registered workflow suites, including approval-blocked workflows without jobs.
949
+ All reported CI must finish successfully; GitHub's `success`, `skipped` and
950
+ `neutral` outcomes pass. No CI allows immediate review. API errors and partial
951
+ results keep the PR waiting. Latest workflow runs replace historical attempts;
952
+ waiting or failing workflows do not consume review capacity.
953
+
954
+ Fresh review also requires a complete, paginated review snapshot with no unresolved
955
+ native `PullRequestReviewThread` from any author. Outdated threads still block
956
+ until resolved. Threads proven to belong to unpublished `PENDING` reviews are
957
+ excluded from this author-facing gate; unknown ownership cannot imply resolution.
958
+ Review summaries and ordinary PR comments have no resolution state. A pending round and no active or uncertain execution are also required, so
959
+ repeated passing-CI/zero-thread observations do not repeatedly review a settled
960
+ target. CI and conversation waiting consume no review Worker or model attempt.
961
+ API failure or incomplete data cannot prove that no conversations remain.
962
+
963
+ ## Repository clones and worktrees
964
+
965
+ The Git module creates missing clones and validates existing repository identity.
966
+ Prepared GitHub CLI authentication supplies command-scoped HTTPS credentials,
967
+ including repositories configured with SSH addresses or API ports. Existing
968
+ checkout files, origin configuration, branches, remote-tracking refs, and
969
+ FETCH_HEAD remain untouched by review preparation.
970
+
971
+ Configured clones and their PR worktrees are dedicated to this system. Each PR
972
+ uses its fixed repository-local `.worktrees/pr-<number>/` directory. Physical
973
+ root/common-directory checks, validated linked administration and backpointers,
974
+ and a session-labelled Git lock establish the target before destructive reuse
975
+ or removal. Initial preparation and new revisions provide a complete checkout
976
+ even when the base checkout uses sparse settings. Confirmation retries retain
977
+ local context. Files, nested clones and administration inside the owned PR
978
+ worktree are disposable; cleanup does not inventory their external consumers.
979
+ Other PR worktrees and retained sessions remain separate. Cleanup rechecks remote
980
+ closure before removal. The [exclusive-environment decision](../../.agents/notes/implemented/architecture/2026-10-17-exclusive-review-environment.md)
981
+ defines this ownership boundary.
982
+
983
+ See the [worktree ownership decision](../../.agents/notes/implemented/architecture/2026-10-17-owned-review-worktrees.md)
984
+ for target validation and recovery boundaries.
985
+
986
+ ## Copilot execution
987
+
988
+ The review module ships `daynight-review` under its own `skills/` directory.
989
+ After taking the instance lock, the daemon captures the installed bundle once
990
+ and prepares an immutable content-addressed snapshot under
991
+ `~/.daynight/cache/review-skills/`. Package updates cannot replace the content
992
+ used by that running daemon. Snapshots remain available for retained sessions
993
+ and uncertain executions; automatic collection is not provided.
994
+
995
+ Each attempt first runs native Copilot skill discovery in the prepared PR
996
+ worktree. A single `--plugin-dir=<snapshot root>` argument supplies a generated
997
+ local plugin wrapper containing `plugin.json` and `skills/daynight-review/`.
998
+ This preserves paths containing commas, spaces and Unicode; inherited
999
+ `COPILOT_SKILLS_DIRS` variables are removed from the child environment.
1000
+ Exactly one enabled `daynight-review` must resolve to that snapshot's directory;
1001
+ a disabled skill, project override or malformed response fails the attempt.
1002
+ The review prompt explicitly invokes the skill and identifies its current
1003
+ absolute entrypoint and digest on both new sessions and resume. The bundled
1004
+ skill owns review methodology; the prompt owns the immutable target, publication
1005
+ eligibility, retry reconciliation and completion protocol. The prompt also
1006
+ explicitly requests the skill's native subagent delegation and synthesis when
1007
+ fresh review is required; confirming a valid matching submitted result retains
1008
+ its reconciliation exception.
1009
+
1010
+ The Copilot adapter then launches the review child in that same worktree and
1011
+ environment. It selects the persisted per-PR UUID on first launch and explicitly resumes that
1012
+ same session thereafter. An interrupted first launch also resumes existing
1013
+ history; missing established history is an error. Only opaque session-directory
1014
+ presence is inspected. Copilot history and agent JSONL are not parsed.
1015
+
1016
+ Every review child receives configured `copilotModel` as separate `--model` and
1017
+ value arguments, and configured `copilotReasoningEffort` as separate
1018
+ `--reasoning-effort` and value arguments. New sessions, resumes, retries and later
1019
+ PR revisions use the same construction. Skill discovery receives neither override.
1020
+ Values pass through the existing `shell: false` execution path; unsupported or
1021
+ unavailable models, effort levels or combinations retain Copilot's normal failure
1022
+ result and the existing attempt/error handling. The
1023
+ [model options decision](../../.agents/notes/implemented/feature/2026-10-22-review-copilot-model.md)
1024
+ records the validation and default-selection choices.
1025
+
1026
+ Prompts travel through stdin in noninteractive mode. `cross-spawn` handles native
1027
+ commands and Windows command shims; prompt text is not embedded in shell code or
1028
+ command arguments. Runtime paths contain Copilot state, cache, temporary files
1029
+ and per-attempt diagnostics. Existing GitHub CLI authentication remains available
1030
+ through Copilot's supported fallback. Discovery and review are sequential phases
1031
+ of one persisted attempt, sharing one retry budget and timeout deadline. The
1032
+ discovery child must be excluded before its exact persisted PID and identity are
1033
+ cleared and a review child can start. Cancellation, timeout or uncertain process
1034
+ exclusion prevents that next launch. Discovery stdout and stderr stream to
1035
+ separate `skill-list` logs and never enter completion-marker parsing.
1036
+
1037
+ The agent reads the current PR title, description and linked scope requirements,
1038
+ then checks the complete captured diff against one concrete problem and outcome.
1039
+ A clear description and changes within the original scope are independent
1040
+ approval gates. Independent objectives, an unreviewable combined PR or unrelated
1041
+ changes block approval even without a Critical/Major code defect. Necessary
1042
+ implementation, structural changes, tests and documentation for the same outcome
1043
+ remain in scope; fixed line or file counts do not decide reviewability. Expanding
1044
+ the description alone cannot justify unrelated work.
1045
+
1046
+ For every fresh review, the main agent first inspects that complete fixed diff,
1047
+ then chooses at least two complementary perspectives based on the PR's actual
1048
+ changes, contracts and risks. It invokes independent subagents, preferably in
1049
+ parallel, with exact head/base/merge-base context, scope, applicable repository
1050
+ instructions, evidence standards and shared worktree, temporary-file and process
1051
+ rules. Source and Git state remain read-only; subagents return findings and
1052
+ coverage limits to the main agent without publishing or emitting completion
1053
+ markers. The main agent waits for all required perspectives, verifies candidates,
1054
+ resolves disagreements and deduplicates root causes. It records the perspective
1055
+ rationale, completed coverage, limits, fix/defer/reject dispositions and confirmed
1056
+ blockers in attempt output, while GitHub comments contain concise findings only.
1057
+ An unavailable tool, failed child or incomplete required perspective is an
1058
+ operational failure; retries or reassignment stay within the attempt's existing
1059
+ budget. An incomplete review publishes neither a result nor a completion marker.
1060
+
1061
+ These subagents belong to one attempt within the daemon-managed main review
1062
+ session; they do not create more review Workers, PR sessions or worktrees.
1063
+ Reconciliation of a valid matching submitted result confirms that result without
1064
+ repeating delegation. The selected questions must fit each PR, including
1065
+ documentation-only changes.
1066
+
1067
+ Before new publication, the agent rereads the current PR information and
1068
+ reevaluates those gates. A successful review either approves or publishes
1069
+ `COMMENT` with at least one actual resolvable review thread. Suitable code findings
1070
+ use diff lines. Description and other PR-level blockers use a clearly labeled
1071
+ file-level conversation on the principal changed file; a review summary alone
1072
+ cannot satisfy this requirement. `REQUEST_CHANGES` remains unused. The reviewer
1073
+ must verify corrections after authors resolve feedback; resolution is a request
1074
+ for rereview, not evidence that the issue was fixed. Operational failures retain
1075
+ bounded retries and cannot be represented as quality findings.
1076
+
1077
+ The daemon verifies remote publication using its stable review identity, captured
1078
+ commit and publishing actor, without interpreting the quality judgment or parsing
1079
+ findings. Marker acceptance is persisted before this read-only verification; API
1080
+ errors retry verification across restart without another model attempt. A complete
1081
+ lookup with no valid matching publication is a protocol failure and uses the
1082
+ remaining bounded model retry budget. A verified `COMMENT` records its real
1083
+ review/thread IDs and arms exactly one follow-up. Once
1084
+ all submitted native conversations are resolved and the current CI passes, that follow-up
1085
+ runs even without new commits or metadata edits. New targets and feedback wakeups
1086
+ coalesce. Same-round confirmation can proceed through open conversations only
1087
+ when exact-round remote evidence proves an approval, commented review with owned
1088
+ threads, or a recoverable matching pending draft under the captured publisher. A
1089
+ failed attempt alone supplies no exemption. If the authenticated reader changes,
1090
+ it can confirm the captured actor's submitted result; an unpublished result or
1091
+ pending draft waits for that actor without consuming model attempts. Verified
1092
+ approval settles the current target, and
1093
+ description edits do not revoke it or start another round.
1094
+
1095
+ The adapter streams separate stdout/stderr logs and accepts only normal zero
1096
+ exit, complete capture and the exact final nonempty stdout line
1097
+ `PR N Review Completed`. Incomplete output, timeout, cancellation and logging
1098
+ errors cannot assert execution completion. A marker alone is insufficient: the
1099
+ coordinator verifies the corresponding remote approval or resolvable feedback
1100
+ before completing the round. It owns scheduling and final state transitions;
1101
+ runtime process supervision supplies evidence under the foreground execution
1102
+ contract.
1103
+
1104
+ The [execution decision](../../.agents/notes/implemented/architecture/2026-10-17-copilot-session-execution.md)
1105
+ records process and publication boundaries; the
1106
+ [PR-quality decision](../../.agents/notes/implemented/process/2026-10-21-review-pr-quality-gates.md)
1107
+ records the approval policy, and the
1108
+ [multi-perspective decision](../../.agents/notes/implemented/process/2026-10-22-pr-specific-review-perspectives.md)
1109
+ records delegation and synthesis. The
1110
+ [conversation-cycle decision](../../.agents/notes/implemented/architecture/2026-10-21-review-conversation-cycle.md)
1111
+ records durable follow-ups and publication verification. The
1112
+ [skill design](../../docs/design/daynight-review-skill.md) owns packaging, snapshots and
1113
+ loading, with rationale in the
1114
+ [bundled-skill decision](../../.agents/notes/implemented/architecture/2026-10-20-bundled-review-skill.md).
1115
+ Native probes with Copilot CLI 1.0.100 verify actual bundled-skill activation and
1116
+ changed-bundle resume with the same UUID, including comma, space and Unicode
1117
+ paths. The bundled-skill decision records the probe's conditions and limits.
1118
+ Live Copilot/GitHub publication acceptance
1119
+ remains separate from those probes and controlled subprocess tests.
1120
+
1121
+ ## Coordination and shutdown
1122
+
1123
+ A FIFO pending queue coalesces observations for each PR while preventing a
1124
+ frequently updated PR from starving other repositories or PRs. One reservation
1125
+ spans preparation, execution and cleanup for each PR. Fresh-round CI and
1126
+ conversation admission precedes that reservation and is refreshed at
1127
+ `pollIntervalMs`; waiting candidates retain their queue position without blocking
1128
+ ready PRs. Admission evidence is kept in memory for the exact revision, head and
1129
+ base branch and is refreshed after restart. New review launches recheck PR state,
1130
+ CI and conversations after worktree preparation. Same-round reconciliation can
1131
+ confirm proven exact-round publication while its own feedback remains open;
1132
+ matching pending drafts require the captured publishing actor. An unsuccessful
1133
+ attempt without publication still waits for unrelated open conversations. A regression
1134
+ defers fresh preparation without consuming an attempt or losing the retained
1135
+ session. CI changes alone do not retrigger completed revisions.
1136
+ Readiness is a launch-time observation; later CI registration or reruns do not
1137
+ automatically cancel an active agent.
1138
+
1139
+ Cleanup does not consume a review worker slot, but cannot overlap another
1140
+ operation on the same worktree. Draft/closure observations cancel active work; head changes wait for the current
1141
+ attempt and remain pending. Failed revisions retain their exhausted budget.
1142
+
1143
+ Ctrl+C stops new work and polling, terminates current managed execution, waits
1144
+ for operations and closes SQLite before releasing the instance lock. Agents must
1145
+ run tools in the foreground and stop their services before returning. Normal
1146
+ unforced exit and drained streams are evidence under that contract. POSIX uses
1147
+ current process groups; Windows cancels live trees with `taskkill /T /F`.
1148
+ Uncertain termination retains the lock and interrupted state.
1149
+
1150
+ Startup checks the PID in an existing `~/.daynight/instance.lock` with a
1151
+ signal-zero probe. A live owner, permission denial, invalid lock metadata or an
1152
+ unclassified probe error preserves the lock and stops startup. Only an explicit
1153
+ no-such-process result permits automatic replacement of a dead owner's lock.
1154
+ Competing starts and releases serialize through `instance.lock.sqlite`; this
1155
+ guard database remains in place and must not be deleted while a CLI can use it.
1156
+ Lock age never establishes that an owner has stopped. PID reuse conservatively
1157
+ blocks startup until the recorded owner can be inspected.
1158
+
1159
+ A crash with no unresolved review or cleanup can therefore restart directly.
1160
+ When interrupted reviews exist, automatic lock recovery blocks their PRs.
1161
+ Pending cleanup remains recorded with its error even if the PR reopens; only
1162
+ conclusively stopped cleanup operations and excluded agents allow that state to
1163
+ clear. Automatic recovery blocks only each affected PR's cleanup and reuse;
1164
+ polling and other PRs in the same repository continue normally, as do other
1165
+ repositories. Uncertain
1166
+ resources retain the lock on shutdown. After stopping the daemon, confirm that
1167
+ the previous CLI and all its agents/tools have stopped, then remove only
1168
+ `instance.lock` and restart. Keep `instance.lock.sqlite`, SQLite state, sessions
1169
+ and logs. That explicitly confirmed restart reconciles interrupted work with
1170
+ the same captured target and session; it never declares a saved running attempt
1171
+ complete or kills a saved process ID.
1172
+
1173
+ The [coordination decision](../../.agents/notes/implemented/architecture/2026-10-17-foreground-review-coordination.md)
1174
+ explains scheduling and the foreground execution boundary. The
1175
+ [stale-lock recovery decision](../../.agents/notes/implemented/bug-fix/2026-10-18-stale-instance-lock-recovery.md)
1176
+ records owner-liveness checks and the separate process-exclusion requirement.