subharness 0.0.1 → 0.0.3

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 (120) hide show
  1. package/LICENSE +201 -21
  2. package/README.md +51 -18
  3. package/dist/adapters/claude-process.d.ts +10 -0
  4. package/dist/adapters/claude-process.js +58 -0
  5. package/dist/adapters/claude-process.js.map +1 -0
  6. package/dist/adapters/claude.js +52 -10
  7. package/dist/adapters/claude.js.map +1 -1
  8. package/dist/adapters/codex-input.d.ts +2 -0
  9. package/dist/adapters/codex-input.js +14 -0
  10. package/dist/adapters/codex-input.js.map +1 -0
  11. package/dist/adapters/codex-permissions.d.ts +13 -0
  12. package/dist/adapters/codex-permissions.js +30 -0
  13. package/dist/adapters/codex-permissions.js.map +1 -0
  14. package/dist/adapters/codex.js +12 -6
  15. package/dist/adapters/codex.js.map +1 -1
  16. package/dist/adapters/fx-auth.js +3 -0
  17. package/dist/adapters/fx-auth.js.map +1 -1
  18. package/dist/adapters/fx-permissions.d.ts +3 -0
  19. package/dist/adapters/fx-permissions.js +128 -0
  20. package/dist/adapters/fx-permissions.js.map +1 -0
  21. package/dist/adapters/fx.js +4 -0
  22. package/dist/adapters/fx.js.map +1 -1
  23. package/dist/cli/args.d.ts +3 -1
  24. package/dist/cli/args.js +18 -12
  25. package/dist/cli/args.js.map +1 -1
  26. package/dist/cli/dashboard-client.d.ts +3 -0
  27. package/dist/cli/dashboard-client.js +78 -0
  28. package/dist/cli/dashboard-client.js.map +1 -0
  29. package/dist/cli/dashboard-layout.d.ts +21 -0
  30. package/dist/cli/dashboard-layout.js +211 -0
  31. package/dist/cli/dashboard-layout.js.map +1 -0
  32. package/dist/cli/dashboard-renderer.d.ts +30 -0
  33. package/dist/cli/dashboard-renderer.js +80 -0
  34. package/dist/cli/dashboard-renderer.js.map +1 -0
  35. package/dist/cli/dashboard.d.ts +31 -0
  36. package/dist/cli/dashboard.js +81 -0
  37. package/dist/cli/dashboard.js.map +1 -0
  38. package/dist/cli/help.d.ts +1 -1
  39. package/dist/cli/help.js +35 -9
  40. package/dist/cli/help.js.map +1 -1
  41. package/dist/cli/main.js +19 -6
  42. package/dist/cli/main.js.map +1 -1
  43. package/dist/cli/output.js +10 -1
  44. package/dist/cli/output.js.map +1 -1
  45. package/dist/config/access.js +4 -4
  46. package/dist/config/access.js.map +1 -1
  47. package/dist/config/loader.js +2 -2
  48. package/dist/config/loader.js.map +1 -1
  49. package/dist/runtime/client.d.ts +5 -1
  50. package/dist/runtime/client.js +91 -40
  51. package/dist/runtime/client.js.map +1 -1
  52. package/dist/runtime/coordinator.d.ts +7 -1
  53. package/dist/runtime/coordinator.js +72 -8
  54. package/dist/runtime/coordinator.js.map +1 -1
  55. package/dist/runtime/daemon.js +100 -18
  56. package/dist/runtime/daemon.js.map +1 -1
  57. package/dist/runtime/dashboard-workspace.d.ts +2 -0
  58. package/dist/runtime/dashboard-workspace.js +38 -0
  59. package/dist/runtime/dashboard-workspace.js.map +1 -0
  60. package/dist/runtime/dashboard.d.ts +28 -0
  61. package/dist/runtime/dashboard.js +19 -0
  62. package/dist/runtime/dashboard.js.map +1 -0
  63. package/dist/runtime/readiness.d.ts +4 -0
  64. package/dist/runtime/readiness.js +17 -0
  65. package/dist/runtime/readiness.js.map +1 -0
  66. package/dist/runtime/select-native.d.ts +2 -1
  67. package/dist/runtime/select-native.js +5 -3
  68. package/dist/runtime/select-native.js.map +1 -1
  69. package/dist/runtime/service.d.ts +1 -1
  70. package/dist/runtime/service.js +10 -3
  71. package/dist/runtime/service.js.map +1 -1
  72. package/dist/runtime/startup-lock.d.ts +5 -0
  73. package/dist/runtime/startup-lock.js +37 -0
  74. package/dist/runtime/startup-lock.js.map +1 -0
  75. package/dist/runtime/startup-protocol.d.ts +17 -0
  76. package/dist/runtime/startup-protocol.js +23 -0
  77. package/dist/runtime/startup-protocol.js.map +1 -0
  78. package/dist/runtime/state.d.ts +1 -2
  79. package/dist/runtime/state.js +8 -43
  80. package/dist/runtime/state.js.map +1 -1
  81. package/dist/runtime/types.d.ts +16 -2
  82. package/dist/runtime/types.js.map +1 -1
  83. package/dist/runtime/worker-client.d.ts +7 -2
  84. package/dist/runtime/worker-client.js +69 -12
  85. package/dist/runtime/worker-client.js.map +1 -1
  86. package/dist/runtime/worker-server.d.ts +7 -0
  87. package/dist/runtime/worker-server.js +101 -0
  88. package/dist/runtime/worker-server.js.map +1 -0
  89. package/dist/runtime/worker.js +2 -66
  90. package/dist/runtime/worker.js.map +1 -1
  91. package/dist/sdk/definitions.js +23 -13
  92. package/dist/sdk/definitions.js.map +1 -1
  93. package/dist/sdk/permission-validation.d.ts +4 -0
  94. package/dist/sdk/permission-validation.js +55 -0
  95. package/dist/sdk/permission-validation.js.map +1 -0
  96. package/dist/sdk/types.d.ts +14 -0
  97. package/dist/sdk/types.js.map +1 -1
  98. package/package.json +17 -17
  99. package/sdk/access-config.md +4 -2
  100. package/sdk/adapter-contract.md +14 -2
  101. package/sdk/agent-skill.md +38 -0
  102. package/sdk/agent.md +6 -2
  103. package/sdk/cli/dashboard-design.md +40 -0
  104. package/sdk/cli/index.md +47 -13
  105. package/sdk/cli/output.md +21 -3
  106. package/sdk/completion-notifications.md +9 -5
  107. package/sdk/config.md +33 -8
  108. package/sdk/distribution.md +21 -7
  109. package/sdk/evals.md +171 -0
  110. package/sdk/fx.md +4 -3
  111. package/sdk/harnesses.md +6 -0
  112. package/sdk/index.md +2 -0
  113. package/sdk/message-delivery.md +6 -2
  114. package/sdk/permissions.md +65 -0
  115. package/sdk/plugins/sub-agents.md +7 -4
  116. package/sdk/pr-integration.md +37 -0
  117. package/sdk/project-team.md +13 -8
  118. package/sdk/sessions.md +1 -1
  119. package/sdk/tools.md +2 -0
  120. package/sdk/v1-runtime.md +22 -7
package/sdk/v1-runtime.md CHANGED
@@ -16,25 +16,33 @@ Custom tools accept Zod 4 object schemas that can be represented as JSON Schema.
16
16
 
17
17
  ## Discovery and loading
18
18
 
19
- Global definitions live in `~/.agents/agents/`; repository definitions live in `.agents/agents/` at the execution worktree root. Outside Git, the supplied directory is the project root. Bare repositories are unsupported execution directories. Nested repositories use the nearest Git worktree root. Symlink directories are not traversed during discovery.
19
+ Global definitions live in `~/.subharness/agents/`; repository definitions live in `.subharness/agents/` at the execution worktree root. Every `.ts` file under those directories except `.d.ts` declarations is a definition entry; see [agent discovery](config.md). Outside Git, the supplied directory is the project root. Bare repositories are unsupported execution directories. Nested repositories use the nearest Git worktree root. Symlink directories are not traversed during discovery.
20
20
 
21
21
  Definitions are trusted executable TypeScript. Loading a catalog evaluates its modules, so callers must trust the selected project and global definition files. Imports resolve relative to each definition through normal Node package resolution, with TypeScript loading supplied by the CLI. Missing imports, invalid exports, and duplicate names fail with the source filename. A session retains its loaded instructions, tools, and harness configuration for follow-ups; new sessions load current definition sources.
22
22
 
23
- An omitted `--cwd` uses the command's working directory. `--prompt-file` paths resolve against the calling command's directory, independently of `--cwd`; files use UTF-8. Prompts must contain non-whitespace text and cannot exceed 1 MiB. One quoted positional prompt, `--prompt`, and `--prompt-file` are mutually exclusive. `--prompt-file -` reads bounded UTF-8 stdin to EOF and rejects a terminal input stream. Direct harness targets accept `--model` and `--effort`; specialist targets reject those overrides.
23
+ An omitted `--cwd` uses the command's working directory. `--prompt-file` paths resolve against the calling command's directory, independently of `--cwd`; files use UTF-8. Prompts must contain non-whitespace text and cannot exceed 1 MiB. One quoted positional prompt, `--prompt`, and `--prompt-file` are mutually exclusive. `--prompt-file -` reads bounded UTF-8 stdin to EOF and rejects a terminal input stream. Direct harness targets accept `--model` and `--effort` for `run` and `check`; specialist targets reject those overrides.
24
+
25
+ `run` and task-creating `send` commands accept `--detach` with every prompt source. The option ends the requesting command's observation immediately after successful admission, so the command returns exactly the existing `started` record and exits `0`. The service explicitly completes that observation response; it does not rely on a caller abandoning a response body. Admission errors keep their records and exit codes, while later failures remain available through `wait` and `status`. Interrupt delivery confirms affected execution has stopped before replacement admission even when detached. Steering rejects `--detach` with `INVALID_ARGUMENT`. The option is an observation request and is never retained as session configuration.
24
26
 
25
27
  ## Execution ownership
26
28
 
27
29
  An on-demand local coordinator owns sessions, queues, task relationships, and response records independently of individual CLI commands. It starts automatically; users do not install or manage a service. Each native session runs in a separate worker process whose working directory is the selected execution directory. Definition loading and custom tool execution in that worker use the same directory. Direct harness sessions carry a built-in target descriptor instead of a definition source reference and do not load TypeScript modules. They supply no specialist instructions, custom tools, or declared children; native instructions and project settings remain effective. Workers inherit the submitting environment, subject to the adapter's explicit authentication selection.
28
30
 
29
- The coordinator accepts local connections only. Its endpoint and access token are stored with owner-only permissions under `~/.agents/state/`. Task and session identifiers resolve through this coordinator from any working directory. Child invocation context is supplied privately by a session launcher that restores the coordinator location and parent context even when native shells change the inherited environment. Launchers use owner-only permissions, contain no provider credentials, and are removed when the session worker closes. Users do not supply parent identifiers or tokens in command flags. A context is accepted only while its parent task allows delegation.
31
+ `check` is a CLI startup probe rather than an execution operation. It resolves the target and access configuration as `run` does, opens the native session in an isolated worker, and closes it without admitting a task or calling the adapter's turn interface. Success is withheld until the isolated worker exits and adapter-owned native processes confirm termination. Cleanup failure or uncertain native termination produces an error; after a failed graceful close, worker termination remains bounded and retains the cleanup diagnostic. It does not expose an SDK execution method and does not require a coordinator for ordinary direct or specialist checks. Managed declared-child resolution still requires the active parent context used by `run`.
32
+
33
+ Readiness means only that the selected target's startup checks passed at that moment. It does not guarantee quota, successful task execution, shell or child-launch permissions, or continued availability, and it does not recursively check descendants. The probe may create an empty native conversation, a temporary session launcher, and adapter-owned temporary files. Loading personal access settings may update Git's local exclude file. Normal worker close removes library-owned temporary files. A removal failure is reported even though files can remain, and abrupt environment termination still cannot guarantee file cleanup.
34
+
35
+ The coordinator accepts local connections only. Its endpoint, instance identifier, and access token are stored with owner-only permissions under `~/.subharness/state/`. Task and session identifiers resolve through this coordinator from any working directory. Child invocation context is supplied privately by a session launcher that restores the coordinator location and parent context even when native shells change the inherited environment. Launchers use owner-only permissions, contain no provider credentials, and are removed when the session worker closes. Users do not supply parent identifiers or tokens in command flags. A context is accepted only while its parent task allows delegation.
30
36
 
31
37
  Closing a response-reading command does not cancel work. The coordinator retains responses and session records for its lifetime. A coordinator restart does not replay tasks or reconstruct queues; unavailable identifiers return an explicit error. Native harness history may still exist, but this version does not promise recovery of library sessions after coordinator or environment exit. Responses are not consumed by readers; each reader supplies its own position. Records are not silently evicted while the coordinator is running.
32
38
 
33
39
  ## Task states and responses
34
40
 
41
+ The coordinator supplies the terminal dashboard with a read-only snapshot of current session work followed by retained finished tasks, including failed active tasks that pause a queue. Each task appears at most once, and retained history is available to newly opened dashboards for the coordinator’s lifetime. The private snapshot includes an explicit finished-history and grouped-context capability markers so the CLI can reject older incompatible coordinators. It carries only session/task identity, selected harness, bounded prompt title, task state, canonical checkout/repository paths, and timestamps needed by the display; it excludes environment variables, credentials, definitions, transcripts, and native diagnostics. Reading it does not acknowledge responses or change task execution. Workers report the actual selected harness to the coordinator after native startup succeeds. Task timing records the first dispatch, latest failure, and terminal completion or confirmed-stop time without resetting on native continuations. Finished rows retain a fixed elapsed duration; recovery clears terminal timing for the resumed task. Snapshot observation adds no public SDK execution method or persistent history. The display contract is defined in [CLI](cli/index.md#live-dashboard).
42
+
35
43
  Task states are `queued`, `running`, `waiting`, `completed`, `failed`, `cancelled`, and `interrupted`. `waiting` means the library task remains active between native turns while delegated work or child-result processing is pending. A native permission request is not a completed response. Terminal outcomes are `completed`, `failed`, `cancelled`, and `interrupted`.
36
44
 
37
- Each complete native response has an opaque response identifier, text, and the task state at that response. `wait --after` returns the next retained response in order, including one that arrived before the command started. If none remains and the task is terminal, it returns the terminal outcome. Unknown response identifiers, including identifiers from another task, are errors. Multiple observers can independently read the same response.
45
+ Each complete native response has an opaque response identifier, text, and the task state at that response. `wait` without `--after` returns the first retained response in order, including one that arrived before the command started, or awaits it. Omission does not select the latest response or begin observation at the current time. `wait --after <response-id>` returns the next retained response after that cursor. If no selected response remains and the task is terminal, it returns the terminal outcome. Unknown response identifiers, including identifiers from another task, are errors. Multiple observers can independently read the same response.
38
46
 
39
47
  ## Queue and recovery rules
40
48
 
@@ -52,12 +60,19 @@ New follow-up tasks in a child session belong to the currently invoking parent t
52
60
 
53
61
  ## Permissions and bounds
54
62
 
55
- Adapters preserve native permission restrictions. Declaring subagents authorizes their invocation: Claude Code receives session-only native allow rules for the exact launcher and documented delegation operations, combined with permissions for declared custom tools. This does not change the native permission mode, user/project settings, explicit deny or approval rules, managed policy, or sandbox. This version does not provide an interactive permission-answer CLI: a native approval or input request that still cannot be handled under that policy fails the task with `INPUT_REQUIRED` and actionable guidance. The permission callback never automatically approves the request. The caller can configure its harness and explicitly recover where supported.
63
+ Adapters preserve native permission restrictions. Declaring subagents authorizes their invocation: Claude Code receives session-only native allow rules for the exact launcher and documented delegation operations, combined with permissions for declared custom tools. These delegation rules do not themselves change native modes, managed policy, or sandbox boundaries. Explicit constructor options separately select session-native permissions under [Native Permissions](permissions.md); persistent user/project settings are unchanged. This version does not provide an interactive permission-answer CLI: a native approval or input request that still cannot be handled under that policy fails the task with `INPUT_REQUIRED` and actionable guidance. The permission callback never automatically approves the request. The caller can configure its harness and explicitly recover where supported.
56
64
 
57
- Ordinary text/JSON tool results and complete responses are limited to 1 MiB. Rich tool results have the image and aggregate limits defined in [custom tools](tools.md). Oversized results produce explicit errors rather than silent truncation. `status` includes at most 4,000 characters of the latest response and marks truncation; `status --full` retrieves the complete latest response and `wait` observes subsequent complete responses. Delegation depth is limited to 8, and each session admits at most 100 pending tasks. Exceeding a bound fails admission without dropping existing work. No automatic task-duration deadline is imposed.
65
+ Ordinary text/JSON tool results and complete responses are limited to 1 MiB. Rich tool results have the image and aggregate limits defined in [custom tools](tools.md). Oversized results produce explicit errors rather than silent truncation. `status` includes at most 4,000 characters of the latest response and marks truncation; `status --full` retrieves the complete latest response, while `wait` observes the first response or a subsequent response selected by a cursor. Delegation depth is limited to 8, and each session admits at most 100 pending tasks. Exceeding a bound fails admission without dropping existing work. No automatic task-duration deadline is imposed.
58
66
 
59
67
  A managed task cannot delegate follow-up work into its own session or an ancestor's session. Such an admission returns `INVALID_PARENT` before changing any execution: that queued work would otherwise wait for the very task whose completion depends on it. Invalid delegation and replacement requests never cancel existing work.
60
68
 
61
- Coordinator startup recovers stale local startup locks whose recorded owner is absent or invalid. It never removes a lock owned by a live process and rechecks the file before removing it. An interrupted coordinator response is reported as unavailable without exposing native diagnostics or automatically repeating the request. Disconnecting an observer detaches that observation; it does not cancel execution.
69
+ Each candidate coordinator, rather than the CLI command that spawned it, holds an operating-system-backed startup lock from its final endpoint check through service startup and atomic endpoint publication. The lock is released automatically if the candidate exits. After acquiring it, a candidate retires without publishing when the retained endpoint gives an authenticated health response for the recorded coordinator instance. This prevents a caller exit or a later candidate from exposing competing endpoint publication.
70
+
71
+ Startup callers do not infer whether their candidate published from an endpoint observation and do not signal a candidate based on such an observation. When its startup deadline expires, a caller sends its candidate a private retirement request. The candidate serializes that request with its publication transition while it still owns the startup lock. If retirement wins, the candidate closes any service that was never published, releases startup ownership, and confirms that it cannot publish later. If publication wins, including when another caller has already admitted work, the candidate reports its published endpoint and remains running. The original caller then uses that endpoint instead of terminating the coordinator.
72
+
73
+ Lock contention is bounded by the spawning command's startup deadline. Waiting for the candidate's publication-or-retirement response uses an additional fixed confirmation window, so command completion remains bounded. If the candidate does not respond, startup fails with `STARTUP_FAILED` stating that retirement could not be confirmed, and the caller leaves the candidate untouched. A later authenticated endpoint discovery may therefore find that candidate. An unconfirmed result never claims that the process stopped and never authorizes killing a potentially published coordinator.
74
+
75
+ Coordinators leave endpoint records in place during shutdown. Legacy pathname lock artifacts do not grant startup ownership and are left untouched. An unavailable endpoint, an unrelated HTTP server on the recorded port, or a legacy record without the current authenticated instance identity does not suppress replacement startup. A replacement coordinator atomically overwrites the record, and tasks owned by a replaced coordinator are not reconstructed. An interrupted coordinator response is reported as unavailable without exposing native diagnostics or automatically repeating the request. Disconnecting an observer detaches that observation; it does not cancel execution.
76
+ A successful detached task-creation request ends its service observation explicitly after the admission record while the coordinator continues to own the task.
62
77
 
63
78
  Catalog discovery evaluates TypeScript in a short-lived process with the selected execution directory as its working directory. Module stdout and stderr are not mixed into CLI output. Session workers retain their loaded instructions, tools, and harness configuration. New sessions, including delegated child sessions, load the current definition source; the library does not serialize or freeze arbitrary TypeScript closures across sessions.