@codetreker/daynight 0.32.1 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +266 -68
  2. package/dist/api/client.d.ts +7 -1
  3. package/dist/api/client.js +117 -21
  4. package/dist/api/client.js.map +1 -1
  5. package/dist/api/json-source.d.ts +3 -0
  6. package/dist/api/json-source.js +113 -0
  7. package/dist/api/json-source.js.map +1 -0
  8. package/dist/api/parse.d.ts +2 -1
  9. package/dist/api/parse.js +16 -1
  10. package/dist/api/parse.js.map +1 -1
  11. package/dist/api/thread.d.ts +6 -0
  12. package/dist/api/thread.js +79 -0
  13. package/dist/api/thread.js.map +1 -0
  14. package/dist/api/types.d.ts +50 -0
  15. package/dist/cli/application.js +12 -2
  16. package/dist/cli/application.js.map +1 -1
  17. package/dist/cli/context.d.ts +9 -1
  18. package/dist/cli/context.js +3 -1
  19. package/dist/cli/context.js.map +1 -1
  20. package/dist/cli/schema.js +10 -10
  21. package/dist/cli/schema.js.map +1 -1
  22. package/dist/commands/cleanup-operation.d.ts +3 -0
  23. package/dist/commands/cleanup-operation.js +12 -0
  24. package/dist/commands/cleanup-operation.js.map +1 -0
  25. package/dist/commands/controller/provider-display.d.ts +2 -0
  26. package/dist/commands/controller/provider-display.js +63 -0
  27. package/dist/commands/controller/provider-display.js.map +1 -0
  28. package/dist/commands/controller/providers/projection.js +12 -0
  29. package/dist/commands/controller/providers/projection.js.map +1 -1
  30. package/dist/commands/controller/runtime.js +4 -2
  31. package/dist/commands/controller/runtime.js.map +1 -1
  32. package/dist/commands/server/runtime.d.ts +10 -1
  33. package/dist/commands/server/runtime.js +24 -7
  34. package/dist/commands/server/runtime.js.map +1 -1
  35. package/dist/commands/skill/skills/using-daynight/SKILL.md +5 -3
  36. package/dist/commands/skill/skills/using-daynight/references/authorization.md +2 -2
  37. package/dist/commands/skill/skills/using-daynight/references/autopilot-managed-task.md +4 -3
  38. package/dist/commands/skill/skills/using-daynight/references/handbook.md +4 -1
  39. package/dist/commands/skill/skills/using-daynight/references/handoff.md +25 -15
  40. package/dist/commands/skill/skills/using-daynight/references/task-content.md +7 -4
  41. package/dist/commands/skill/skills/using-daynight/references/task-management.md +56 -6
  42. package/dist/commands/skill/skills/using-daynight/references/write-safety.md +22 -3
  43. package/dist/commands/skill/usage.md +84 -7
  44. package/dist/commands/task/command.js +28 -3
  45. package/dist/commands/task/command.js.map +1 -1
  46. package/dist/commands/task/definition.js +40 -6
  47. package/dist/commands/task/definition.js.map +1 -1
  48. package/dist/commands/task/rendering.js +4 -0
  49. package/dist/commands/task/rendering.js.map +1 -1
  50. package/dist/commands/task/thread-diagnostics.d.ts +5 -0
  51. package/dist/commands/task/thread-diagnostics.js +32 -0
  52. package/dist/commands/task/thread-diagnostics.js.map +1 -0
  53. package/dist/commands/task/thread-rendering.d.ts +8 -0
  54. package/dist/commands/task/thread-rendering.js +80 -0
  55. package/dist/commands/task/thread-rendering.js.map +1 -0
  56. package/dist/commands/task/thread.d.ts +11 -0
  57. package/dist/commands/task/thread.js +74 -0
  58. package/dist/commands/task/thread.js.map +1 -0
  59. package/dist/commands/worker/backends/session-api.d.ts +1 -1
  60. package/dist/commands/worker/backends/session-api.js +4 -4
  61. package/dist/commands/worker/backends/session-api.js.map +1 -1
  62. package/dist/commands/worker/backends/web-store.d.ts +4 -0
  63. package/dist/commands/worker/backends/web-store.js +40 -6
  64. package/dist/commands/worker/backends/web-store.js.map +1 -1
  65. package/dist/commands/worker/backends/web.js +248 -127
  66. package/dist/commands/worker/backends/web.js.map +1 -1
  67. package/dist/commands/worker/cleanup-error.d.ts +5 -0
  68. package/dist/commands/worker/cleanup-error.js +9 -0
  69. package/dist/commands/worker/cleanup-error.js.map +1 -0
  70. package/dist/commands/worker/cleanup-schedule.d.ts +3 -0
  71. package/dist/commands/worker/cleanup-schedule.js +11 -0
  72. package/dist/commands/worker/cleanup-schedule.js.map +1 -0
  73. package/dist/commands/worker/cleanup.js +47 -31
  74. package/dist/commands/worker/cleanup.js.map +1 -1
  75. package/dist/commands/worker/coordinator.js +186 -63
  76. package/dist/commands/worker/coordinator.js.map +1 -1
  77. package/dist/commands/worker/execution.d.ts +1 -1
  78. package/dist/commands/worker/execution.js +2 -2
  79. package/dist/commands/worker/execution.js.map +1 -1
  80. package/dist/commands/worker/prompts.js +2 -2
  81. package/dist/commands/worker/prompts.js.map +1 -1
  82. package/dist/commands/worker/remote.js +3 -4
  83. package/dist/commands/worker/remote.js.map +1 -1
  84. package/dist/commands/worker/remove-worktree-contents.d.ts +3 -0
  85. package/dist/commands/worker/remove-worktree-contents.js +106 -0
  86. package/dist/commands/worker/remove-worktree-contents.js.map +1 -0
  87. package/dist/commands/worker/runtime.js +1 -1
  88. package/dist/commands/worker/runtime.js.map +1 -1
  89. package/dist/commands/worker/sqlite/006-cleanup-schedules.sql +14 -0
  90. package/dist/commands/worker/store.d.ts +5 -1
  91. package/dist/commands/worker/store.js +53 -0
  92. package/dist/commands/worker/store.js.map +1 -1
  93. package/dist/commands/worker/types.d.ts +10 -0
  94. package/dist/commands/worker/worktrees.js +70 -24
  95. package/dist/commands/worker/worktrees.js.map +1 -1
  96. package/dist/platform/diagnostics.d.ts +5 -0
  97. package/dist/platform/diagnostics.js +12 -0
  98. package/dist/platform/diagnostics.js.map +1 -1
  99. package/dist/session/codex-subagent-activity.d.ts +4 -0
  100. package/dist/session/codex-subagent-activity.js +13 -0
  101. package/dist/session/codex-subagent-activity.js.map +1 -0
  102. package/dist/session/v2/archive.d.ts +6 -0
  103. package/dist/session/v2/archive.js +163 -0
  104. package/dist/session/v2/archive.js.map +1 -0
  105. package/dist/session/v2/protocol.d.ts +19 -0
  106. package/dist/session/v2/protocol.js +260 -0
  107. package/dist/session/v2/protocol.js.map +1 -0
  108. package/dist/session/v2/responsibility.d.ts +3 -0
  109. package/dist/session/v2/responsibility.js +12 -0
  110. package/dist/session/v2/responsibility.js.map +1 -0
  111. package/dist/session/v2/types.d.ts +293 -0
  112. package/dist/session/v2/types.js +2 -0
  113. package/dist/session/v2/types.js.map +1 -0
  114. package/dist/session/v2/values.d.ts +59 -0
  115. package/dist/session/v2/values.js +201 -0
  116. package/dist/session/v2/values.js.map +1 -0
  117. package/package.json +5 -3
package/README.md CHANGED
@@ -1,15 +1,24 @@
1
1
  # Daynight CLI
2
2
 
3
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, run foreground task workers through
4
+ alias. Use it to manage server-backed projects, tasks, discussion threads and
5
+ attachments, install the `using-daynight` skill for coding agents, run foreground
6
+ task workers through
6
7
  Herdr or browser-connected native Controllers, and run a local GitHub PR reviewer through Copilot CLI. Both command names
7
- share configuration and behavior.
8
+ share configuration and behavior. Supported native platforms are Linux, Windows
9
+ and Apple Silicon (ARM64) macOS. Intel macOS is unsupported.
8
10
 
9
11
  See the [project overview](../../README.md) for the browser workspace and service,
10
12
  and the [development guide](../../docs/development.md) for source builds,
11
- validation, package versions and npm publication. Each command's `--help` owns
12
- its exact usage. Review execution additionally requires Git, an authenticated
13
+ validation, package versions and npm publication. Ordinary test and installed
14
+ acceptance suites exclude stress workloads. From this package, `pnpm test:stress`
15
+ builds the CLI and runs the rendering and full Session-v2 `.stress.ts` suites;
16
+ `pnpm test:stress:budgets` runs the server validation gate with the four full
17
+ 128 MiB/256 MiB installed-CLI byte probes. The latter requires an isolated
18
+ `DAYNIGHT_TEST_DATABASE_URL` and the [server validation prerequisites](../daynight-server/README.md#validate).
19
+ Both commands are explicit local-only validation and refuse CI. The
20
+ [local stress guide](../../docs/development.md#local-stress-validation) owns
21
+ selection and receipt interpretation. Each command's `--help` owns its exact usage. Review execution additionally requires Git, an authenticated
13
22
  GitHub CLI and Copilot CLI on `PATH`.
14
23
 
15
24
  - [Install and update](#install-and-update)
@@ -22,6 +31,7 @@ GitHub CLI and Copilot CLI on `PATH`.
22
31
  - [Project management](#project-management)
23
32
  - [Task management](#task-management)
24
33
  - [Task deletion](#task-deletion)
34
+ - [Task discussion threads](#task-discussion-threads)
25
35
  - [Task attachments](#task-attachments)
26
36
  - [Worker configuration and startup](#worker-configuration-and-startup)
27
37
  - [Worker manual management](#worker-manual-management)
@@ -148,13 +158,15 @@ daynight project list [--json]
148
158
  daynight project show <project-id> [--json]
149
159
  daynight task
150
160
  daynight task create --title <title> [options]
151
- daynight task list [--all | --status <status>] [--ready] [--json] [--project <project-id>]
161
+ daynight task list [--all | --status <status>] [--ready] [--assigned-to <assignee>] [--json] [--project <project-id>]
152
162
  daynight task ready [--limit <N>] [--json] [--project <project-id>]
153
163
  daynight task show <task-id> [--json] [--project <project-id>]
154
164
  daynight task update <task-id> [options]
155
165
  daynight task set-status <task-id> <status> [--claim-id <claim-id>] [--if-version <version>] [--project <project-id>]
156
166
  daynight task delete <task-id> [--remove-depends] [--if-version <version>] [--project <project-id>]
157
167
  daynight task graph <task-id> [--depends-only] [--json] [--project <project-id>]
168
+ daynight task thread read <task-id> [--before-id <message-id> | --after-id <message-id>] [--count=N] [--details] [--project <project-id>]
169
+ daynight task thread post <task-id> --body <text> [--reply-to <message-id>] [--claim-id <claim-id>] [--project <project-id>]
158
170
  daynight task attachment
159
171
  daynight task attachment put <task-id> <file> [--path <relative-path>] [--project <project-id>]
160
172
  daynight task attachment list <task-id> [--tree | --json] [--project <project-id>]
@@ -417,9 +429,7 @@ keep the credential name within 100 characters. The credential never expires by
417
429
  The Web account's token manager can set a future expiration, restore “Never expires”, or
418
430
  revoke it. Changing expiration keeps the same credential, so the saved CLI login
419
431
  continues without replacing its secret. Expired or revoked credentials cannot be
420
- revived. The [token manager mockup](../../packages/daynight-web/tests/mockups/tokens.html)
421
- shares the production components and styles for creating tokens and editing
422
- expiration, including conflict and uncertain-result states. A credential
432
+ revived. A credential
423
433
  represents the account's current project permissions. `daynight logout` revokes the current credential and removes
424
434
  its local value after a confirmed response; an already invalid credential is
425
435
  removed locally. Network or unconfirmed failures remain visible. Configuration
@@ -553,6 +563,8 @@ daynight task list --allow-agents false --ready
553
563
  daynight task list --ready
554
564
  daynight task list --all --json
555
565
  daynight task list --status in_progress --json
566
+ daynight task list --ready --assigned-to me --json
567
+ daynight task list --assigned-to unassigned --json
556
568
  daynight task show <task-id> --json
557
569
  daynight task properties <task-id> --json
558
570
  daynight task properties --schema --json
@@ -563,6 +575,9 @@ daynight task update <task-id> --allow-agents true --if-version <version>
563
575
  daynight task create --title "Check Windows build" --required-platform windows
564
576
  daynight task update <task-id> --required-platform macos --if-version <version>
565
577
  daynight task update <task-id> --clear-required-platform --if-version <version>
578
+ daynight task create --title "Review installation" --assigned-to <user-uuid>
579
+ daynight task update <task-id> --assigned-to <user-uuid> --if-version <version>
580
+ daynight task update <task-id> --clear-assigned-to --if-version <version>
566
581
  daynight task set-status <task-id> <status> [--claim-id <claim-id>] [--if-version <version>] [--project <project-id>]
567
582
  daynight task update <task-id> --depends-on <task-a> --depends-on <task-b>
568
583
  daynight task update <task-id> --clear-dependencies
@@ -600,7 +615,7 @@ in the root `.gitignore`. A cached binding is verified against the server on eac
600
615
  use and remains stable if another project later shares that repository.
601
616
 
602
617
  Creation starts in `todo` with `allowAgents=false` and unrestricted
603
- `requiredPlatform=null` unless explicitly set. Unset properties remain absent;
618
+ `requiredPlatform=null` and `assignedTo=null` unless explicitly set. Unset properties remain absent;
604
619
  creation does not inject a PR array or worker null. `task set-status <id> <status>`
605
620
  sets `todo`, `in_progress` or `done`, including reopening and direct completion.
606
621
  Every project member may use ordinary status setting. Active worker completion
@@ -622,7 +637,7 @@ Entering in_progress or done requires all direct prerequisites, ordinary and
622
637
  external, to be done. Reopening done requires no direct in-progress or done
623
638
  dependents. Refusals return sorted blocking task IDs without cascading changes.
624
639
  The project transaction serializes status and dependency writes and preserves
625
- materials, properties/PRs, permission, both dependency sets and attachments.
640
+ materials, assignedTo, properties/PRs, permission, both dependency sets and attachments.
626
641
 
627
642
  Migration `014_task_status_assignment.sql` converts historical proposed rows
628
643
  to todo, increments only those versions and updates their update time while
@@ -728,7 +743,26 @@ service order across all pages. This order applies to human and JSON results.
728
743
  `task ready` accepts neither `--status` nor `--cursor`. `task list` supports the
729
744
  same permission and compatibility filters across every matching page. Both are
730
745
  automatic-selection conditions independent of readiness; explicitly designated
731
- execution retains the manual exception.
746
+ execution retains the manual exception. List also accepts
747
+ `--assigned-to <user-uuid|me|unassigned>`, combined with its other filters and
748
+ preserved across every page. `task ready` has no assignee option; use
749
+ `task list --ready --assigned-to me` for that intersection. Automatic acquisition
750
+ requires the task to be assigned to the worker's authenticated account, in addition
751
+ to permission and other eligibility checks. Existing claim inventory and manual
752
+ control remain execution-based; the
753
+ [self-assigned acquisition decision](../../.agents/notes/implemented/architecture/2026-11-03-worker-self-assigned-claims.md)
754
+ owns the runtime rule.
755
+
756
+ For `me`, each successful task-page response must carry one canonical
757
+ Daynight-User-ID, even when its items array is empty. A complete list traversal
758
+ binds its first successful page to that identity and rejects a different later
759
+ principal or a task assigned to someone else. The binding is per traversal, not
760
+ a global client cache. UUID and unassigned filters also verify every result;
761
+ mismatches are protocol errors, not locally discarded rows. No extra `/me`
762
+ request is issued. Non-me requests without a configured expectedUserId retain
763
+ their existing optional-header behavior. Error responses retain the existing
764
+ service-error and configured-principal admission behavior; me adds no new
765
+ error-response header requirement.
732
766
 
733
767
  Updates preserve omitted fields; an empty description clears it. Repeated
734
768
  `--depends-on` and `--external-depends-on` declare the complete ordinary and
@@ -738,8 +772,22 @@ only those external edges. IDs are canonicalized and sorted; malformed and
738
772
  case-equivalent duplicate/cross-declared UUIDs fail before configuration or
739
773
  network access. `--clear-dependencies` sends two empty sets and conflicts with
740
774
  either dependency option. An update needs at least one mutable
741
- field. `--allow-agents true|false` explicitly changes automatic-execution
742
- permission; omitted preserves it. Creation rejects the option. Existing tasks
775
+ field. Create/update accept `--assigned-to <user-uuid>`; update also accepts
776
+ `--clear-assigned-to` to send null. CLI creation without `--assigned-to` reads
777
+ the signed-in account through `/me` and submits its UUID. An explicit UUID skips
778
+ that identity lookup. A failed or cancelled lookup prevents creation; the CLI
779
+ does not substitute an unassigned task. Update omission preserves the existing
780
+ assignee. Direct API callers retain optional assignment and may create unassigned
781
+ tasks by omitting `assignedTo` or sending null. The set/clear options conflict, and invalid UUIDs or combinations fail before
782
+ configuration, Git or HTTP access. Writes accept UUIDs, not the list tokens
783
+ me/unassigned. A real assignment change atomically sets allowAgents=false; an
784
+ equal assignment causes no permission reset; a pure equal update preserves
785
+ version and timestamps. Other supplied fields keep their ordinary mutation
786
+ rules. Actual changes are refused while in_progress. Assignment grants neither project access nor
787
+ control of another worker, Session or archive.
788
+
789
+ `--allow-agents true|false` explicitly changes automatic-execution permission;
790
+ omission preserves it when assignment does not change. Creation rejects the option. Existing tasks
743
791
  receive true through migration without changing versions or business timestamps.
744
792
  A matching same-value permission PATCH retains version and time, while a stale
745
793
  version still conflicts and an actual in-progress toggle fails atomically.
@@ -752,8 +800,12 @@ are refused atomically. Explicit manual status setting remains available for eve
752
800
  requirement. The query platform selects candidates; it does not configure or
753
801
  prove the environment of a future worker.
754
802
  By default the CLI reads the task version before PATCH; `--if-version <n>`
755
- uses that exact positive int64 version. Conflicts and failed writes are reported
756
- without automatic retries.
803
+ uses that exact positive int64 version without a task pre-read. Existing project
804
+ resolution/admission still applies. Null clearing is serialized literally; only
805
+ undefined fields are omitted. A normal write consumes the full Task response
806
+ without a post-write GET or a name lookup. A combined update may advance its
807
+ version for other fields, so v+1 alone does not establish an assignee change.
808
+ Conflicts and failed writes are reported without automatic retries.
757
809
 
758
810
  Text options accept both separated values and `--option=value`. Inline assignment
759
811
  splits at the first equals sign and supports leading dashes, such as
@@ -764,29 +816,35 @@ inline assignment. Attachment `put` declares its `--path` as text, accepting
764
816
  paths starting with a dash. Property set/remove also accept this terminator for
765
817
  literal property/value positionals; other operations retain their declared syntax.
766
818
 
767
- The internal typed ApiClient accepts optional `workerId` on TaskFilters and
768
- TaskPageQuery. It requests only the authenticated user/worker active claims and
769
- validates active state and matching worker ID in responses. `listTasks` returns
819
+ The internal typed ApiClient accepts optional `assignedTo` and `workerId` on
820
+ TaskFilters and TaskPageQuery. Assignment selectors accept `me`, `unassigned` or
821
+ a user UUID; the worker uses `me` for new candidates across every page. With
822
+ workerId, the client requests only the authenticated user/worker active claims
823
+ and validates active state and matching worker ID in responses. `listTasks` returns
770
824
  only after every page succeeds; `listTaskPage` remains partial. A workerId-only
771
825
  traversal across all relevant projects provides ownership inventory; extra filters
772
- or incomplete pages cannot authorize cleanup. This field is not a public task CLI
773
- option.
826
+ or incomplete pages cannot authorize cleanup. These filters are not public task
827
+ CLI options.
774
828
 
775
829
  Human task lists use labeled blocks containing ID, project, title, complete
776
830
  properties, status, readiness, automatic-execution permission, required platform,
777
- dependencies and blocking. Property rows are ordered by name and rendered as
831
+ assignee, dependencies and blocking. Property rows are ordered by name and rendered as
778
832
  terminal-safe JSON; missing keys are not replaced with default values.
779
833
  Description, version and timestamps
780
834
  remain available in show, ready, create and update output. Graph nodes include
781
- state, permission, required platform, dependencies, blocking and title-preview truncation flags.
835
+ state, permission, required platform, assignee, dependencies, blocking and
836
+ title-preview truncation flags.
782
837
  Task and graph decoders require a boolean `allowAgents`; missing, null or
783
838
  nonboolean values are protocol errors. They also require `requiredPlatform`
784
839
  as null or one of the three platform enums; missing keys or other values fail
785
840
  without a runtime default. Human output uses `Required platform: any` for null
786
- and the enum otherwise. Queries support
841
+ and the enum otherwise. `assignedTo` is also required as null or a canonical
842
+ local user UUID on every Task and graph node; missing, malformed or noncanonical
843
+ values fail instead of defaulting. Human output adds `Assigned to: USER_UUID` or
844
+ `Assigned to: unassigned`, with no profile request or rule narration. Task metadata queries support
787
845
  `--json`: task `list` returns every matching task in one array, omitting only
788
- `description` while retaining every other API field, including raw PR strings,
789
- version and timestamps. This applies to the default list and every filter,
846
+ `description` while retaining every other API field, including explicit nullable
847
+ assignedTo, raw PR strings, version and timestamps. This applies to the default list and every filter,
790
848
  including `--all`. Project lists retain all API fields. Task `ready` returns its
791
849
  selected full tasks as an array, details return one full resource, and graphs
792
850
  return the selected task-chain API object unless `--depends-only` projects the
@@ -904,6 +962,68 @@ outcome unknown. The [deletion requirements](../../docs/spec/daynight-task-delet
904
962
  and [design](../../docs/design/daynight-task-deletion.md) own retained history,
905
963
  reference removal and cache invalidation.
906
964
 
965
+ ## Task discussion threads
966
+
967
+ ```bash
968
+ daynight task thread read <task-id>
969
+ daynight task thread read <task-id> --after-id <last-read-message-id> --count=20
970
+ daynight task thread read <task-id> --before-id <first-shown-message-id> --count=20
971
+ daynight task thread read <task-id> --details --project <project-id>
972
+ daynight task thread post <task-id> --body 'What should the retry policy be?'
973
+ daynight task thread post <task-id> --body 'Use an explicit retry decision.' --reply-to <message-id>
974
+ daynight task thread post <task-id> --body 'The check passed.' --claim-id <active-claim-id>
975
+ ```
976
+
977
+ A Thread holds durable discussion independently of task execution. Reads and
978
+ posts work before execution, while its original environment is offline, and
979
+ after completion. Messages are immutable and replies refer to messages in the
980
+ selected task. Posting neither changes task metadata nor wakes an Agent.
981
+ Descriptions and attachments remain the owners of effective requirements,
982
+ solutions and formal results; Sessions hold execution content.
983
+
984
+ Read fetches one page, defaulting to the latest messages. `--count=N` accepts
985
+ 1 through 100 and defaults to 20; the CLI always sends that value explicitly.
986
+ `--before-id` and `--after-id` are mutually exclusive. Messages display from old
987
+ to new with complete Id, Author and account Id, millisecond UTC CreatedAt,
988
+ optional ReplyTo, and complete Message. Agent authors also have `Agent: True`.
989
+ `--details` expands verified claim, worker and provider attribution. Thread
990
+ commands provide readable text and do not accept `--json`.
991
+
992
+ `... Has more messages before` appears above a page with earlier messages;
993
+ `Has more messages after...` appears below a page with later messages. Continue
994
+ history with the first displayed Id and incremental reading with the last
995
+ fully consumed displayed Id. The 256 KiB output budget can reduce the page
996
+ below its requested count; complete messages remain contiguous and bodies are
997
+ never truncated. A post receipt cannot advance the read position: after reading
998
+ A, another person's B and a local post C must still be read from A.
999
+
1000
+ Post requires nonblank `--body`, preserving its original whitespace. For text
1001
+ beginning with a dash, use `--body=-example`. The service generates the message
1002
+ Id and authenticates the author. Omit `--claim-id` for an ordinary account post;
1003
+ provide a current claim explicitly for verified Agent attribution. The CLI does
1004
+ not infer a claim or accept a client message Id, version or submission token.
1005
+ `--reply-to` is optional and must identify a message in the same task.
1006
+
1007
+ Terminal text escapes dangerous controls. Multiline Message lines are indented,
1008
+ retain LF and TAB, and encode literal backslashes before visible control
1009
+ escapes; DEL is `\x7f`, CR is `\r`, and other unsafe controls use `\uXXXX`.
1010
+ The representation preserves the full body without executing terminal escapes.
1011
+ Success prints `Message posted.`, the complete Id and optional ReplyTo, without
1012
+ repeating the body. An uncertain post exits with a clear unknown-outcome message.
1013
+ Read the Thread before deciding whether to send again; equal text cannot prove
1014
+ that a particular request succeeded. The CLI never automatically repeats POST.
1015
+
1016
+ The [Thread requirements](../../docs/spec/daynight-task-thread.md) own the
1017
+ service contract; the [CLI design](../../docs/design/task-thread-cli.md) owns
1018
+ source validation, rendering and submission confirmation. Explicit `--project`
1019
+ uses the supplied UUID directly for the Thread request; otherwise the existing
1020
+ Git binding resolves the project. Origin and credential remain fixed for one
1021
+ invocation. Argument errors exit 2 before configuration or network access;
1022
+ other failures exit 1. Diagnostics remain on stderr and exclude message bodies
1023
+ and untrusted server text. A confirmed post followed by a local receipt-output
1024
+ or cleanup failure retains its confirmed message Id and is not reported as an
1025
+ unknown remote result.
1026
+
907
1027
  ## Task attachments
908
1028
 
909
1029
  Attachment commands use the existing project selection and server configuration:
@@ -951,10 +1071,11 @@ records binary transport and output ownership.
951
1071
  ## Worker configuration and startup
952
1072
 
953
1073
  `daynight worker run` is a foreground reconciler. It claims eligible ready tasks
954
- across configured repositories, runs native agents through the claim's Herdr or
1074
+ assigned to its authenticated account across configured repositories, runs native agents through the claim's Herdr or
955
1075
  Web backend, and cleans resources when the original claim leaves its complete
956
1076
  inventory. The agent owns delivery, acceptance, evidence and final claim-bound
957
- completion.
1077
+ completion. Worker follows the CLI platform support policy: Linux, Windows and
1078
+ Apple Silicon (ARM64) macOS.
958
1079
 
959
1080
  The running worker reports an account-owned runtime snapshot immediately after
960
1081
  identity and authentication are ready, every 30 seconds, and after complete task
@@ -1200,13 +1321,19 @@ line separators and bidirectional display controls are escaped as visible text;
1200
1321
  Unicode titles and emoji remain readable. Full titles and owner IDs are retained,
1201
1322
  with Herdr responsible for fitting the label into its current terminal width.
1202
1323
 
1203
- The local database has exactly these business fields:
1324
+ The local claim index has these business fields:
1204
1325
 
1205
1326
  ```text
1206
1327
  projects(project_id, repo_url, local_path)
1207
1328
  tasks(project_id, task_id, claim_id, status, agent, session_id, agent_control_mode)
1208
1329
  ```
1209
1330
 
1331
+ A separate `cleanup_schedules` table binds terminal cleanup responsibility to
1332
+ the original Project/task/claim/worktree. It retains the first deadline,
1333
+ notification submission state, failure count, next retry time, stage and error.
1334
+ These records preserve responsibility; they do not prove that resources stopped
1335
+ or disappeared.
1336
+
1210
1337
  Status is pending, active or done. Pending is an actual acquired claim waiting
1211
1338
  for startup; active owns startup, running, recovery or cleanup responsibility;
1212
1339
  done means the ended claim's resources have been cleaned. Completed rows remain,
@@ -1218,7 +1345,8 @@ The state directory belongs to the configured single service, Daynight account
1218
1345
  and workerId. Finish old executions before changing those identities and
1219
1346
  rebuilding local state. The running process pins its startup authenticated user;
1220
1347
  the claim-index database does not retain prior-service or prior-account recovery
1221
- scopes. The claim index has its own `user_version=5`. All five business databases
1348
+ scopes. The claim index and cleanup schedule share `user_version=6`; upgrading
1349
+ version 5 preserves its Project and task rows. All five business databases
1222
1350
  reset `user_version=0` after their ownership checks: the original schema and data
1223
1351
  are discarded, then the baseline and numbered upgrades rebuild the current
1224
1352
  format. This includes existing empty files and query access. Known valid nonzero
@@ -1229,7 +1357,13 @@ its migration sequence; the [SQLite migration requirements](../../docs/spec/cli-
1229
1357
  define atomicity, ownership blockers and supported starting formats.
1230
1358
 
1231
1359
  Each reconciliation obtains the complete own-claim inventory for configured and
1232
- saved Projects. Still-owned local active tasks are queued for fresh target
1360
+ saved Projects using only workerId. Assignment does not filter this inventory:
1361
+ existing executions retain their recovery and cleanup authority. New candidates
1362
+ combine assignedTo=me, ready, automatic permission and actual platform before
1363
+ server pagination; the claim transaction rechecks the assignee against the
1364
+ authenticated user ID. Unassigned tasks and tasks assigned to another account
1365
+ are ineligible for automatic acquisition. Explicit manual resume retains its
1366
+ original execution-owner/admin rules. Still-owned local active tasks are queued for fresh target
1233
1367
  observation and recovery before global Git discovery, so a sibling checkout's
1234
1368
  filesystem error does not block an already-reserved task. New pending startup
1235
1369
  and new claims still require complete global resource discovery. Failed or
@@ -1270,8 +1404,10 @@ pane's retained reference is not saved as a newly observed session ID. A live
1270
1404
  agent keeps its current connection.
1271
1405
 
1272
1406
  Startup, recovery and continuation prompts require autonomous decisions within
1273
- the task scope and existing authorization. When human intervention is necessary,
1274
- the managed agent sets its own task's `paused` property to true with an observed
1407
+ the task scope and existing authorization. Human intervention requires specific
1408
+ information, a decision, authorization or an action that the agent cannot supply
1409
+ within that scope and authority. Before waiting for that intervention, the
1410
+ managed agent sets its own task's `paused` property to true with an observed
1275
1411
  exact version and confirms the same assignment and pause before waiting. It
1276
1412
  reports the issue and retains session context; the user chooses how to respond.
1277
1413
  After verifying resolution, the original assignment and permission to resume,
@@ -1279,10 +1415,13 @@ it clears the pause and confirms false or absence before continuing. Independent
1279
1415
  user restrictions still apply. The [managed workflow](src/commands/skill/skills/using-daynight/references/autopilot-managed-task.md#request-user-interaction)
1280
1416
  owns readback, failure and conflict handling.
1281
1417
 
1282
- Ordinary review and CI waits remain ongoing execution: the agent waits, checks
1283
- results and continues delivery without ending its turn or setting a pause just
1284
- because a poll times out. Fixed native full access and folder trust apply to
1285
- every fresh/resumed process; task delivery remains within its business authorization.
1418
+ Pending PR review, required reviewer approval and CI remain ongoing execution,
1419
+ including reviews performed by a person. Pending results and polling timeouts
1420
+ do not justify setting `properties.paused=true`, requesting user intervention
1421
+ or ending the turn. The agent monitors results and continues delivery while
1422
+ honoring independent user pauses, restrictions and revocations. Fixed native
1423
+ full access and folder trust apply to every fresh/resumed process; task delivery
1424
+ remains within its business authorization.
1286
1425
 
1287
1426
  For a still-owned active claim, each patrol observes the live agent. An
1288
1427
  interactive-ready agent that is not launching and has no first input pending
@@ -1314,10 +1453,12 @@ agent's ID may fill a NULL record; inactive pane references remain excluded.
1314
1453
 
1315
1454
  The NULL rule also covers interruption before a newly started native ID was saved.
1316
1455
  It retains the task, claim and worktree and requires no history scan or approval
1317
- gate. A failed resume of a known ID remains an error. Launch/input receipts,
1318
- process observations, retries and cleanup progress exist only in the current
1319
- call or process. Recovery counts reset on restart; reaching recoveryLimit keeps
1320
- the task active with a visible error until explicit retry or another run.
1456
+ gate. A failed resume of a known ID remains an error. Business launch/input
1457
+ receipts, process observations and execution retries remain local to the current
1458
+ call or process in Herdr mode. Terminal cleanup retains its separate persistent
1459
+ schedule. Herdr execution recovery counts reset on restart; reaching
1460
+ recoveryLimit keeps the task active with a visible error until explicit retry or
1461
+ another run. Web recovery follows the persistent rules below.
1321
1462
 
1322
1463
  For human input, use another interactive terminal:
1323
1464
 
@@ -1362,15 +1503,23 @@ lost across a process interruption.
1362
1503
 
1363
1504
  During normal reconciliation, when the original claim is absent from a
1364
1505
  successful complete inventory, the worker asks its agent to release attributable
1365
- temporary files, services and processes outside the worktree. It waits at most
1366
- ten minutes for this cleanup attempt, stops the agent, closes its workspace, removes the matching worktree
1367
- and marks the local row done. Done, release and force withdrawal have the same terminal
1368
- resource rule. Failed stop or deletion retains responsibility and the error.
1369
-
1370
- Known-target cleanup and shutdown observe that Herdr execution directly;
1371
- worktree deletion validates only its target Git registration and directory.
1372
- Unrelated repository or sibling-worktree registration errors are reported
1373
- separately and do not prevent a healthy agent from stopping.
1506
+ temporary files, services and processes outside the worktree. It waits until
1507
+ cleanup completes or the original ten-minute deadline expires, then stops the
1508
+ agent, closes its workspace, removes the matching worktree and marks the local
1509
+ row done. Done, release and force withdrawal have the same terminal
1510
+ resource rule. Cleanup observations, notification, stop/close, and worktree
1511
+ verification and deletion each have a five-minute operation budget, including
1512
+ their RPC, cleanup provenance HTTP verification, Controller cleanup requests
1513
+ and Git commands. Notification and
1514
+ Controller cleanup-response waits are also capped by the remaining ten-minute
1515
+ agent deadline. Ordinary execution keeps its existing operation budgets. Failed
1516
+ stop or deletion retains responsibility and the error.
1517
+
1518
+ Known-target cleanup observes that Herdr execution directly; worktree deletion
1519
+ validates only its target Git registration and directory. Shutdown proves the
1520
+ original processes stopped without depending on Git discovery or cleanup retry
1521
+ backoff. Unrelated repository or sibling-worktree registration errors are
1522
+ reported separately and do not prevent a healthy agent from stopping.
1374
1523
 
1375
1524
  After the cleanup message is successfully submitted, a subsequent patrol that
1376
1525
  observes idle completes the cleanup turn and proceeds to stop the agent and
@@ -1381,20 +1530,35 @@ and the current bounded wait, without automatic replay. Reaching the deadline
1381
1530
  still proceeds through actual stop confirmation. Idle in this terminal cleanup
1382
1531
  phase does not complete the business task.
1383
1532
 
1384
- Cleanup timing and progress are in memory. Polls do not extend the current
1385
- attempt's deadline; after a crash, the next successful reconciliation observes
1386
- remaining resources and starts a new cleanup attempt and timer. Cleanup prompts
1387
- may repeat. Separate tasks have independent bounded jobs, so one held RPC does
1388
- not postpone another task's cleanup. A cleanup already selected in the current
1389
- process can continue during later service-read failures.
1533
+ Terminal cleanup is recorded before notification or resource removal. The
1534
+ original deadline and notification submission state survive failure, cancellation
1535
+ and restart; a cleanup notification with an unknown submission result is not
1536
+ replayed. Restart restores the
1537
+ same claim's responsibility and observes actual remaining resources without
1538
+ starting business execution. Previously confirmed cleanup can continue during
1539
+ later service-read failures.
1540
+
1541
+ Failed claims retry independently after 1, 2, 4, 8, 16, 32 and then at most 60
1542
+ seconds, when normal reconciliation next observes eligibility. Backoff does not
1543
+ spend execution recovery budget or release a capacity slot. Other eligible
1544
+ cleanup and healthy execution continue under the existing capacity limit. Errors
1545
+ identify the failed stage and next retry time, distinguishing unconfirmed native
1546
+ stop from a stopped agent awaiting backend closure, archive upload or worktree
1547
+ removal. If a retry-state write fails, the current process retains bounded
1548
+ backoff and both errors without claiming that the latest decision is durable.
1390
1549
 
1391
1550
  Ctrl+C stops acquisition and scheduling, cancels all running jobs including
1392
1551
  terminal cleanup, and joins them before directly stopping agents and closing
1393
- their workspaces. Process exit sends no cleanup prompt and does not wait for a
1394
- cleanup turn. It preserves claims, worktrees, native session IDs and all
1395
- unfinished active/pending rows, including those whose ownership has ended. The
1396
- next run uses normal inventory reconciliation to re-enter terminal cleanup for
1397
- ended claims. External temporary resources may remain after direct interruption.
1552
+ their workspaces. Process exit sends no cleanup prompt, does not wait for a
1553
+ cleanup turn or retry backoff, and does not repeat archive upload or worktree
1554
+ removal. It preserves claims, worktrees, native session IDs, unfinished
1555
+ active/pending rows and existing terminal cleanup schedules, including ended
1556
+ claims. The next run restores each saved responsibility, original deadline and
1557
+ notification state, then verifies remaining resources. A retained Herdr cleanup
1558
+ still requires its original backend even if current configuration uses Web;
1559
+ backend initialization and retries remain local to that cleanup job and cannot
1560
+ block unrelated Web execution. External temporary resources may remain after
1561
+ direct interruption.
1398
1562
  Normal completion, release, withdrawal and manual-control cleanup retain their
1399
1563
  notification and removal sequence. Pending stop confirmations must settle before the private
1400
1564
  Herdr instance stops; stop errors remain visible, and uncertain stopping retains
@@ -1462,12 +1626,31 @@ requires proof that the original native processes stopped and the exact native
1462
1626
  session ID. A missing journal or ID cannot authorize a replacement conversation.
1463
1627
  Unknown initial inputs and operations are reconciled without replay.
1464
1628
 
1629
+ Web recovery counts and diagnostic pause reasons persist across worker restarts.
1630
+ Exhausted automatic recovery or the execution failure threshold pauses the
1631
+ original execution before worktree preparation, Controller initialization,
1632
+ launch or native input. An older exhausted stopped record without a pause reason
1633
+ or orderly-shutdown provenance is reconciled from its journal and complete
1634
+ process-stop proof before any launch;
1635
+ uncertain stop evidence retains a diagnostic wait. A healthy final recovery
1636
+ and its orderly shutdown restart are not paused merely because the count has
1637
+ reached its limit.
1638
+
1639
+ A paused execution keeps its active claim, native session ID, worktree and
1640
+ capacity slot. The worker continues publishing `waiting` with `herdr:null` even
1641
+ when execution is blocked. A failed summary update is retried using a newly read
1642
+ task version without consuming native recovery budget; an unchanged confirmed
1643
+ summary is not written again. Ordinary restart and shutdown cannot clear this
1644
+ pause. It is separate from `task.properties.paused`, which controls Herdr
1645
+ continuation pings.
1646
+
1465
1647
  Normal Web terminal cleanup keeps its original cleanup operation and deadline,
1466
1648
  then proves native stop before deleting the task worktree. Worker shutdown stops
1467
1649
  owned processes while preserving unfinished claims, worktrees and native history.
1468
1650
  The [session design](../../docs/design/task-session-protocol.md) owns stopping,
1469
- recovery and relay details; the Herdr lifecycle above retains its process-local
1470
- recovery and cleanup semantics.
1651
+ recovery and relay details. Herdr business recovery remains process-local; both
1652
+ modes retain terminal cleanup responsibility, its original deadline and
1653
+ notification state in the independent schedule.
1471
1654
 
1472
1655
  The worker starts `daynight controller codex|claude|copilot --launch-id <uuid>`
1473
1656
  from a private immutable launch ticket. Its cwd, profile, claim, generation,
@@ -1561,11 +1744,22 @@ Retry performs one attempt for an active claim still owned by this worker:
1561
1744
  daynight worker retry <task-id> --claim-id <claim-id> --project <project-id>
1562
1745
  ```
1563
1746
 
1564
- It connects the live agent or resumes its recorded native session. A NULL ID
1565
- starts a fresh conversation in the same task worktree with an `info` event. The
1566
- claim and agent type remain; pending rows are started through normal run
1567
- scheduling. After the attempt, run connects to the actual surviving resource. Retry does not
1568
- persist a permit or a cumulative cross-restart budget.
1747
+ In Herdr mode, retry connects the live agent or resumes its recorded native
1748
+ session. A NULL ID starts a fresh conversation in the same task worktree with an
1749
+ `info` event. Its extra attempt and recovery count remain process-local.
1750
+
1751
+ In Web mode, retry persists one authorization to recover the original native
1752
+ session. It still requires the original active claim, matching generation and
1753
+ complete proof that the old processes stopped. Missing native identity or stop
1754
+ evidence cannot authorize a replacement conversation or a repeated initial
1755
+ assignment. Authorization does not report successful execution: the summary
1756
+ remains waiting through initialization until a ready or working observation, and failure
1757
+ pauses again. The attempt remains bound to that generation across ticks and
1758
+ worker restarts; initialization cannot authorize another generation.
1759
+
1760
+ Both modes retain the claim and agent type; pending rows are started through
1761
+ normal run scheduling. After the attempt, run reconciles the actual surviving
1762
+ resource and any persistent Web pause.
1569
1763
 
1570
1764
  Release validates current Project access, source owner/admin, original claim
1571
1765
  and exact supplied version. Its ordering is:
@@ -1594,6 +1788,10 @@ daynight worker resume <task-id> --claim-id <released-claim-id> --if-version <ve
1594
1788
  ```
1595
1789
 
1596
1790
  Resume requires the previous released claim, ready task and original owner/admin.
1791
+ Remote Worker control reads the caller's current `/projects/{id}/access`
1792
+ projection for administrator authority and verifies its project/principal binding;
1793
+ member profile reads retain their separate directory responsibility. Grant
1794
+ versions preserve the full positive int64 range.
1597
1795
  It preserves the explicit manual permission/platform exception, obtains fresh
1598
1796
  claim/worktree identities with current settings, and registers pending with a
1599
1797
  NULL native session ID. Start run to execute it.
@@ -1,5 +1,6 @@
1
+ import type { ThreadReadQuery, PostThreadMessageInput, ThreadMessage, ThreadPage } from "./types.js";
1
2
  import type { Operation } from "./operation.js";
2
- import type { AttachmentConsumer, CreateProjectInput, CreateTaskInput, DeleteTaskInput, ErrorDetails, Project, ProjectMember, PutTaskAttachmentInput, ReadyTaskFilters, ServerError, Task, SetTaskStatusInput, TaskAttachment, TaskFilters, TaskGraph, UpdateTaskInput, ClaimWorkerTaskInput, CompleteWorkerTaskInput, ReleaseWorkerClaimInput, ResumeWorkerTaskInput, WithdrawWorkerClaimInput, UpdateWorkerClaimInput, User, Page, TaskPageQuery, WorkerReport, WorkerReportReceipt, TaskPropertyResource, TaskPropertySchema, SetTaskPropertyInput, RemoveTaskPropertyInput } from "./types.js";
3
+ import type { AttachmentConsumer, CreateProjectInput, CreateTaskInput, DeleteTaskInput, ErrorDetails, Project, ProjectAccess, ProjectMember, PutTaskAttachmentInput, ReadyTaskFilters, ServerError, Task, SetTaskStatusInput, TaskAttachment, TaskFilters, TaskGraph, UpdateTaskInput, ClaimWorkerTaskInput, CompleteWorkerTaskInput, ReleaseWorkerClaimInput, ResumeWorkerTaskInput, WithdrawWorkerClaimInput, UpdateWorkerClaimInput, User, Page, TaskPageQuery, WorkerReport, WorkerReportReceipt, TaskPropertyResource, TaskPropertySchema, SetTaskPropertyInput, RemoveTaskPropertyInput } from "./types.js";
3
4
  type Context = {
4
5
  readonly operation: string;
5
6
  readonly projectId?: string;
@@ -17,19 +18,24 @@ export declare class ApiError extends Error {
17
18
  readonly details?: ErrorDetails;
18
19
  readonly outcomeUnconfirmed: boolean;
19
20
  readonly confirmedRefusal: boolean;
21
+ readonly confirmedMessageId?: string;
20
22
  constructor(context: Context, phase: ApiPhase, options: {
21
23
  readonly cause: unknown;
22
24
  readonly status?: number;
23
25
  readonly serverError?: ServerError;
24
26
  readonly outcomeUnconfirmed?: boolean;
25
27
  readonly confirmedRefusal?: boolean;
28
+ readonly confirmedMessageId?: string;
26
29
  });
27
30
  }
28
31
  export type ApiClient = {
32
+ readTaskThread(projectId: string, taskId: string, query: ThreadReadQuery): Promise<ThreadPage>;
33
+ postTaskThreadMessage(projectId: string, taskId: string, input: PostThreadMessageInput): Promise<ThreadMessage>;
29
34
  getCurrentUser(): Promise<User>;
30
35
  reportWorker(workerId: string, input: WorkerReport): Promise<WorkerReportReceipt>;
31
36
  createProject(input: CreateProjectInput): Promise<Project>;
32
37
  getProject(projectId: string): Promise<Project>;
38
+ getProjectAccess(projectId: string): Promise<ProjectAccess>;
33
39
  listProjects(): Promise<readonly Project[]>;
34
40
  listProjectMembers(projectId: string): Promise<readonly ProjectMember[]>;
35
41
  createTask(projectId: string, input: CreateTaskInput): Promise<Task>;