@codetreker/daynight 0.21.9 → 0.21.13

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 (85) hide show
  1. package/README.md +359 -27
  2. package/dist/api/client.d.ts +4 -1
  3. package/dist/api/client.js +18 -1
  4. package/dist/api/client.js.map +1 -1
  5. package/dist/api/parse.d.ts +3 -1
  6. package/dist/api/parse.js +27 -0
  7. package/dist/api/parse.js.map +1 -1
  8. package/dist/api/types.d.ts +18 -3
  9. package/dist/cli/commands.js +2 -0
  10. package/dist/cli/commands.js.map +1 -1
  11. package/dist/commands/skill/skills/using-daynight/references/handoff.md +3 -3
  12. package/dist/commands/worker/cleanup.d.ts +6 -0
  13. package/dist/commands/worker/cleanup.js +173 -0
  14. package/dist/commands/worker/cleanup.js.map +1 -0
  15. package/dist/commands/worker/config.d.ts +21 -0
  16. package/dist/commands/worker/config.js +144 -0
  17. package/dist/commands/worker/config.js.map +1 -0
  18. package/dist/commands/worker/control.d.ts +55 -0
  19. package/dist/commands/worker/control.js +151 -0
  20. package/dist/commands/worker/control.js.map +1 -0
  21. package/dist/commands/worker/coordinator.d.ts +35 -0
  22. package/dist/commands/worker/coordinator.js +548 -0
  23. package/dist/commands/worker/coordinator.js.map +1 -0
  24. package/dist/commands/worker/definition.d.ts +2 -0
  25. package/dist/commands/worker/definition.js +50 -0
  26. package/dist/commands/worker/definition.js.map +1 -0
  27. package/dist/commands/worker/diagnostics.d.ts +20 -0
  28. package/dist/commands/worker/diagnostics.js +56 -0
  29. package/dist/commands/worker/diagnostics.js.map +1 -0
  30. package/dist/commands/worker/execution.d.ts +41 -0
  31. package/dist/commands/worker/execution.js +318 -0
  32. package/dist/commands/worker/execution.js.map +1 -0
  33. package/dist/commands/worker/herdr/agents.d.ts +186 -0
  34. package/dist/commands/worker/herdr/agents.js +726 -0
  35. package/dist/commands/worker/herdr/agents.js.map +1 -0
  36. package/dist/commands/worker/herdr/arguments.d.ts +8 -0
  37. package/dist/commands/worker/herdr/arguments.js +58 -0
  38. package/dist/commands/worker/herdr/arguments.js.map +1 -0
  39. package/dist/commands/worker/herdr/codex-input.d.ts +2 -0
  40. package/dist/commands/worker/herdr/codex-input.js +35 -0
  41. package/dist/commands/worker/herdr/codex-input.js.map +1 -0
  42. package/dist/commands/worker/herdr/command.d.ts +22 -0
  43. package/dist/commands/worker/herdr/command.js +115 -0
  44. package/dist/commands/worker/herdr/command.js.map +1 -0
  45. package/dist/commands/worker/herdr/instance.d.ts +56 -0
  46. package/dist/commands/worker/herdr/instance.js +322 -0
  47. package/dist/commands/worker/herdr/instance.js.map +1 -0
  48. package/dist/commands/worker/herdr/preflight.d.ts +40 -0
  49. package/dist/commands/worker/herdr/preflight.js +251 -0
  50. package/dist/commands/worker/herdr/preflight.js.map +1 -0
  51. package/dist/commands/worker/herdr/rpc.d.ts +29 -0
  52. package/dist/commands/worker/herdr/rpc.js +186 -0
  53. package/dist/commands/worker/herdr/rpc.js.map +1 -0
  54. package/dist/commands/worker/herdr.d.ts +95 -0
  55. package/dist/commands/worker/herdr.js +35 -0
  56. package/dist/commands/worker/herdr.js.map +1 -0
  57. package/dist/commands/worker/index.d.ts +18 -0
  58. package/dist/commands/worker/index.js +58 -0
  59. package/dist/commands/worker/index.js.map +1 -0
  60. package/dist/commands/worker/instance-lock.d.ts +5 -0
  61. package/dist/commands/worker/instance-lock.js +11 -1
  62. package/dist/commands/worker/instance-lock.js.map +1 -1
  63. package/dist/commands/worker/prompts.d.ts +4 -0
  64. package/dist/commands/worker/prompts.js +64 -0
  65. package/dist/commands/worker/prompts.js.map +1 -0
  66. package/dist/commands/worker/remote.d.ts +23 -0
  67. package/dist/commands/worker/remote.js +146 -0
  68. package/dist/commands/worker/remote.js.map +1 -0
  69. package/dist/commands/worker/runtime.d.ts +16 -0
  70. package/dist/commands/worker/runtime.js +384 -0
  71. package/dist/commands/worker/runtime.js.map +1 -0
  72. package/dist/commands/worker/store.d.ts +73 -5
  73. package/dist/commands/worker/store.js +475 -36
  74. package/dist/commands/worker/store.js.map +1 -1
  75. package/dist/commands/worker/types.d.ts +37 -1
  76. package/dist/commands/worker/worktrees.d.ts +1 -0
  77. package/dist/commands/worker/worktrees.js +9 -0
  78. package/dist/commands/worker/worktrees.js.map +1 -1
  79. package/dist/config/document.d.ts +1 -1
  80. package/dist/config/document.js +1 -0
  81. package/dist/config/document.js.map +1 -1
  82. package/dist/platform/instance-lock.d.ts +4 -0
  83. package/dist/platform/instance-lock.js +9 -1
  84. package/dist/platform/instance-lock.js.map +1 -1
  85. package/package.json +2 -2
package/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  The `@codetreker/daynight` package provides the `daynight` command and its `dn`
4
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.
5
+ the `using-daynight` skill for coding agents, run foreground task workers through
6
+ Herdr, and run a local GitHub PR reviewer through Copilot CLI. Both command names
7
+ share configuration and behavior.
7
8
 
8
9
  See the [project overview](../../README.md) for the browser workspace and service,
9
10
  and the [development guide](../../docs/development.md) for source builds,
@@ -20,6 +21,8 @@ GitHub CLI and Copilot CLI on `PATH`.
20
21
  - [Task management](#task-management)
21
22
  - [Task deletion](#task-deletion)
22
23
  - [Task attachments](#task-attachments)
24
+ - [Worker configuration and startup](#worker-configuration-and-startup)
25
+ - [Worker manual management](#worker-manual-management)
23
26
  - [Review configuration and startup](#review-configuration-and-startup)
24
27
  - [Review status listing](#review-status-listing)
25
28
  - [Durable review state](#durable-review-state)
@@ -78,11 +81,11 @@ its agents, scope, path and package version. A skill failure exits nonzero and
78
81
  reports the package outcome separately; a successfully installed npm package is
79
82
  retained, and rerunning `update` retries the skill refresh. All phases must
80
83
  succeed before the command reports success. It requires no review configuration and does
81
- not open SQLite, modify sessions or restart a running reviewer. The next CLI
82
- invocation uses the installed version. Restart any running reviewer to use it;
83
- on Windows, a reviewer holding a native addon open can prevent npm from replacing
84
+ not open SQLite, modify sessions or restart a running reviewer or worker. The next CLI
85
+ invocation uses the installed version. Restart any running reviewer or worker to use it;
86
+ on Windows, a reviewer or worker holding a native addon open can prevent npm from replacing
84
87
  that file and cause the update to fail. The
85
- [self-update decision](../../.agents/notes/implemented/feature/2026-10-20-cli-self-update.md)
88
+ [self-update decision](../../.agents/notes/archived/feature/2026-10-20-cli-self-update.md)
86
89
  records installation ownership and verification requirements.
87
90
 
88
91
  ## Client commands
@@ -94,6 +97,12 @@ daynight --version # Also -v
94
97
  daynight update
95
98
  daynight login [--no-browser] # Authorize CLI access through the browser
96
99
  daynight logout # Revoke and remove the current CLI credential
100
+ daynight worker # Show worker help
101
+ daynight worker run # Run until interrupted
102
+ daynight worker retry <task-id> --claim-id <claim-id> [--project <project-id>]
103
+ daynight worker release <task-id> --claim-id <claim-id> --if-version <version> [--project <project-id>]
104
+ daynight worker resume <task-id> --claim-id <previous-claim-id> --if-version <version> [--project <project-id>]
105
+ daynight worker transfer <task-id> --claim-id <claim-id> --if-version <version> [target options] [--project <project-id>]
97
106
  daynight review # Show review help
98
107
  daynight review run
99
108
  daynight review list # Also review ls
@@ -132,7 +141,7 @@ Unknown commands and invalid arguments exit with status 2; operation failures
132
141
  exit with status 1 and retain their cause. The old `--daemon-review` and root
133
142
  `add-repo` forms are invalid. The
134
143
  [client design](../../docs/design/daynight.md) owns command composition and lazy loading;
135
- the [composition decision](../../.agents/notes/implemented/architecture/2026-10-20-client-command-composition.md)
144
+ the [composition decision](../../.agents/notes/archived/architecture/2026-10-20-client-command-composition.md)
136
145
  records module ownership and the preserved data layout.
137
146
 
138
147
  ## Agent skill installation
@@ -144,7 +153,8 @@ prompt explicitly names the `worker-managed` environment, the `using-daynight`
144
153
  skill and that mode, together with their assignment. `SKILL.md` routes to the
145
154
  selected instructions; ordinary execution does not load managed task rules.
146
155
  Shared task inputs, delivery and acceptance rules retain one owner in the bundle.
147
- The worker runtime remains under development.
156
+ The [foreground worker](#worker-configuration-and-startup) constructs that
157
+ explicit assignment and loads the installed managed entry before launch.
148
158
 
149
159
  Install the skill through an interactive terminal:
150
160
 
@@ -293,9 +303,9 @@ update, run the applicable `source` command again to refresh an existing shell.
293
303
  A saved generated script must be regenerated after updating. The
294
304
  [completion design](../../docs/design/daynight-completion.md) explains the shared grammar
295
305
  and shell integration. The
296
- [completion decision](../../.agents/notes/implemented/feature/2026-10-20-shell-completion.md)
306
+ [completion decision](../../.agents/notes/archived/feature/2026-10-20-shell-completion.md)
297
307
  records compatibility and execution trade-offs; the
298
- [setup decision](../../.agents/notes/implemented/feature/2026-10-21-completion-setup.md)
308
+ [setup decision](../../.agents/notes/archived/feature/2026-10-21-completion-setup.md)
299
309
  records startup-file ownership and installation limits.
300
310
 
301
311
  ## Configuration setup
@@ -382,8 +392,8 @@ business execution. Human input consumes no business timeout. Review guidance
382
392
  saves configuration without network, login or authentication checks; cloning and
383
393
  review state initialization belong to the business operation.
384
394
 
385
- The [configuration decision](../../.agents/notes/implemented/feature/2026-10-21-guided-configuration-setup.md)
386
- owns review guidance and persistence; the
395
+ The [configuration decision](../../.agents/notes/archived/feature/2026-10-21-guided-configuration-setup.md)
396
+ records the review-guidance and persistence choices; the
387
397
  [device-login decision](../../.agents/notes/implemented/architecture/2026-10-25-cli-device-login.md)
388
398
  owns the default service, explicit login/logout and credential lifecycle. The
389
399
  [top-level setup removal decision](../../.agents/notes/implemented/simplification/2026-10-25-remove-top-level-setup.md)
@@ -744,9 +754,329 @@ known issue and the trusted same-origin preview model. The
744
754
  [authentication architecture](../../docs/design/daynight-auth.md) defines the required
745
755
  authentication and project-membership checks for attachment requests. Trusted
746
756
  executable HTML retains the application origin. The
747
- [CLI delivery decision](../../.agents/notes/implemented/feature/2026-10-21-task-attachment-cli.md)
757
+ [CLI delivery decision](../../.agents/notes/archived/feature/2026-10-21-task-attachment-cli.md)
748
758
  records binary transport and output ownership.
749
759
 
760
+ ## Worker configuration and startup
761
+
762
+ `daynight worker run` is a foreground process that claims eligible ready tasks
763
+ across configured repositories and runs Copilot or Codex in a dedicated Herdr
764
+ instance. The agent owns task delivery, acceptance, evidence and final
765
+ claim-bound completion. The worker owns concurrency, resources, recovery and
766
+ cleanup based on its current claim inventory.
767
+
768
+ Install Git, Herdr 0.9.5 or newer with protocol 22 capabilities, and the selected
769
+ native agent on PATH. Native/provider authentication and the current official
770
+ Herdr SessionStart integration must be configured explicitly. Codex needs the
771
+ hooks feature and `--no-daemon`; Unix hook scripts need bash and python3, while
772
+ Windows hooks need PowerShell. The worker reports missing capabilities or
773
+ integration/history instead of installing or changing global native settings.
774
+ Git transport and tools used by the task, such as authenticated GitHub CLI for
775
+ PR delivery, must also be ready.
776
+
777
+ Run `daynight login` for Daynight authentication. Add the following mapping to
778
+ the shared `~/.daynight/config.yml`, preserving existing connection and review
779
+ settings:
780
+
781
+ ```yaml
782
+ worker:
783
+ maxConcurrent: 1
784
+ pollIntervalMs: 5000
785
+ recoveryLimit: 3
786
+ agent: copilot
787
+ model: null
788
+ args: []
789
+ repositories:
790
+ - remote: https://github.com/OWNER/REPO.git
791
+ path: ../code/repo
792
+ - remote: https://github.com/OWNER/OTHER.git
793
+ path: ../code/other
794
+ agent: codex
795
+ model: null
796
+ args: []
797
+ ```
798
+
799
+ These are the defaults for all optional worker fields; `repositories` is
800
+ required. Each entry requires `remote` and `path`, with optional `projectId`,
801
+ `agent`, `model` and `args`. The service project must already exist and match the
802
+ repository. Add `projectId` when more than one project matches. Missing local
803
+ repositories are cloned; existing roots and origins are verified without
804
+ resetting their files or branches. Use the native authentication configuration
805
+ for credentials, keeping credentials out of repository URLs and argument lists.
806
+
807
+ Paths are absolute or relative to the configuration file's directory, never
808
+ the launch directory. Tilde expansion and drive-relative Windows paths are
809
+ rejected. Repository identities, project IDs and paths cannot duplicate or
810
+ overlap, including the fixed Daynight state directory. Unknown worker fields,
811
+ wrong types, invalid arguments and unsupported path shapes fail visibly.
812
+ `maxConcurrent` is a positive integer, `recoveryLimit` is nonnegative and
813
+ `pollIntervalMs` is a positive safe integer within the timer range.
814
+
815
+ Repository agent settings override fields independently when the type stays
816
+ the same; explicit null model or an empty args list clears that field. Switching
817
+ agent type clears inherited model and arguments unless the repository explicitly
818
+ sets them. Args replace the list rather than append. The recovery limit is
819
+ worker-wide. Configuration loads at startup, without hot reload; existing claims
820
+ keep their original frozen configuration after a restart, while later claims
821
+ use the newly loaded settings.
822
+
823
+ New tasks have automatic execution disabled. Enable it explicitly with the
824
+ normal task update workflow after reading the current task/version. The worker
825
+ selects only ready, permitted tasks compatible with its actual platform; WSL
826
+ counts as Linux. It never enables that permission itself. Released tasks wait
827
+ for explicit management and do not immediately re-enter ordinary automatic
828
+ acquisition. Run the worker with:
829
+
830
+ ```bash
831
+ daynight worker run
832
+ ```
833
+
834
+ The command generates and atomically saves a stable root `workerId` on first
835
+ use. One foreground instance owns fixed `~/.daynight/worker/` state: its SQLite,
836
+ instance lock, logs, temporary resources and private Herdr data. There is no
837
+ state-path override. Each task uses `daynight/<task-id>` and
838
+ `<repository>/.worktrees/daynight/<task-id>`. The same valid claim retains dirty
839
+ work, native history and configuration; a new claim has a fresh execution
840
+ identity and conversation.
841
+
842
+ The worker verifies the startup credential through the existing current-user
843
+ API and pins successful response identity, including empty pages. Each local
844
+ claim retains its original Daynight user ID. If another account is logged in on
845
+ the same OS account, the stable workerId stays the same, but that account's empty
846
+ inventory cannot terminate or resume the previous account's work. Scope-paused
847
+ records need the original account/identity inspected; do not remove local state
848
+ or regenerate workerId to make the mismatch disappear. The running process
849
+ keeps its startup credential; restart after an intended account change.
850
+
851
+ Changing serverUrl also separates local responsibility from remote work. The
852
+ worker queries and acquires only on its current service. Previously committed
853
+ cleanup deadlines and normal shutdown cover that worker's local records across
854
+ all original services, without calling an old API or asking the new service
855
+ about old records. A newly granted current-service claim freezes its new
856
+ configuration and waits pending behind any active predecessor with the same task UUID for that
857
+ worker, including another origin. Read-only Git ownership attributes
858
+ an occupied canonical path; it does not adopt the old conversation or config.
859
+
860
+ The foreground stderr output and JSONL logs identify project/task/claim, platform,
861
+ waiting, pause and cleanup errors. The log path is printed at startup. An
862
+ unconfirmed claim request, native launch or input is retained for observation;
863
+ it is not replayed. A pause still reserves capacity. Recovering missing original
864
+ configuration, history or stop evidence requires inspection, without creating a
865
+ replacement conversation to conceal the loss.
866
+
867
+ For human input, copy the safe `attach` descriptor printed after the running
868
+ worker has completed inventory and private managed-instance readiness.
869
+ Invoke its `executable` with its `arguments` (`herdr --session w` for the default
870
+ executable), apply exactly its `environment` overrides and remove the names in
871
+ `unsetEnvironment` **only for that attach client process**. The descriptor's
872
+ private XDG values select the worker's exact Herdr instance; the existing task
873
+ pane keeps its original native XDG and private HISTFILE. The descriptor contains
874
+ routing and native-home paths, not a dump of authentication values. Continue in
875
+ the original task pane so the worker can observe the same execution.
876
+
877
+ Native startup can be waiting at a folder-trust or authorization screen even
878
+ when Herdr reports idle/interactiveReady. The worker checks the current Codex
879
+ input surface before automatic text and Enter, reports a blocking reason and
880
+ keeps the first prompt unsent. It does not choose native trust or change global
881
+ trust configuration. Configure that prerequisite normally in the native tool or
882
+ use the original attached task pane to make the decision explicitly, then leave
883
+ the business composer available for input. This check does not inspect arbitrary
884
+ human draft meaning or prove that a model consumed previously submitted text.
885
+
886
+ The checked Codex startup/restart layout is the standard/default business
887
+ composer together with a loaded model/reasoning and current-directory footer
888
+ (`model-with-reasoning · current-dir`). Ask text or a version header alone is
889
+ insufficient because provisional startup can show them too. A custom footer,
890
+ cropped footer or otherwise unrecognized visible layout remains unknown; the
891
+ original Operation bounds observation and ends not-submitted if that supported
892
+ surface never appears. In the original session, finish any blocking decision
893
+ and restore the supported standard native layout before requesting public retry.
894
+ The worker does not change the layout, infer arbitrary draft meaning or turn
895
+ this screen check into a native consumption receipt.
896
+
897
+ For started executions, a successful complete own-claim inventory from the
898
+ original account makes the original claim's absence cause
899
+ the same terminal cleanup for done, release and transfer: request attributable
900
+ outside-worktree cleanup for at most the original ten-minute deadline, confirm
901
+ the original agent stopped, close its workspace, delete its worktree and retain
902
+ local history. Failures keep responsibility and resume cleanup after restart.
903
+ A failed, incomplete or differently scoped inventory cannot authorize a new
904
+ terminal-cleanup decision. Already persisted cleanup/control intents continue in
905
+ the same foreground process through a lightweight discovery loop and one
906
+ transient asynchronous job per full claim, before current-user/project network
907
+ requests and even during server read failures. Only already authorized intents
908
+ with known original account scope advance; unknown-scope terminal/control
909
+ intents remain preserved. Each job waits at most one second or its nearer
910
+ original deadline, independently of pollIntervalMs. One task's held RPC does not
911
+ postpone another task's next cleanup advance; per-task serialization still
912
+ prevents overlapping operations on the same execution. There is no persisted job
913
+ queue.
914
+
915
+ Ctrl+C stops acquisition and ordinary input, cancels and joins the ordinary
916
+ cleanup discovery loop and all per-claim jobs, then runs original-task shutdown
917
+ with a separate bounded cancellation scope and a shared exit deadline.
918
+ Unfinished claims, worktrees and native history remain; the private instance
919
+ stops only after original agents are confirmed stopped. Stop uncertainty is
920
+ reported and retains the instance/resources for inspection. Restart the command
921
+ to reconcile with the same worker identity and original state. After consuming
922
+ interrupted shutdown, the worker refreshes Herdr resources before ordinary
923
+ execution. If a native launch may have occurred but its exact original session
924
+ ID is missing, shutdown preserves its old binding, launch and PID evidence and
925
+ pauses; it does not turn that execution into a first launch. Proven
926
+ never-started work and executions with a known original native ID retain their
927
+ normal recovery path.
928
+
929
+ A causal worker cancellation propagates into shutdown without adding a fault
930
+ pause. Existing real pauses, recovery budget and unknown-action records keep
931
+ their meaning; an unrelated error is not normal cancellation merely because the
932
+ signal is already aborted. Read-only interruption followed by successful
933
+ shutdown can resume the original session through the normal recovery path.
934
+
935
+ Pending successors whose resources, workspace and native launch are proven
936
+ never started stay pending on normal exit. A successful complete inventory from
937
+ the same original account can complete an absent unstarted claim directly,
938
+ without activating it or touching an older claim's fixed Git path. Other tasks'
939
+ shutdown initialization is isolated so one bad record does not prevent known
940
+ agents stopping. Untracked resources or unknown scope keep the private instance
941
+ when its stop cannot be confirmed.
942
+
943
+ Linux, Windows and macOS complete Goal acceptance is separate from the installed
944
+ runtime and its component checks. The
945
+ [worker requirements](../../docs/spec/daynight-worker.md) and
946
+ [worker design](../../docs/design/daynight-worker.md) own the behavior and
947
+ mechanisms, including native capability limits.
948
+
949
+ ## Worker manual management
950
+
951
+ Manual commands select one task and its exact original claim. They use the same
952
+ fixed SQLite and singleton lock as `worker run`. With a foreground worker, that
953
+ process remains the sole agent controller and consumes the persisted decision;
954
+ without one, the command acquires the same lock and advances the same coordinator
955
+ for that execution. There is no separate control service. Current configuration
956
+ and Daynight authentication are required, and the original service origin must
957
+ match. Release, transfer and retry require the unfinished original local record;
958
+ resume can use an explicit project with its configured repository.
959
+
960
+ Read the current task before deciding a versioned operation:
961
+
962
+ ```bash
963
+ daynight task show <task-id> --json
964
+ daynight worker release <task-id> --claim-id <source-claim-id> --if-version <version>
965
+ ```
966
+
967
+ Release and transfer first verify project access and source owner/admin
968
+ permission, then persist the concrete source decision before cleanup. The
969
+ controller requests the original agent's attributable temporary-resource cleanup,
970
+ waits for its original deadline of at most 10 minutes, confirms that agent stopped,
971
+ closes its task workspace and deletes its worktree. Only then can it submit the
972
+ remote write at the exact supplied version. Other tasks keep their shared Herdr
973
+ instance. Failed stopping or deletion retains the source responsibility and a
974
+ visible error. Cleanup keeps its original deadline after restart; each HTTP
975
+ request has an independent bounded scope, without a five-minute total command
976
+ limit.
977
+
978
+ Release returns the task to `todo` and clears its execution interval. The daemon
979
+ skips released tasks until explicitly resumed. Resume starts a fresh execution
980
+ on this worker:
981
+
982
+ ```bash
983
+ daynight worker resume <task-id> --claim-id <released-claim-id> --if-version <version> \
984
+ --project <project-id>
985
+ ```
986
+
987
+ The previous claim must still be released and the task ready. The original owner
988
+ or a current project admin may resume it, retaining the explicit manual exception
989
+ to automatic permission and platform filters. The new claim and worktree IDs are
990
+ generated and persisted before submission. Its actual grant commits local
991
+ `pending` with this repository's current effective agent/model/args; `worker run`
992
+ then performs ordinary capacity checks and prepares a fresh native conversation.
993
+ The deleted source worktree and native history are not required. Run
994
+ `daynight worker run` if the foreground worker is stopped.
995
+
996
+ Transfer explicitly identifies the target's current user, stable worker and
997
+ machine descriptor, actual platform and selected agent:
998
+
999
+ ```bash
1000
+ daynight worker transfer <task-id> --claim-id <source-claim-id> --if-version <version> \
1001
+ --target-user-id <user-id> --target-worker-id <worker-id> \
1002
+ --target-machine-id <machine-id> --target-machine-name "target-machine" \
1003
+ --target-platform linux --target-agent codex
1004
+ ```
1005
+
1006
+ Use the intended receiver's actual descriptor and the explicitly selected new
1007
+ agent type. A trace-free new transfer grant honors that agent even when the
1008
+ receiver's current repository defaults select the other type. It freezes
1009
+ `model: null` and `args: []` for that type, with the current recovery limit; a
1010
+ matching type uses the current effective model/args. Existing pending snapshots
1011
+ are retained. The source operator's owner/admin permission is checked separately
1012
+ from the target's
1013
+ current membership. Transfer still requires automatic execution permission,
1014
+ platform compatibility and completed dependencies. It preserves `in_progress`
1015
+ and the task's execution interval, installing a fresh target claim/worktree ID
1016
+ with empty runtime associations. The receiver discovers its actual grant through
1017
+ normal claim inventory and starts a new execution; an old task path still in use
1018
+ blocks preparation. No source files, SQLite snapshots or native history are
1019
+ transported. Target and source agents may differ. Public commands provide no
1020
+ claim/worktree-ID override or continuity confirmation option; the service and
1021
+ typed client reject deprecated `continuityConfirmed` input.
1022
+
1023
+ For a paused execution that still belongs to the original owner, authorize one
1024
+ extra recovery attempt:
1025
+
1026
+ ```bash
1027
+ daynight worker retry <task-id> --claim-id <claim-id>
1028
+ ```
1029
+
1030
+ Retry preserves the original claim, worktree/native identity and frozen
1031
+ settings, retaining the cumulative recovery count rather than resetting it.
1032
+ Concurrent or repeated requests do not accumulate extra authorization or launch
1033
+ a second agent. The controller consumes the single permit for that original
1034
+ execution; a further failure remains visible. Retry cannot replace terminal
1035
+ cleanup or recreate an execution that has ended.
1036
+
1037
+ A native launch acknowledged before a blocking startup screen has a specific
1038
+ continuation path when its first prompt is durably known unsent. Keep the
1039
+ original worker/native session running and use another terminal to attach to
1040
+ that original pane. Inspect the reported folder-trust/authorization requirement
1041
+ and make the native decision yourself. Once the business composer is available,
1042
+ run:
1043
+
1044
+ ```bash
1045
+ daynight worker retry <task-id> --claim-id <original-claim-id> --project <project-id>
1046
+ ```
1047
+
1048
+ The controller first checks the original worktree, full binding, frozen argv,
1049
+ workspace/launch evidence, same shell and every saved native key PID. Ordinary
1050
+ child-process changes do not replace the original proof. After that read-only
1051
+ identity check, it consumes one authorized recovery attempt (the cumulative
1052
+ count increases by one, without reset) and can deliver the first prompt once in
1053
+ the original native process without another agent.start or conversation. Missing
1054
+ an official native ID before the first turn does not by itself block this
1055
+ proven-unsent continuation. This is not permission to resend an earlier
1056
+ submitted/unknown prompt, infer loss from an empty-looking composer or restart
1057
+ an unproven missing-ID conversation. Legacy records with unknown native-process
1058
+ role remain fenced; migration does not construct identity from foreground PID
1059
+ order. Automated cleanup text and /exit use the same screen boundary; a blocking
1060
+ screen is not accepted with Enter merely to finish shutdown.
1061
+
1062
+ Management diagnostics identify the original claim and report persisted waiting,
1063
+ completion, rejection or unknown results. Interrupting the command retains its
1064
+ intent so the foreground controller or a later management invocation can
1065
+ continue. An unknown release/transfer write is reconciled by reading the actual
1066
+ task and saved target claim; it is never resent or assigned replacement IDs,
1067
+ even when a read still shows the old value. Reinvoking that same decision can
1068
+ reconcile its result by targeted reads, including beside a running foreground
1069
+ worker, without taking over resource control or resubmitting. An already-cleaned
1070
+ source is not restarted. Only a definitely rejected submission can be replaced by a new explicit
1071
+ decision, with the supplied `--if-version` matching a fresh task observation. The
1072
+ numeric version may remain the same when the refusal did not change the task,
1073
+ including a definite pre-dispatch failure or permission refusal. An unknown
1074
+ submission cannot be reset or replayed; `--if-version` is never silently replaced.
1075
+ Unknown resume requests likewise retain their original claim/worktree/config
1076
+ until the actual grant can be confirmed. These targeted reads reconcile manual
1077
+ writes; automatic cleanup still relies only on a complete successful inventory
1078
+ for the original authenticated user and worker.
1079
+
750
1080
  ## Review configuration and startup
751
1081
 
752
1082
  Register a repository explicitly, or let the first review operation guide registration:
@@ -843,7 +1173,7 @@ review preparation and execution. Startup acquires an exclusive instance lock,
843
1173
  opens SQLite and prepares the configured clones. Each repository is polled
844
1174
  independently; access failures retain its last complete observation and remain
845
1175
  visible in diagnostics. The
846
- [repository registration decision](../../.agents/notes/implemented/feature/2026-10-18-add-repo-configuration.md)
1176
+ [repository registration decision](../../.agents/notes/archived/feature/2026-10-18-add-repo-configuration.md)
847
1177
  records the fixed-path and configuration-only choices.
848
1178
 
849
1179
  ## Review status listing
@@ -890,7 +1220,7 @@ database, migrate a schema, recover interrupted work or update application state
890
1220
  SQLite may create or update its WAL coordination sidecar files while reading an
891
1221
  existing database. Missing or invalid configuration, unreadable or corrupt state,
892
1222
  and unsupported schema versions fail visibly. The
893
- [listing decision](../../.agents/notes/implemented/feature/2026-10-18-review-status-listing.md)
1223
+ [listing decision](../../.agents/notes/archived/feature/2026-10-18-review-status-listing.md)
894
1224
  records status attribution and snapshot limits.
895
1225
 
896
1226
  ## Durable review state
@@ -925,7 +1255,7 @@ Database state does not replace physical Git/worktree or session-history
925
1255
  verification.
926
1256
 
927
1257
  See the [review architecture](../../docs/design/daynight-review.md) for transitions and the
928
- [state decision](../../.agents/notes/implemented/architecture/2026-10-17-durable-review-state.md)
1258
+ [state decision](../../.agents/notes/archived/architecture/2026-10-17-durable-review-state.md)
929
1259
  for persistence choices. The coordinator opens this state before scheduling work
930
1260
  and advances only the revision captured by each completed attempt.
931
1261
 
@@ -941,7 +1271,7 @@ the previous repository observation. A completed pass commits its observations
941
1271
  and success time atomically. Rate-limit failures expose the server's retry
942
1272
  deadline and block later same-host calls in that client; the coordinator schedules
943
1273
  the next pass after the applicable deadline.
944
- The [observation decision](../../.agents/notes/implemented/architecture/2026-10-17-github-observation.md)
1274
+ The [observation decision](../../.agents/notes/archived/architecture/2026-10-17-github-observation.md)
945
1275
  records pagination and failure handling.
946
1276
 
947
1277
  CI admission uses a read-only GraphQL query for the current PR head and
@@ -978,11 +1308,13 @@ even when the base checkout uses sparse settings. Confirmation retries retain
978
1308
  local context. Files, nested clones and administration inside the owned PR
979
1309
  worktree are disposable; cleanup does not inventory their external consumers.
980
1310
  Other PR worktrees and retained sessions remain separate. Cleanup rechecks remote
981
- closure before removal. The [exclusive-environment decision](../../.agents/notes/implemented/architecture/2026-10-17-exclusive-review-environment.md)
982
- defines this ownership boundary.
1311
+ closure before removal. The [exclusive-environment decision](../../.agents/notes/archived/architecture/2026-10-17-exclusive-review-environment.md)
1312
+ records the choice of this ownership boundary.
983
1313
 
984
- See the [worktree ownership decision](../../.agents/notes/implemented/architecture/2026-10-17-owned-review-worktrees.md)
985
- for target validation and recovery boundaries.
1314
+ The [review architecture](../../docs/design/daynight-review.md#worktree-生命周期)
1315
+ defines target validation and recovery boundaries; the
1316
+ [worktree ownership decision](../../.agents/notes/archived/architecture/2026-10-17-owned-review-worktrees.md)
1317
+ records their rationale.
986
1318
 
987
1319
  ## Copilot execution
988
1320
 
@@ -1102,17 +1434,17 @@ before completing the round. It owns scheduling and final state transitions;
1102
1434
  runtime process supervision supplies evidence under the foreground execution
1103
1435
  contract.
1104
1436
 
1105
- The [execution decision](../../.agents/notes/implemented/architecture/2026-10-17-copilot-session-execution.md)
1437
+ The [execution decision](../../.agents/notes/archived/architecture/2026-10-17-copilot-session-execution.md)
1106
1438
  records process and publication boundaries; the
1107
- [PR-quality decision](../../.agents/notes/implemented/process/2026-10-21-review-pr-quality-gates.md)
1439
+ [PR-quality decision](../../.agents/notes/archived/process/2026-10-21-review-pr-quality-gates.md)
1108
1440
  records the approval policy, and the
1109
1441
  [multi-perspective decision](../../.agents/notes/implemented/process/2026-10-22-pr-specific-review-perspectives.md)
1110
1442
  records delegation and synthesis. The
1111
- [conversation-cycle decision](../../.agents/notes/implemented/architecture/2026-10-21-review-conversation-cycle.md)
1443
+ [conversation-cycle decision](../../.agents/notes/archived/architecture/2026-10-21-review-conversation-cycle.md)
1112
1444
  records durable follow-ups and publication verification. The
1113
1445
  [skill design](../../docs/design/daynight-review-skill.md) owns packaging, snapshots and
1114
1446
  loading, with rationale in the
1115
- [bundled-skill decision](../../.agents/notes/implemented/architecture/2026-10-20-bundled-review-skill.md).
1447
+ [bundled-skill decision](../../.agents/notes/archived/architecture/2026-10-20-bundled-review-skill.md).
1116
1448
  Native probes with Copilot CLI 1.0.100 verify actual bundled-skill activation and
1117
1449
  changed-bundle resume with the same UUID, including comma, space and Unicode
1118
1450
  paths. The bundled-skill decision records the probe's conditions and limits.
@@ -1171,7 +1503,7 @@ and logs. That explicitly confirmed restart reconciles interrupted work with
1171
1503
  the same captured target and session; it never declares a saved running attempt
1172
1504
  complete or kills a saved process ID.
1173
1505
 
1174
- The [coordination decision](../../.agents/notes/implemented/architecture/2026-10-17-foreground-review-coordination.md)
1506
+ The [coordination decision](../../.agents/notes/archived/architecture/2026-10-17-foreground-review-coordination.md)
1175
1507
  explains scheduling and the foreground execution boundary. The
1176
- [stale-lock recovery decision](../../.agents/notes/implemented/bug-fix/2026-10-18-stale-instance-lock-recovery.md)
1508
+ [stale-lock recovery decision](../../.agents/notes/archived/bug-fix/2026-10-18-stale-instance-lock-recovery.md)
1177
1509
  records owner-liveness checks and the separate process-exclusion requirement.
@@ -1,5 +1,5 @@
1
1
  import type { Operation } from "./operation.js";
2
- import type { AttachmentConsumer, CreateProjectInput, CreateTaskInput, DeleteTaskInput, ErrorDetails, Project, PutTaskAttachmentInput, ReadyTaskFilters, ServerError, Task, SetTaskStatusInput, TaskAttachment, TaskFilters, TaskGraph, UpdateTaskInput, ClaimWorkerTaskInput, CompleteWorkerTaskInput, ReleaseWorkerClaimInput, ResumeWorkerTaskInput, TransferWorkerClaimInput, UpdateWorkerClaimInput, Page, TaskPageQuery } from "./types.js";
2
+ import type { AttachmentConsumer, CreateProjectInput, CreateTaskInput, DeleteTaskInput, ErrorDetails, Project, ProjectMember, PutTaskAttachmentInput, ReadyTaskFilters, ServerError, Task, SetTaskStatusInput, TaskAttachment, TaskFilters, TaskGraph, UpdateTaskInput, ClaimWorkerTaskInput, CompleteWorkerTaskInput, ReleaseWorkerClaimInput, ResumeWorkerTaskInput, TransferWorkerClaimInput, UpdateWorkerClaimInput, User, Page, TaskPageQuery } from "./types.js";
3
3
  type Context = {
4
4
  readonly operation: string;
5
5
  readonly projectId?: string;
@@ -26,9 +26,11 @@ export declare class ApiError extends Error {
26
26
  });
27
27
  }
28
28
  export type ApiClient = {
29
+ getCurrentUser(): Promise<User>;
29
30
  createProject(input: CreateProjectInput): Promise<Project>;
30
31
  getProject(projectId: string): Promise<Project>;
31
32
  listProjects(): Promise<readonly Project[]>;
33
+ listProjectMembers(projectId: string): Promise<readonly ProjectMember[]>;
32
34
  createTask(projectId: string, input: CreateTaskInput): Promise<Task>;
33
35
  getTask(projectId: string, taskId: string): Promise<Task>;
34
36
  listTasks(projectId: string, filters?: TaskFilters): Promise<readonly Task[]>;
@@ -52,6 +54,7 @@ export type ApiClient = {
52
54
  export declare const createApiClient: (options: {
53
55
  readonly serverUrl: string;
54
56
  readonly serverToken?: string;
57
+ readonly expectedUserId?: string;
55
58
  readonly operation: Operation;
56
59
  readonly fetch?: typeof globalThis.fetch;
57
60
  }) => ApiClient;
@@ -2,7 +2,7 @@ import { performance } from "node:perf_hooks";
2
2
  import { parseApiJson, stringifyApiJson } from "./json.js";
3
3
  import { OperationError } from "./operation.js";
4
4
  import { validateServerToken, validateTokenTransport } from "../config/server-token.js";
5
- import { canonicalId, parsePage, parseProject, parseServerError, parseTask, parseTaskGraph, parseTaskAttachment, ProtocolError, validateAttachmentPath } from "./parse.js";
5
+ import { canonicalId, parsePage, parseProject, parseProjectMembers, parseServerError, parseTask, parseTaskGraph, parseTaskAttachment, parseUser, ProtocolError, validateAttachmentPath } from "./parse.js";
6
6
  export class ApiError extends Error {
7
7
  operation;
8
8
  phase;
@@ -55,6 +55,7 @@ export const createApiClient = (options) => {
55
55
  if (!/^https?:$/.test(origin.protocol) || origin.username !== "" || origin.password !== "" || origin.pathname !== "/" || origin.search !== "" || origin.hash !== "")
56
56
  throw new Error("serverUrl must be an HTTP(S) service origin without credentials, path, query or fragment.");
57
57
  const serverToken = options.serverToken === undefined ? undefined : validateServerToken(options.serverToken);
58
+ const expectedUserId = options.expectedUserId === undefined ? undefined : resourceId(options.expectedUserId);
58
59
  if (serverToken !== undefined)
59
60
  validateTokenTransport(origin.origin);
60
61
  const operation = options.operation;
@@ -166,6 +167,15 @@ export const createApiClient = (options) => {
166
167
  reader = response.body.getReader();
167
168
  // Cancelling an already errored stream repeats its existing failure, rather than introducing a cleanup failure.
168
169
  void reader.closed.catch((error) => { bodyFailure = error; });
170
+ }
171
+ if (success && expectedUserId !== undefined) {
172
+ phase = "protocol";
173
+ const principal = response.headers.get("Daynight-User-ID");
174
+ if (principal === null || canonicalId(principal) !== expectedUserId)
175
+ throw new ProtocolError("The authenticated response principal does not match the expected user.");
176
+ phase = "response";
177
+ }
178
+ if (reader !== undefined) {
169
179
  while (true) {
170
180
  checkRequest();
171
181
  const chunk = await Promise.race([reader.read(), aborted]);
@@ -344,6 +354,8 @@ export const createApiClient = (options) => {
344
354
  const herdrMatches = (actual, expected) => actual === null || expected === null ? actual === expected : actual.session === expected.session && actual.workspaceId === expected.workspaceId && actual.paneId === expected.paneId;
345
355
  const descriptorMatches = (worker, descriptor) => worker.claimId === canonicalId(descriptor.claimId) && worker.workerId === canonicalId(descriptor.workerId) && worker.machine.id === canonicalId(descriptor.machine.id) && worker.machine.name === descriptor.machine.name && worker.platform === descriptor.platform && worker.agent === descriptor.agent && worker.worktreeId === canonicalId(descriptor.worktreeId);
346
356
  const workerMutation = (projectId, taskId, action, suffix, method, input, matches, sameValue = false) => {
357
+ if (Object.hasOwn(input, "continuityConfirmed"))
358
+ throw new Error("continuityConfirmed is no longer accepted. New executions require fresh claim and worktree IDs.");
347
359
  const project = resourceId(projectId), task = resourceId(taskId);
348
360
  taskVersion(input.version);
349
361
  return exchange({ operation: action, projectId: project, taskId: task }, `/projects/${encodeURIComponent(project)}/tasks/${encodeURIComponent(task)}${suffix}`, method, { kind: "json", parse: (value) => {
@@ -355,12 +367,17 @@ export const createApiClient = (options) => {
355
367
  } }, [200], { kind: "json", value: input }, true);
356
368
  };
357
369
  return {
370
+ getCurrentUser: () => exchange({ operation: "auth.me" }, "/me", "GET", { kind: "json", parse: parseUser }, [200], undefined, true),
358
371
  createProject: (input) => request({ operation: "project.create" }, "/projects", "POST", (value) => parseProject(value), { name: input.name, repoUrl: input.repoUrl }),
359
372
  getProject: (projectId) => {
360
373
  const project = resourceId(projectId);
361
374
  return request({ operation: "project.show", projectId: project }, `/projects/${encodeURIComponent(project)}`, "GET", (value) => parseProject(value, project));
362
375
  },
363
376
  listProjects: () => list({ operation: "project.list" }, "/projects", (value) => parseProject(value), (project) => project.id),
377
+ listProjectMembers: (projectId) => {
378
+ const project = resourceId(projectId);
379
+ return exchange({ operation: "project.members", projectId: project }, `/projects/${encodeURIComponent(project)}/members`, "GET", { kind: "json", parse: (value) => parseProjectMembers(value, project) }, [200], undefined, true);
380
+ },
364
381
  createTask: (projectId, input) => {
365
382
  const project = resourceId(projectId);
366
383
  writableProperties(input.properties);