jg-agent-hq 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/LICENSE +21 -0
  3. package/README.md +104 -2
  4. package/api/README.md +253 -0
  5. package/dist/actions/actions.d.ts +50 -0
  6. package/dist/actions/actions.js +911 -0
  7. package/dist/actions/index.d.ts +2 -0
  8. package/dist/actions/index.js +3 -0
  9. package/dist/actions/live/index.d.ts +1 -0
  10. package/dist/actions/live/index.js +2 -0
  11. package/dist/actions/live/live.d.ts +32 -0
  12. package/dist/actions/live/live.js +133 -0
  13. package/dist/actions/reads.d.ts +17 -0
  14. package/dist/actions/reads.js +101 -0
  15. package/dist/cli/cli.d.ts +2 -0
  16. package/dist/cli/cli.js +232 -0
  17. package/dist/contracts/actions/index.d.ts +4 -0
  18. package/dist/contracts/actions/index.js +4 -0
  19. package/dist/contracts/actions/types.d.ts +547 -0
  20. package/dist/contracts/actions/types.js +199 -0
  21. package/dist/contracts/constants.d.ts +11 -0
  22. package/dist/contracts/constants.js +13 -0
  23. package/dist/contracts/handoffs/index.d.ts +2 -0
  24. package/dist/contracts/handoffs/index.js +2 -0
  25. package/dist/contracts/handoffs/types.d.ts +585 -0
  26. package/dist/contracts/handoffs/types.js +112 -0
  27. package/dist/contracts/identities/index.d.ts +1 -0
  28. package/dist/contracts/identities/index.js +2 -0
  29. package/dist/contracts/identities/types.d.ts +2 -0
  30. package/dist/contracts/identities/types.js +3 -0
  31. package/dist/contracts/index.d.ts +19 -0
  32. package/dist/contracts/index.js +20 -0
  33. package/dist/contracts/plans/index.d.ts +8 -0
  34. package/dist/contracts/plans/index.js +8 -0
  35. package/dist/contracts/plans/types.d.ts +2635 -0
  36. package/dist/contracts/plans/types.js +401 -0
  37. package/dist/contracts/skills/index.d.ts +2 -0
  38. package/dist/contracts/skills/index.js +2 -0
  39. package/dist/contracts/skills/types.d.ts +98 -0
  40. package/dist/contracts/skills/types.js +48 -0
  41. package/dist/contracts/types.d.ts +4746 -0
  42. package/dist/contracts/types.js +226 -0
  43. package/dist/errors/index.d.ts +1 -0
  44. package/dist/errors/index.js +2 -0
  45. package/dist/errors/utilities.d.ts +8 -0
  46. package/dist/errors/utilities.js +14 -0
  47. package/dist/handoffs/handoffs.d.ts +43 -0
  48. package/dist/handoffs/handoffs.js +449 -0
  49. package/dist/handoffs/index.d.ts +4 -0
  50. package/dist/handoffs/index.js +6 -0
  51. package/dist/handoffs/types.d.ts +492 -0
  52. package/dist/handoffs/types.js +29 -0
  53. package/dist/handoffs/utilities.d.ts +11 -0
  54. package/dist/handoffs/utilities.js +24 -0
  55. package/dist/index.d.ts +6 -0
  56. package/dist/index.js +7 -0
  57. package/dist/ipc/client.d.ts +20 -0
  58. package/dist/ipc/client.js +88 -0
  59. package/dist/ipc/constants.d.ts +5 -0
  60. package/dist/ipc/constants.js +6 -0
  61. package/dist/ipc/framing.d.ts +12 -0
  62. package/dist/ipc/framing.js +49 -0
  63. package/dist/ipc/index.d.ts +4 -0
  64. package/dist/ipc/index.js +6 -0
  65. package/dist/ipc/server.d.ts +11 -0
  66. package/dist/ipc/server.js +108 -0
  67. package/dist/locks/constants.d.ts +6 -0
  68. package/dist/locks/constants.js +11 -0
  69. package/dist/locks/index.d.ts +4 -0
  70. package/dist/locks/index.js +6 -0
  71. package/dist/locks/locks.d.ts +94 -0
  72. package/dist/locks/locks.js +327 -0
  73. package/dist/locks/types.d.ts +31 -0
  74. package/dist/locks/types.js +19 -0
  75. package/dist/plans/admission.d.ts +175 -0
  76. package/dist/plans/admission.js +232 -0
  77. package/dist/plans/authority.d.ts +13 -0
  78. package/dist/plans/authority.js +159 -0
  79. package/dist/plans/evidence.d.ts +11 -0
  80. package/dist/plans/evidence.js +176 -0
  81. package/dist/plans/files.d.ts +40 -0
  82. package/dist/plans/files.js +181 -0
  83. package/dist/plans/finalization.d.ts +13 -0
  84. package/dist/plans/finalization.js +35 -0
  85. package/dist/plans/index.d.ts +6 -0
  86. package/dist/plans/index.js +7 -0
  87. package/dist/plans/plans.d.ts +238 -0
  88. package/dist/plans/plans.js +673 -0
  89. package/dist/plans/projections.d.ts +13 -0
  90. package/dist/plans/projections.js +94 -0
  91. package/dist/plans/reconciliation.d.ts +34 -0
  92. package/dist/plans/reconciliation.js +239 -0
  93. package/dist/plans/revisions.d.ts +51 -0
  94. package/dist/plans/revisions.js +199 -0
  95. package/dist/plans/types.d.ts +379 -0
  96. package/dist/plans/types.js +63 -0
  97. package/dist/plans/utilities.d.ts +27 -0
  98. package/dist/plans/utilities.js +182 -0
  99. package/dist/providers/claude/claude.d.ts +35 -0
  100. package/dist/providers/claude/claude.js +131 -0
  101. package/dist/providers/claude/control/control.d.ts +101 -0
  102. package/dist/providers/claude/control/control.js +295 -0
  103. package/dist/providers/claude/control/index.d.ts +2 -0
  104. package/dist/providers/claude/control/index.js +2 -0
  105. package/dist/providers/claude/control/permissions.d.ts +9 -0
  106. package/dist/providers/claude/control/permissions.js +93 -0
  107. package/dist/providers/claude/control/skills.d.ts +8 -0
  108. package/dist/providers/claude/control/skills.js +51 -0
  109. package/dist/providers/claude/control/stream.d.ts +7 -0
  110. package/dist/providers/claude/control/stream.js +214 -0
  111. package/dist/providers/claude/control/types.d.ts +43 -0
  112. package/dist/providers/claude/control/types.js +1 -0
  113. package/dist/providers/claude/history/history.model.d.ts +31 -0
  114. package/dist/providers/claude/history/history.model.js +491 -0
  115. package/dist/providers/claude/history/index.d.ts +5 -0
  116. package/dist/providers/claude/history/index.js +7 -0
  117. package/dist/providers/claude/history/types.d.ts +1798 -0
  118. package/dist/providers/claude/history/types.js +52 -0
  119. package/dist/providers/claude/history/utilities.d.ts +22 -0
  120. package/dist/providers/claude/history/utilities.js +101 -0
  121. package/dist/providers/claude/index.d.ts +1 -0
  122. package/dist/providers/claude/index.js +2 -0
  123. package/dist/providers/claude/rpc.d.ts +42 -0
  124. package/dist/providers/claude/rpc.js +183 -0
  125. package/dist/providers/claude/transformers.d.ts +9 -0
  126. package/dist/providers/claude/transformers.js +43 -0
  127. package/dist/providers/claude/types.d.ts +33 -0
  128. package/dist/providers/claude/types.js +37 -0
  129. package/dist/providers/codex/approvals/index.d.ts +2 -0
  130. package/dist/providers/codex/approvals/index.js +2 -0
  131. package/dist/providers/codex/approvals/types.d.ts +195 -0
  132. package/dist/providers/codex/approvals/types.js +89 -0
  133. package/dist/providers/codex/approvals/utilities.d.ts +16 -0
  134. package/dist/providers/codex/approvals/utilities.js +108 -0
  135. package/dist/providers/codex/codex.d.ts +9 -0
  136. package/dist/providers/codex/codex.js +237 -0
  137. package/dist/providers/codex/index.d.ts +7 -0
  138. package/dist/providers/codex/index.js +6 -0
  139. package/dist/providers/codex/rpc.d.ts +20 -0
  140. package/dist/providers/codex/rpc.js +128 -0
  141. package/dist/providers/codex/transformers.d.ts +26 -0
  142. package/dist/providers/codex/transformers.js +130 -0
  143. package/dist/providers/codex/types.d.ts +246 -0
  144. package/dist/providers/codex/types.js +84 -0
  145. package/dist/providers/codex/validations.d.ts +8 -0
  146. package/dist/providers/codex/validations.js +14 -0
  147. package/dist/providers/index.d.ts +6 -0
  148. package/dist/providers/index.js +7 -0
  149. package/dist/providers/process.d.ts +8 -0
  150. package/dist/providers/process.js +117 -0
  151. package/dist/providers/types.d.ts +42 -0
  152. package/dist/providers/types.js +1 -0
  153. package/dist/runtime/index.d.ts +2 -0
  154. package/dist/runtime/index.js +2 -0
  155. package/dist/runtime/runtime.d.ts +20 -0
  156. package/dist/runtime/runtime.js +268 -0
  157. package/dist/runtime/state/constants.d.ts +3 -0
  158. package/dist/runtime/state/constants.js +4 -0
  159. package/dist/runtime/state/index.d.ts +2 -0
  160. package/dist/runtime/state/index.js +3 -0
  161. package/dist/runtime/state/state.d.ts +74 -0
  162. package/dist/runtime/state/state.js +241 -0
  163. package/dist/runtime/types.d.ts +60 -0
  164. package/dist/runtime/types.js +13 -0
  165. package/dist/sessions/index.d.ts +3 -0
  166. package/dist/sessions/index.js +4 -0
  167. package/dist/sessions/names/index.d.ts +1 -0
  168. package/dist/sessions/names/index.js +2 -0
  169. package/dist/sessions/names/utilities.d.ts +4 -0
  170. package/dist/sessions/names/utilities.js +12 -0
  171. package/dist/sessions/sessions.d.ts +14 -0
  172. package/dist/sessions/sessions.js +87 -0
  173. package/dist/sessions/types.d.ts +4 -0
  174. package/dist/sessions/types.js +1 -0
  175. package/dist/sessions/utilities.d.ts +9 -0
  176. package/dist/sessions/utilities.js +38 -0
  177. package/dist/skills/index.d.ts +1 -0
  178. package/dist/skills/index.js +2 -0
  179. package/dist/skills/skills.d.ts +50 -0
  180. package/dist/skills/skills.js +179 -0
  181. package/dist/store/control/constants.d.ts +5 -0
  182. package/dist/store/control/constants.js +7 -0
  183. package/dist/store/control/control.model.d.ts +96 -0
  184. package/dist/store/control/control.model.js +827 -0
  185. package/dist/store/control/index.d.ts +4 -0
  186. package/dist/store/control/index.js +4 -0
  187. package/dist/store/control/transformers.d.ts +8 -0
  188. package/dist/store/control/transformers.js +42 -0
  189. package/dist/store/control/types.d.ts +871 -0
  190. package/dist/store/control/types.js +175 -0
  191. package/dist/store/handoffs/handoffs.model.d.ts +37 -0
  192. package/dist/store/handoffs/handoffs.model.js +147 -0
  193. package/dist/store/handoffs/index.d.ts +1 -0
  194. package/dist/store/handoffs/index.js +2 -0
  195. package/dist/store/index.d.ts +2 -0
  196. package/dist/store/index.js +2 -0
  197. package/dist/store/plans/index.d.ts +1 -0
  198. package/dist/store/plans/index.js +2 -0
  199. package/dist/store/plans/plans.model.d.ts +149 -0
  200. package/dist/store/plans/plans.model.js +201 -0
  201. package/dist/store/schema.sql +192 -0
  202. package/dist/store/store.d.ts +8 -0
  203. package/dist/store/store.js +181 -0
  204. package/dist/store/store.worker.d.ts +1 -0
  205. package/dist/store/store.worker.js +176 -0
  206. package/dist/store/types.d.ts +3485 -0
  207. package/dist/store/types.js +93 -0
  208. package/errors/README.md +83 -0
  209. package/package.json +59 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0
4
+
5
+ - Preserve coordinator-owned, revision-bound plan comparison evidence through plan operations. Expose its bounded count in status without copying review bodies into responses.
6
+ - Require the comparison collection in the coordination contract. The private coordinator owns semantic review, relevance selection and execution gates.
7
+
8
+ ## 0.1.0
9
+
10
+ - Add the shared lock API, owner-aware recovery and built-package verification.
11
+ - Add the standalone local controller, owner-only IPC and CLI, worker-owned SQLite discovery metadata, browser-safe contracts, native Codex history and actual subscription observations.
12
+ - Add exclusive Codex thread control, receipt-backed actions, live steering, explicit next-turn queues, native permissions/questions, uncertain-delivery reconciliation and bounded reconnect/live-history reads.
13
+ - Add native Claude subscription windows and a version-checked incremental history reader, with explicit unknown execution states and unavailable unsupported formats.
14
+ - Add persistent Claude session control, native question/permission replies, receipt-backed queued input and interruption, scoped provider failures and shared live presentation. Report unsupported Claude steering explicitly.
15
+ - Add short session-name suggestions, atomic creation suffixes and authorized case-insensitive name lookup in the local API and CLI.
16
+ - Add native skill catalogs, honest unavailable metadata, exact invocation previews and explicit text/skill input through the existing durable message and queue actions. Add trusted native skill-loading roots without global installation.
17
+ - Add execution and inspection digests, initial milestone UUID finalization, separate operator-bound plan/sequence approvals and scoped execution authority, recoverable file writes and bounded SQLite milestone projections.
18
+ - Add runtime-owned plan quiescence/checkpoints, operator-confirmed progress reconciliation, retained verification and partial checkout fingerprints, paused scoped input, external-edit interruption and paged revision evidence. Require fresh execution authority after revision or runtime restart.
19
+ - Add explicit cross-provider challenges, native finding collection and author feedback with replay-safe delivery and revision/identity guards.
20
+ - Add the private public-site workspace, canonical documentation pages, shared JG theme/components, generated social assets and offline build/browser verification. Keep website dependencies and assets outside the runtime package.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jesus Graterol
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,105 @@
1
- # Temporary Holding Version
1
+ # jg-agent-hq
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Workspace primitives for native coding agents. The public API provides owner-aware filesystem locks, Claude and Codex thread control, live input and history, actual account usage, and revision-bound plan authority.
4
+
5
+ Requires Node.js 24.15.0 or later on Linux or macOS. The lock protocol uses POSIX ownership, private directories and process-liveness probes. Windows is outside the supported host contract.
6
+
7
+ ## Installation
8
+
9
+ Install the package locally:
10
+
11
+ ```sh
12
+ npm install jg-agent-hq
13
+ npx jg-agent-hq serve --state-root .runtime --workspace-root .
14
+ ```
15
+
16
+ Install Claude Code and/or Codex separately and sign in through their native CLIs. Run the controller in your trusted workspace. The CLI examples below assume the installed executable is on PATH; prefix them with `npx` for a local npm installation.
17
+
18
+ This public package provides a local controller and browser-safe contracts. Applications own their UI, authentication and deployment. It does not include a hosted app or a Moldea UI download.
19
+
20
+ ## Development
21
+
22
+ Use pnpm 12.4.0. Run `pnpm install`, then `pnpm check:package` to build, exercise the built API and packed consumer, typecheck and check formatting. `pnpm test:unit` and `pnpm test:integration` select their own categories after a build. The private website workspace has separate checks; install Chromium with `pnpm --dir website exec playwright install chromium`, then run `pnpm --dir website check`. `pnpm check` runs both boundaries.
23
+
24
+ Work on `development`; reviewed changes reach `main` through a pull request. npm releases are manual and use the exact tested tarball.
25
+
26
+ ## Lock ownership
27
+
28
+ Callers supply a trusted state root. Locks live in its private `.runtime/hq.lock`. A holder records its process ID, nonce, safe operation label and creation time. Live holders are awaited. Dead, incomplete or unverifiable owners require inspection and are never automatically reclaimed, because child processes may remain alive.
29
+
30
+ Short metadata operations use `withHqLock`. Long-lived runtime ownership must use a separate owner record; never hold a metadata lock for an agent turn's lifetime. The lock coordinates cooperating processes and does not isolate hostile code running as the same OS user.
31
+
32
+ See the [API reference](api/README.md) and [error contracts](errors/README.md).
33
+
34
+ ## Local controller
35
+
36
+ Install Codex and sign in through its native CLI, then start `jg-agent-hq serve --state-root .runtime --workspace-root /path/to/workspace`. Run `jg-agent-hq status --state-root .runtime` in a client. `threads`, `thread`, `turns`, `items` and `usage` read native information; `stop` waits for confirmed runtime shutdown.
37
+
38
+ The Node API exposes `createAgentHq({ stateRoot, allowedRoots })` and `requestAgentHq(stateRoot, command)`. Configuration comes from these trusted operator inputs. Coding-instruction files are not runtime configuration.
39
+
40
+ The controller owns its SQLite worker and native connections independently of client connections. Private state contains the lifetime owner, Unix socket and SQLite discovery metadata. Conversation bodies remain in the native providers' storage. Browsing never resumes an external session or starts inference. Quota windows come from native account observations, with explicit stale and unavailable states.
41
+
42
+ The current read contracts were exercised against Codex 0.163.0 and Claude Code 2.1.304 on Linux. Unsupported native responses fail explicitly. `jg-agent-hq/contracts` contains browser-safe schemas and types; importing it does not import the host runtime.
43
+
44
+ Use `--provider claude` for Claude history and usage; the default is `codex`. Claude connects lazily through its native structured CLI, with normal settings enabled and no user prompt. Usage requests explicitly disable the optional transcript-behavior scan. Its local history reader supports the qualified 2.1.304 format only, keeps byte locations rather than conversation bodies in SQLite, and reports unsupported history as unavailable. File history cannot establish current execution state. See the [reader limits and freshness contract](api/README.md#claude-history).
45
+
46
+ Explicit actions create, name, adopt, resume and close threads; send idle messages; steer an exact running turn; queue the next message; interrupt; and answer native questions or permissions. Actions have stable UUIDs and durable receipts. Repeating the same request returns its receipt; changing that UUID's payload conflicts. A lost acknowledgement stays uncertain until the exact native response arrives or the operator makes an explicit recovery choice. HQ never resends uncertain input.
47
+
48
+ Native execution settings, instructions, skills and tool permissions remain with each CLI. Claude uses an owned structured process per controlled session and reports immediate steering as unavailable. Plan approval grants no native tool permission. Close other CLI controllers before confirming adoption, resume or recovery. HQ coordinates sessions sharing one state directory; it cannot lock independently running native CLIs. Durable state includes `action.key`, which must stay private and accompany its SQLite database. Queued undelivered text is saved; ordinary message bodies and question answers are not.
49
+
50
+ Use `suggest-thread-name --topic "Build usage" --state-root <directory>` for an editable label and `managed-thread-name --name build-usage --state-root <directory>` to resolve it. Creation adds a short ordinal suffix when a name is occupied. Actions and relationships retain immutable IDs.
51
+
52
+ Use `skills --thread-id <id> --state-root <directory>` to browse the controlled session's native skill catalog. `skill-preview --thread-id <id> --skill-id <id> --arguments "auto exact-plan" --state-root <directory>` shows the exact invocation without sending it. Missing native metadata is explicitly unavailable. The CLI loads all skill content and retains its permissions and invocation rules.
53
+
54
+ Use `jg-agent-hq request --state-root <directory>` with a closed HQ command on stdin for action and control reads. The [API reference](api/README.md) describes action envelopes, receipts and reconnect reads.
55
+
56
+ ## Plan coordination
57
+
58
+ `plan-status --directory <path>` and `plan-milestones --directory <path>` inspect a selected ordinary planning directory. No project registry is required. Mutations use the existing `request` JSON command with `kind: 'plan'`; see the [plan command reference](api/README.md#plan-coordination).
59
+
60
+ Finalization assigns milestone UUIDs and returns the complete canonical sequence. Plan approval, sequence approval and scoped execution authorization are separate explicit operator actions. None sends native input or answers tool permissions. `coordination.json` holds current records beside the plan. SQLite retains write replay identities and a replaceable, paged milestone projection. Keep both when recovering interrupted writes. A pending write blocks further mutation until its original action is reconciled.
61
+
62
+ Coordinators can retain revision-bound compatibility reviews in that same file. Core operations preserve the records without assessing them or granting authority. The integrating coordinator owns review freshness and conflict gates.
63
+
64
+ Begin a revision before native planning. HQ stops bound implementation threads and their owned background work, captures partial-work evidence, and keeps execution paused while the CLI revises the plan and regenerates milestones. The finalizer carries exact matches automatically and asks for one confirmation covering every unmatched completed or partial milestone. Equivalent rewording preserves the original completion evidence. Changed requirements remain pending. Present and approve the canonical sequence, then explicitly authorize the new execution scope and mode. Neither approval nor restart resumes implementation. See the [revision recovery contract](api/README.md#revision-and-progress-recovery).
65
+
66
+ ## Cross-provider feedback
67
+
68
+ Create a handoff with the JSON request interface: `kind: 'handoff'` and a `create` command containing a UUID, current `runtimeEpoch`, managed `sourceThreadId` and `purpose: 'challenge' | 'review'`. Creation opens a short-named reviewer session with the opposite provider, without sending a prompt. Preview the exact native skill invocation, then explicitly send its digest. Both CLIs keep their own skills, tool permissions and conversation histories.
69
+
70
+ Collect one completed reviewer message by its exact native turn/item reference. Preview and explicitly send it through `jg-feedback` to the original author. Feedback remains untrusted advice; delivery and native turn completion grant no plan approval, execution authority or acceptance of recommendations. Busy authors receive queued feedback through the existing action ledger. An uncertain send is never automatically retried.
71
+
72
+ `handoff-show --id <uuid>` reads one handoff; `handoffs --workspace-root <path>` pages the inbox. The [handoff reference](api/README.md#cross-provider-handoffs) describes creation, preview, send and native findings collection through the same CLI's JSON request interface.
73
+
74
+ ## Project blueprint
75
+
76
+ - `src/index.ts`: the explicit public package boundary.
77
+ - `src/locks/`: lock ownership, acquisition, status and deliberate recovery.
78
+ - `src/runtime/`: trusted configuration and lifetime ownership.
79
+ - `src/ipc/` and `src/cli/`: private local commands and the installed executable.
80
+ - `src/providers/codex/`: native history and account protocol.
81
+ - `src/providers/claude/`: native structured control and usage, plus the version-checked, worker-owned local history reader.
82
+ - `src/sessions/`: authorized, cursor-bound history reads and short label suggestions.
83
+ - `src/plans/`: execution digests, milestone finalization, revision checkpoints, retained verification and explicit plan authority.
84
+ - `src/skills/`: bounded native catalogs, invocation previews and explicit input preparation.
85
+ - `src/handoffs/`: explicit cross-provider challenges, selected native findings and author assessment links.
86
+ - `src/actions/`: durable action dispatch, native input routing and bounded live presentation.
87
+ - `src/store/`: SQLite discovery metadata and the action/control ledger in one worker.
88
+ - `src/contracts/`: browser-safe command and response contracts.
89
+ - `scripts/package/`: build-output cleanup and packed-consumer checks.
90
+ - `scripts/test-support/`: disposable external CLI fixtures.
91
+ - `vitest/`: separate unit and integration selection.
92
+ - `api/README.md`: canonical public API reference.
93
+ - `errors/README.md`: stable application errors.
94
+ - `website/`: private public-site workspace with its own README and test/check commands; canonical documentation bodies remain in this root README and `api/README.md`.
95
+ - `docs/website.md`: durable website architecture, verification and generated-asset sources.
96
+
97
+ `/docs` is reserved for concise, quickly scannable documentation of essential durable concepts and processes. API references remain outside `/docs`.
98
+
99
+ ## Testing
100
+
101
+ Tests consume built public exports. Unit tests cover application-owned decisions; integration tests use real temporary files, SQLite workers, IPC, child processes and an isolated tarball consumer. Synthetic CLIs replace only the external provider boundary. Every fixture removes its own resources. Production output excludes all test categories. `pnpm test` builds, then runs unit and integration suites. `pnpm check:package` is the task-completion check. Run changed integration files three consecutive times with retries disabled, using Vitest's `--repeats=2 --retry=0`.
102
+
103
+ The website's README and `docs/website.md` define its build-once check composition, category-specific scripts and owned preview/browser lifecycle. Root and website checks must both pass for task completion when workspace configuration or canonical site content changes.
104
+
105
+ Current local checks establish the tested host only. Release qualification must include the Node engines floor and current LTS; macOS operation requires its own runtime evidence.
package/api/README.md ADDED
@@ -0,0 +1,253 @@
1
+ # Public API
2
+
3
+ Import the named exports from `jg-agent-hq`. Internal module paths are private.
4
+
5
+ ## Lock lifecycle
6
+
7
+ - `acquireHqLock(root, command, options?)` acquires `.runtime/hq.lock` and returns an asynchronous release function. The caller owns the trusted state root and supplies a non-empty, single-line operation label. Surrounding whitespace is trimmed. The returned release function is idempotent and refuses a replaced owner.
8
+ - `withHqLock(root, command, operation, options?)` runs an asynchronous operation under the lock. It releases on success or failure; operation failures propagate unchanged. If cleanup also fails, the original operation error stays primary and cleanup failure is reported on stderr.
9
+ - `readHqLockState(root, now?)` reports free, held or unreadable without acquiring or reclaiming the lock. Held state includes the owner, liveness and age.
10
+ - `getOwnerLiveness(pid)` reports alive, dead or unknown. An unverifiable owner is not evidence that recovery is safe.
11
+ - `releaseHqLock(root, nonce)` is deliberate operator recovery. Confirm first that the inspected owner and its children have stopped. It checks the inspected nonce rather than liveness, because a reused PID must not prevent recovery.
12
+
13
+ `IHqLockOptions` retains the wait timeout, setup window and poll interval. Defaults are 120 seconds, 16 seconds and 200 milliseconds. Durations must be finite and non-negative; the poll interval must be positive. Invalid acquisition arguments fail before filesystem writes. An empty freshly created file is tolerated only within the setup window. Owner records are bounded to 16,384 UTF-8 bytes. The private directory and lock must belong to the current user and have no group/other access.
14
+
15
+ `IHqLockOwner`, `IOwnerLiveness`, `IHqLockOptions` and `IHqLockState` describe the contracts. `RUNTIME_DIRECTORY` and `HQ_LOCK_FILE` expose the established names.
16
+
17
+ All operations may expose the relevant intentional contracts in [errors](../errors/README.md). Filesystem failures outside those classifications propagate to the trusted Node caller. The returned acquisition release function can expose the ownership-changed contract.
18
+
19
+ ## Runtime lifecycle
20
+
21
+ `createAgentHq({ stateRoot, allowedRoots })` starts one controller and returns `IAgentHq`: its canonical `stateRoot`, a `closed` lifetime promise, `request(command)` and idempotent `close()`. Paths must be absolute. Allowed roots must exist and are canonicalized at startup. A client-selected workspace must resolve inside an allowed root. State is a real directory owned by the current OS user with no group/other access. The controller creates it privately when absent.
22
+
23
+ The controller exclusively creates `hq-owner.json`. A live, inactive, incomplete or unverifiable existing owner prevents another controller from starting. There is no automatic takeover. Before deliberate recovery, establish that the inspected host, its worker and native process group have stopped. Runtime shutdown sends interruption requests across the bounded session cohort concurrently, then closes IPC connections, SQLite and owned native processes before removing the exact owner. Failed cleanup preserves ownership evidence. A new runtime receives a new epoch.
24
+
25
+ `requestAgentHq(stateRoot, command)` is a one-command IPC client. It verifies the private owner and socket, binds the command to the runtime epoch and checks the matching response. Closing a client does not close the host. `stop` accepts a shutdown request; the SDK caller must await `runtime.closed` when it owns the runtime. The CLI confirms owner removal before reporting `state: stopped`.
26
+
27
+ The socket accepts at most 32 simultaneous connections. Requests are bounded to 65,536 UTF-8 bytes; native and IPC response frames to 8,388,608 bytes. Structured transports reject malformed UTF-8/JSON, oversized frames and incomplete tails. Each native connection has at most 32 pending calls with a 30-second response deadline. IPC connections have a 35-second deadline. The SQLite worker bounds its queue to 128 commands, accommodating client reads, native lifecycle observations and action dispatch; collection operations remain limited to one page. Database work runs off the host event loop. The state directory is a same-user trust boundary, not a sandbox against other code running as that user.
28
+
29
+ ## Read commands
30
+
31
+ Import `HqRequestSchema`, `HqResponseSchema` and their inferred types from `jg-agent-hq/contracts`. Requests are closed contracts. Responses tolerate additive fields. Read providers are `codex` and `claude`. Both providers support explicit thread control. Status reports Codex steering as available and Claude steering as unavailable.
32
+
33
+ | Command | Required fields | Result |
34
+ | --------- | --------------------------------------- | ------------------------------------------------------------------------------------------ |
35
+ | `status` | None | Runtime epoch, host PID, start time, worker availability and native transport availability |
36
+ | `stop` | None | Accepted shutdown and runtime epoch |
37
+ | `threads` | `provider`, `workspaceRoot` | Paged native discovery; optional `search` |
38
+ | `thread` | `provider`, `workspaceRoot`, `nativeId` | One native thread's metadata |
39
+ | `turns` | Same target fields | Paged native turn metadata without hydrating items |
40
+ | `items` | Same target fields | Paged persisted native items; optional `turnId` |
41
+ | `usage` | `provider` | Actual subscription observations |
42
+
43
+ Paged commands accept `limit` (default 32, maximum 128) and an opaque `cursor`. Continue with exactly the same command, target, filters and limit. The cursor binds those fields to the provider continuation. Codex requests descending creation order for threads, descending turns and ascending items. Claude orders discovery by creation time/native UUID descending and history by native chain position ascending. Workspace authorization is rechecked for each request, independently of cursor validation, before selected-thread items are fetched.
44
+
45
+ Threads expose native state, `historyState` (`available` or `unavailable`), ownership (`external`, `managed` or `uncertain`) and nullable `managedId`. A managed thread uses its HQ name; an external thread retains its nullable native name. Timestamps use Unix milliseconds. Discovery projections are not authoritative transcript history and never cache a conversation body. Repeated Codex history reads go to its native APIs so a completed turn whose items have not flushed can be read again later. There is no resume-to-read behavior or Codex transcript-file parser.
46
+
47
+ ## Claude history
48
+
49
+ Claude connects on its first read through `claude --print --input-format stream-json --output-format stream-json --verbose`. No user prompt, bare mode, permission bypass or SDK dependency is used. Runtime status reports this adapter as `idle`, `ready` or `unavailable`, with its observed CLI version. An unavailable native lane requires restarting the host after resolving the native problem.
50
+
51
+ The qualified CLI interface has no session-history listing operation. The Claude-owned reader therefore uses direct UUID JSONL files in the native project's directory beneath `CLAUDE_CONFIG_DIR`, or the normal `.claude` directory. Both CLI and versioned transcript records must match 2.1.304. Other formats, encoded project keys longer than 200 characters, directory/file links, malformed records and records larger than 1 MiB report unavailable. Discovery never recurses into subdirectories, including excluded directories. Unsupported discovered sessions have `historyState: unavailable`; they do not prevent supported sessions from being listed.
52
+
53
+ Discovery verifies the workspace recorded inside each transcript before returning its identity or title. A matching native directory name alone is insufficient because punctuation replacement can produce colliding directory keys. Foreign workspaces are omitted. If a file's workspace cannot be established, discovery reports unavailable rather than inventing an empty result.
54
+
55
+ The existing SQLite worker incrementally records file identity, complete-line offsets, message identities and parent links. It does not save message bodies. Each worker batch inspects at most 128 directory entries and reads at most 4 MiB of new transcript bytes, one file at a time. The adapter continues batches with a host-event-loop yield between them, within a 30-second operation budget. If that budget is reached, the read reports unavailable and subsequent reads continue indexing. At most four incomplete discovery iterators remain open. Shutdown closes them. Discovery continuations use that projection without starting another directory scan; start a fresh first page to refresh discovery. Removed files are discarded from the projection after a complete refresh. No additional cache infrastructure or browser cache is used.
56
+
57
+ Current-chain membership and turn starts are indexed as metadata. Ordinary item and turn continuations seek those indexes; they do not walk the full chain per page. A changed branch rebuilds membership before exposing that revision. Repeated native message identities can replace content while retaining their parent; a changed parent for the same identity is an unsupported format.
58
+
59
+ Selected history reads refresh only that file, retain incomplete tails, and detect truncation or replaced identity. Changed branch/file revisions invalidate item and turn continuations. Only the current parent-linked conversation chain is returned. Text is reread from the native file for the selected page and normalized as plain text. Non-text content has explicit native block labels. Each selected page reads at most 4 MiB of record bytes and returns at most 4 MiB of serialized item presentation, so a large-text page can contain fewer rows than its requested limit.
60
+
61
+ File timestamps and records do not prove that a native process is idle or a turn completed. Claude file-backed thread and turn states are therefore `unknown`, with no invented completion timestamp. Explicit native custom titles are preserved; a missing title remains null. File-backed grouping follows native user records and parent links, including generated user-record markers; it is not an authoritative execution boundary.
62
+
63
+ ## Thread control and live input
64
+
65
+ Send `{ kind: 'action', action: { id, runtimeEpoch, command } }`. Generate one UUID per user intent, take the epoch from `status`, and retain the complete envelope until its receipt can be read. The validated envelope is limited to 32,768 UTF-8 bytes. It is recorded before native writes. Reusing the UUID with the identical envelope returns the saved receipt without dispatch; a changed envelope conflicts. This check also works for an original request read after restart. A new UUID with an expired epoch cannot execute.
66
+
67
+ | Action | Fields and behavior |
68
+ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
69
+ | `thread-create` | `provider` (`codex` or `claude`), `workspaceRoot`, `name`. Creates an empty native thread and sets its readable name before reporting acknowledgement. |
70
+ | `thread-adopt` | The same fields plus `nativeId`, `operatorConfirmation`. Explicitly transfers an external thread after confirmed inactive ownership. Codex must report it unloaded; Claude requires qualified workspace history and the native idle/session-identity checks. |
71
+ | `thread-resume` | `threadId`, `operatorConfirmation`. Resumes an inactive managed thread; HQ does not fetch its complete conversation bodies. |
72
+ | `thread-recover` | `threadId`, `operatorConfirmation`, `recovery`. The recovery is `{ kind: 'resume' }` for a known native identity, `{ kind: 'attach', nativeId }` for an inspected identity after uncertain creation, or `{ kind: 'create' }` to explicitly create a fresh empty thread when no native identity was recorded. The latter can leave an empty orphan from the uncertain creation; it never repeats a message. |
73
+ | `thread-rename` | `threadId`, `name`. Changes the name only after the matching native acknowledgement. |
74
+ | `thread-close` | `threadId`. Requires an idle thread and pauses its queue. Codex cleans and verifies its native terminal list before unsubscribe. Claude closes the owned CLI and proves process-group exit before releasing control. |
75
+ | `message` | `threadId`, `input`. Starts a turn only while idle. |
76
+ | `steer` | `threadId`, `expectedTurnId`, `text`. Codex uses native `turn/steer`. Claude rejects this operation; it never substitutes interruption. A finished or changed turn cannot become a new turn. |
77
+ | `queue` | `threadId`, `expectedTurnId`, `input`. Saves an explicit next-turn message or skill invocation, never a permission or question answer. |
78
+ | `queue-send` | `queuedActionId`. Explicitly authorizes a still-undelivered queue entry, including a queue paused by restart or interruption. |
79
+ | `queue-cancel` | `queuedActionId`. Cancels only an undelivered queue entry and clears its saved body. |
80
+ | `interrupt` | `threadId`, `expectedTurnId`. A native request acknowledgement leaves the thread stopping until native completion evidence arrives. |
81
+ | `native-reply` | `threadId`, `expectedTurnId`, `approvalId`, `response`. Answers one exact current native request; cannot consume queue text. |
82
+
83
+ Message and queue input is a closed union: `{ kind: 'text', text }` or `{ kind: 'skill', skillId, arguments }`. Text is nonempty and at most 65,536 characters; skill arguments may be empty and cap at 16,384 characters. The envelope's UTF-8 limit still applies. A selected skill is resolved through the target thread's current native catalog before admission. Unavailable, missing or disabled selections cannot dispatch. Normal text needs no catalog read. Steering retains its `text` field and exact active-turn target.
84
+
85
+ Names use lowercase ASCII letters, digits and hyphens, start with a letter or digit, and have at most 32 characters. Names are unique without regard to case in one state directory. Creation and adoption resolve collisions atomically with ordinal suffixes such as `build-usage-2`, truncating the base to keep the complete name within 32 characters. Explicit rename rejects an occupied or pending name. Provider/native-session pairs remain unique. At most 32 native sessions are controlled concurrently; close idle sessions to release capacity. Native discovery remains independent of that limit. Confirm that other native CLI controllers are closed before adoption, resume or recovery. An unloaded native status cannot prove another CLI has stopped. HQ provides exclusive coordination within one canonical state directory; it does not impose a global lock on independent CLIs. Recovery is permitted only after the producing runtime has stopped and its ownership evidence has been inspected.
86
+
87
+ Receipts separate `delivery` (`queued`, `submitted`, `acknowledged`, `uncertain`, `failed`, `canceled`) from nullable native turn `completion` (`completed`, `failed`, `interrupted`). Acknowledgement means the exact native request was accepted, not that the turn or tool completed. Permission replies remain submitted after a pipe write and become acknowledged only when Codex resolves the exact native request or Claude returns a tool-result block for the exact tool-use identity. Claude cancellation expires the prompt and leaves an unacknowledged written reply uncertain. Resolution does not prove a tool ran. The receipt includes HQ/native identity, request phase, digest, timestamps, safe failure classification and optional related action. Only selected receipts expose undelivered `queuedText` and `queuedSkill`; collection reads omit both. Queued native skill selections contain a native name and nullable source path, never skill content. Both are cleared after delivery acknowledgement or cancellation.
88
+
89
+ A missing acknowledgement never triggers an automatic resend. Exact late responses reconcile delivery, including completion that arrived first. Native output loss marks the affected provider controls and submitted work uncertain. A Claude process failure affects its own session; a Codex transport failure affects its Codex cohort. Restart quarantines controls from an interrupted runtime; explicit recovery preserves the HQ identity and name. Successful shutdown proves native process-group exit before marking controls inactive. Unknown creation without a native identity remains uncertain.
90
+
91
+ Normal native turn completion may advance ready queued entries once, in creation/UUID order. Failure, interruption, explicit interrupt admission or restart pauses the queue. Permission prompts do not advance it. An unacknowledged start or metadata change blocks dependent starts until its outcome is reconciled or the stopped runtime is recovered explicitly. A turn's completion does not settle an unresolved steering receipt.
92
+
93
+ Native replies use one of these closed response forms:
94
+
95
+ - `{ kind: 'decision', decision: 'accept' | 'acceptForSession' | 'decline' | 'cancel' }` for command/file approval, restricted to the choices Codex offers.
96
+ - `{ kind: 'permission', decision: 'accept' | 'decline', scope: 'turn' | 'session' }` for additional permissions. Acceptance copies only the complete displayed native scope. Unknown permission fields cannot be approved.
97
+ - `{ kind: 'answers', answers: { [questionId]: [answer] } }` for native questions. Every requested question must have an answer; `allowsMultiple` indicates whether several answers are allowed. Codex questions accept one answer, and predefined choices are enforced when free text is unavailable.
98
+
99
+ Prompts expose `replyActionId` as soon as a reply is admitted, so reconnecting clients can read its receipt and avoid offering another answer while native resolution is pending. Prompts and answers remain in memory. SQLite retains only native request identities, scope fingerprints and reply receipts. Fingerprints use a per-store HMAC key in the private 32-byte `action.key`. Keep that file with the database; a missing or invalid key on a nonempty store fails closed. Ordinary message bodies are not saved by HQ. Undelivered queued messages are saved until dispatch or cancellation.
100
+
101
+ ### Claude native control
102
+
103
+ Each controlled session has one persistent native `claude` process in the authorized workspace. HQ adds structured input/output, replayed user-message acknowledgements, partial-message output and `--permission-prompt-tool=stdio`. It does not set a model, replace instructions/settings, disable session persistence, bypass permissions or enable a bare mode. Native skills remain available. Control was exercised against CLI 2.1.304. Native idle initialization, session identity and matching acknowledgements establish capability; a changed version label alone does not disable compatible controls. File history retains its separate exact-version check.
104
+
105
+ Creation chooses a native UUID without inference, then names that exact session. Resume uses native `--resume` and verifies the session-id fence on the name control before marking the session idle. The operator's handoff confirmation establishes that another CLI controller is closed; file timestamps and file-backed unknown states do not establish this. Independently running CLIs are outside HQ's state-directory coordination boundary.
106
+
107
+ An ordinary message is submitted only while idle. Its native UUID becomes the turn identity. A matching native replay or result acknowledges delivery, and the native result establishes completion. A request-success envelope can acknowledge a name change or interruption without a response body. HQ never writes queued follow-up input into Claude's own busy queue; the shared HQ queue dispatches it only after the previous result. Interruption acknowledgement alone does not establish a stop. An error result is classified as interrupted only when the qualified native interruption marker was observed for an explicitly interrupted input. Other terminal errors remain failed.
108
+
109
+ Claude questions use exact question text as their answer identity and expose whether multiple selections are supported. Tool permissions offer `accept` or `decline` for the displayed input only. Session-wide permission changes are unavailable; HQ does not apply native permission suggestions automatically. A reply is written through the separate control channel and acknowledged only by the matching tool result. Tool execution can still fail after that acknowledgement. Reused raw request IDs in different CLI processes have distinct controller scopes. Prompt bodies and replies remain out of SQLite.
110
+
111
+ Partial text uses temporary live identities until the final native message UUID arrives; that replacement shares the existing global live-item budget. Native thinking content is not copied into text presentation. Persisted history reconciles matching final items through the same content normalizer. Closing the session proves owned process-group exit, including native background children, before HQ releases control.
112
+
113
+ ## Native skill catalog
114
+
115
+ `skills` accepts `threadId`, optional `search`, `limit` (default 32, maximum 128) and `cursor`. It operates on a controlled session and never adopts or resumes an external session. Codex uses native `skills/list` for that thread's authorized workspace; Claude uses that session's native initialization command list, which includes explicit-only skills. Its refresh endpoint omits those skills, so HQ does not use it. Close and explicitly resume the session to refresh Claude's catalog. Inactive or unsupported sessions report `unavailable`, with no successful-empty fallback. Native discovery errors produce `partial` and an `unavailableCount`. `observedAt` records when the native inventory was observed; it stays fixed for a Claude session and is null when unavailable.
116
+
117
+ Rows contain an opaque `id`, native `name`, `description`, nullable `argumentHint`, `kind`, `path`, `scope`, `prerequisites` and `requiresExplicitInvocation`, plus native availability as `isEnabled`. Codex supplies skill identity, source/scope, enabled state and declared tool prerequisites. Claude supplies native command names, descriptions, argument hints and a built-in marker when available. Missing fields are null or `kind: 'unavailable'`; HQ does not inspect skill files to infer them. Declared prerequisites are metadata, not proof that an integration is connected. Invocation rules remain with the CLI, including explicit-only skills.
118
+
119
+ Both native inventory interfaces are unpaged. HQ accepts at most 4,096 native rows and 1 MiB of normalized catalog metadata per read, then provides stable ID seek pages guarded by the complete inventory revision and query. A changed inventory invalidates continuation. Only native metadata is read, never skill bodies or complete conversation histories. Concurrent reads for the same thread share their in-flight native request; Codex results are not retained as an HQ cache. Claude's native initialization metadata remains attached to its owned connection until that session closes. Native refresh and discovery caches remain provider-owned.
120
+
121
+ `skill-preview` accepts `threadId`, `skillId` and `arguments`. Its result is `ready`, `missing`, `disabled` or `unavailable`, with the selected metadata and exact text only when ready. Codex previews `$name arguments` and receives an explicit native skill selection containing its native name/path alongside that text. Claude previews `/name arguments` and performs native slash-command loading. Native same-name precedence applies. Preview never sends user input. Explicit message and queue actions share the established action ledger, ownership checks and delivery/uncertainty rules. They grant no tool permissions and do not expand the invoked workflow's authority.
122
+
123
+ Trusted runtime construction also accepts `codexExtraSkillRoots?: string[]` and `claudeAdditionalDirectories?: string[]`. Paths must resolve to existing absolute directories. Codex receives process-local `skills/extraRoots/set`; Claude receives native `--add-dir` arguments, which also grant native file access to those directories. These inputs belong to the operator and cannot be changed through IPC commands. The installed `serve` command exposes repeated `--codex-extra-skill-root` and `--claude-additional-directory` flags. No global skill installation or coding-instruction change is performed.
124
+
125
+ ## Control reads and reconnect
126
+
127
+ | Command | Fields | Result |
128
+ | --------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
129
+ | `managed-threads` | `workspaceRoot`, optional `limit`, `cursor` | Creation/UUID seek page of HQ records, including inactive and uncertain states. |
130
+ | `managed-thread` | `threadId` | One HQ record or null. |
131
+ | `managed-thread-name` | `name` | One HQ record or null, with case-insensitive lookup and the same workspace authorization. |
132
+ | `suggest-thread-name` | `topic` | An editable lowercase label, with a currently free suffix when needed. This read does not reserve it. |
133
+ | `receipt` | `actionId` | One receipt or null. |
134
+ | `actions` | `threadId`, optional `limit`, `cursor` | Creation/UUID seek page of action metadata without queued bodies. |
135
+ | `events` | `threadId`, optional `after` (default 0), `limit` | Ascending durable sequence page and `hasMore`; continue after the final sequence. |
136
+ | `approvals` | `threadId` | Current in-memory native prompts, including exact scope and question metadata. |
137
+ | `live-items` | `threadId` | Active/awaiting-flush item window and `hasGap`. |
138
+
139
+ The installed CLI exposes `managed-thread-name --name <name>` and `suggest-thread-name --topic <topic>`. Suggestions normalize punctuation to hyphens, keep at most 32 characters, and use `session` when the topic contains no ASCII letters or digits. Creation checks availability again inside its admission transaction. All action targets, histories and relationships continue to use immutable HQ/native identities. Name lookup never adopts, resumes or starts a native session.
140
+
141
+ Control pages default to 32 and cap at 128. Seek cursors are bound to their complete query and ordering. Reads recheck allowed workspaces. Rejected controls retain their known thread association, and native availability failures appear in each affected thread's replay. Lifecycle replay contains metadata, not token or tool output. The native lifecycle backlog is bounded to 128 operations; an overflow stops native control and marks its state uncertain rather than losing events silently.
142
+
143
+ Live item presentation is bounded to 128 items per cached thread, 32 windows and 4 MiB of serialized presentation across the runtime, including escaped text and identifiers. This leaves room inside the IPC response limit. Display text uses the same truncation contract as native history. Eviction, an unavailable window or missing chunks sets `hasGap`. Completed items remain `awaiting-flush` after thread closure until a native history page contains exactly matching normalized content or the bounded cache evicts them. Read persisted history and the live window together after reconnect; a process restart cannot reconstruct unflushed in-memory content.
144
+
145
+ Items expose only normalized presentation fields. User/agent text, commands and file changes have explicit kinds. Unknown native kinds report `unsupported` without copying arbitrary payloads. Display text is bounded to 65,536 UTF-16 code units without splitting a surrogate pair; `isTruncated` reports omissions. An unsupported or oversized native transport frame fails explicitly.
146
+
147
+ ## Subscription observations
148
+
149
+ Usage retains actual bucket/window identities, optional native labels, reported used percentage, remaining percentage, window duration and reset time. Percentages are never estimated from token counts or summed across sessions. Reported usage above 100 is preserved; remaining percentage floors at zero. `ordinaryUsageAllowed` is nullable when the native response does not report permission.
150
+
151
+ `available` means a usable observation exists. `exhausted` requires Codex's native permission/reached signal or a fully used Claude meter that the native response marks active. Neither label authorizes a model operation. `unavailable` covers missing windows or an observation that could not be obtained. Failed refreshes preserve a measured snapshot as `stale`, with its original `observedAt`. Observations older than 60 seconds or past a reported reset are stale. Codex account/rate-limit notifications trigger a coalesced refresh. Claude auth notifications discard account measurements and invalidate responses started for that account; rate-limit events mark the observation stale until the current or next structured refresh succeeds.
152
+
153
+ Claude uses the experimental `get_usage` control with `skip_behaviors: true`, and validates the native `rate_limits.limits` rows rather than inferring quotas from session costs or reading credentials. The [published provider control types](https://app.unpkg.com/@anthropic-ai/claude-agent-sdk@0.3.301/files/sdk.d.ts) describe this protocol; HQ invokes the installed CLI directly. Independent model/surface windows stay separate. Null percentages are omitted; zero is retained when reported. Unsupported shapes are unavailable. Claude does not report a duration or ordinary-usage permission in this contract, so those fields remain null. No private OAuth endpoint, credential scrape or status-line execution is used.
154
+
155
+ Every usage read requests current native observations; the last successful snapshot is retained only to explain freshness after a failure. There is no TTL cache that suppresses a native refresh. Multiple simultaneous reads share one pending refresh.
156
+
157
+ ## CLI
158
+
159
+ `jg-agent-hq serve --state-root <directory> --workspace-root <directory>` starts the host. Repeat `--workspace-root` to authorize several roots. Client commands use `--state-root`; history commands also use one `--workspace-root` and, where required, `--native-id`. History and usage accept `--provider codex|claude` (default `codex`). Paged commands support `--limit` and `--cursor`; items support `--turn-id`; thread discovery supports `--search`. CLI paths resolve from the caller's working directory. There are no shell commands or raw native RPC passthroughs.
160
+
161
+ Output is one JSON line with `schemaVersion: 1`. Read output includes the command `kind` and `result`. Startup reports `kind: ready`. Confirmed shutdown reports `kind: stop` with `result.state: stopped`. Failure output goes to stderr with a safe error kind/message and exit status 1. The CLI never prints diagnostic causes or native payloads in an error response.
162
+
163
+ `jg-agent-hq request --state-root <directory>` reads one complete HQ request from stdin, validates it, and prints the usual response. It accepts no extra target flags. This exposes action and reconnect operations without putting message text or question answers in command-line arguments. Its `stop` response acknowledges admission; use the dedicated `stop` command for confirmed shutdown.
164
+
165
+ ## Plan coordination
166
+
167
+ `computePlanRevision({ body, metadata, milestones })` is the pure Node API for execution identity. `metadata` contains `scope`, `repositories` and `errorReservations`. Reservation entries contain `repository`, `namespace`, inclusive `start`/`end`, `registryPath` and `purpose`; this API hashes them and does not allocate codes. Repository and reservation order is canonicalized. Plan bodies normalize line endings only. Private coordinators supply the body after parsing their own frontmatter; ordinary planning directories use the entire plan file.
168
+
169
+ Send `{ kind: 'plan', command }` through the existing local request API. Every command selects `target: { directory }`, an absolute directory inside an allowed workspace. A private host supplies `parsePlanContract({ directory, content })` when constructing the runtime. It returns the exact body after frontmatter and its contract metadata from the current file. The core validates that exclusion boundary and metadata while leaving private frontmatter policy with its owner. With no parser, the whole ordinary plan is contractual. The private server resolves operator identity itself and never forwards browser-supplied roots, contract exclusions or metadata.
170
+
171
+ | Command kind | Required fields and result |
172
+ | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
173
+ | `status` | `target`. Returns current execution revisions, full inspection hashes, approval state and a bounded coordination summary and retained-evidence counts. |
174
+ | `milestones` | `target`, optional `limit` (default 32, maximum 128) and `cursor`. Returns a bounded ordered seek page. |
175
+ | `finalize` | `target`, `action`, `expected`. Assigns initial UUIDs or reconciles a checkpoint. Returns the complete canonical file, or a saved proposal needing one confirmation. Optional `confirmation: { proposalId, decisions }` resolves every unmatched source. |
176
+ | `begin-revision` | `target`, `action`, `expected`, `intent: 'plan' \| 'breakdown'`, `threadIds`, `checkouts`. Closes execution admission and starts owned interruption/checkpoint work. |
177
+ | `revision-invoke` | `target`, `action`, `expected`, `revisionId`, `skill: 'jg-plan' \| 'jg-breakdown'`. Explicitly opens the next native planning invocation after proven quiescence. It sends no model input itself. |
178
+ | `complete` | `target`, `action`, `expected`, `milestoneId`, actual `checks` and selected `checkouts`. Retains the verified contract/check references and actual worktree fingerprints, then advances the marker. |
179
+ | `reconciliation` | `target`, `collection: 'sources' \| 'drafts' \| 'evidence' \| 'correspondences'`, optional `limit` (32/128) and `cursor`. Returns retained evidence by indexed seek page. |
180
+ | `approve` | `target`, `action`, `expected`, `scope: 'plan' \| 'sequence'`, `presentationHash`. The hash must match the exact presented plan or finalized sequence. Sequence approval also requires current plan approval. |
181
+ | `revoke` | `target`, `action`, `expected`, `scope: 'plan' \| 'sequence' \| 'execution' \| 'all'`. Revoking a plan also revokes sequence and execution authority; revoking a sequence also revokes execution authority. |
182
+ | `authorize` | `target`, `action`, `expected`, `mode: 'supervised' \| 'auto'`, selected unique `milestoneIds`. Records permission for this exact execution scope without starting an agent. |
183
+ | `check-execution` | `target`, `expected`, `authorizationId`, `milestoneId`, `mode`. Rejects missing, revoked, stale, wrong-mode or out-of-scope authority. It sends no native input. |
184
+
185
+ `expected` is the exact `{ planDigest, breakdownDigest }` returned by inspection. Each mutating `action` has a UUID `id`, `operatorId` and `source: { kind: 'user-action' | 'user-message', reference }`. These are trusted local operator inputs. The module never infers approval from natural-language claims, an agent response or imported feedback. Its owner-only local IPC and files do not isolate hostile code executing as the same OS user. Native permissions remain separate action kinds with their own exact native request identities.
186
+
187
+ A first-use sequence has one `**Milestone ID:** <uuid>` immediately below each `**Status:**` line. Blank lines may separate the heading from its status; no intervening requirement prose is allowed. The initial finalizer rejects duplicate, malformed or misplaced IDs and inconsistent framing. It refreshes existing Overview status rows and returns the complete canonical file for presentation before approval. A changed finalized contract goes through checkpoint reconciliation. A raw or changed sequence cannot inherit finalized status or sequence authority. A done marker remains visible but blocks execution without completion evidence.
188
+
189
+ The milestone contract includes its stable UUID, title without its ordinal, all requirement prose, shared sequence requirements and the approval statement. Status and identity marker lines are excluded from the prose; only the derived Overview table is excluded from shared text. Prose next to that table remains contractual. Sequence order is significant. Renumbering preserves execution identity; changed requirements, dependencies, scope, reservations or order require applicable approval. Full-file hashes preserve exact UTF-8 bytes and are distinct from normalized execution revisions. Administrative frontmatter excluded by the trusted contract parser, session labels, status advancement and coordination receipts do not change execution digests.
190
+
191
+ Plan and milestone artifacts are bounded to 1 MiB each; coordination evidence is bounded to 8 MiB and a sequence to 1,024 milestones. Reads do not scan planning trees. Milestone pages use ordinal seek ordering with unique ascending ordinals. Cursors bind the selected directory, page size, execution revisions and exact milestone inspection hash. Any changed artifact requires a fresh page; renumbering or status-only edits still preserve approval. A SQLite projection is rebuilt only when the selected milestone file's full hash changes. Every read verifies its source file; the projection is replaceable and never grants authority.
192
+
193
+ Mutations hold the shared metadata lock at `<coordinationRoot>/.runtime/hq.lock` (`coordinationRoot` defaults to `stateRoot`), retain a durable action identity and intended write before changing files, sync temporary files and atomically replace each artifact. Use `serve --coordination-root <directory>` when the canonical coordination lock is separate from runtime storage. Repeating an action UUID with the identical payload never reapproves revoked work. A changed payload conflicts. An interrupted write remains blocked and can be retried with its original action only when files match the recorded baseline or exact intended output. Conflicting edits are preserved. Completed write bodies are removed from SQLite while replay identity remains. The current finalization receipt retains the operator event, execution revision, canonical file hash and timestamp independently of write recovery bodies. Status reads expose `pendingActionId` for unresolved writes; they never approve or resume work.
194
+
195
+ `coordination.json` includes required `comparisons`, an array bounded to 1,024 records validated by `PlanComparisonSchema`. Each record binds `sourceRevision`, `targetDirectory`, `targetRevision`, a `compatible` or `contradiction` verdict, `reason`, `reviewedAt` and reviewer provenance (`provider`, `cliVersion`, nullable observed `model`, and native message `reference`). A trusted coordinator writes these records while holding the same metadata lock. Core operations preserve them; status exposes only `comparisonCount`. They never change execution digests or grant authority. The coordinator owns relevance, freshness, semantic judgments, bounded review reads and any execution gate, including contradictions. The standalone core does not assess compatibility.
196
+
197
+ The installed `plan-status` and `plan-milestones` commands accept `--state-root` and `--directory`; the latter also accepts `--limit` and `--cursor`. Use `request` for the closed JSON mutation commands. The result is a tagged `status`, `milestones`, `reconciliation`, `reconciliation-required`, `finalized` or `execution-check` object within the outer `plan` response. A retried finalization returns current status when its finalized artifact no longer exists or has changed.
198
+
199
+ ### Revision and progress recovery
200
+
201
+ Begin revision before invoking a planning skill. Execution admission closes under the shared short lock. The runtime interrupts exactly the affected managed threads and verifies their native background cleanup before granting an editing lease. It retains a checkpoint of contracts, UUIDs/status, original completion records, selected checkout claims and actual Git/file fingerprints. Metadata locks are released during native planning. Failed or uncertain cleanup keeps editing blocked. Stop jobs belong to the runtime and survive a client disconnect. A runtime restart requires an explicit new planning invocation; it never adopts the editing lease automatically.
202
+
203
+ The local host supplies checkout evidence as `{ repository, directory, claimReference, paths }`. Paths are exact relative task paths. The core streams their contents, records link targets without following them, includes missing paths as deletions, and captures the current Git branch/HEAD. It does not stage or reset files and rejects traversal, parent-link escapes, `.git` and excluded archive/backup directories. Check commands and references are trusted operator evidence; this primitive does not execute arbitrary submitted commands or treat an imported agent claim as verification.
204
+
205
+ After native `jg-plan` removes milestones and native `jg-breakdown` regenerates them, close the planning controller before finalization. Only unique exact normalized title and complete-contract matches retain identity automatically. Every unmatched checkpoint source, including done and partial work, appears in one saved proposal. Confirmation decisions use `sourceIds`, `targetIds`, `relation` (`equivalent`, `requirements-changed`, `omitted`, `reopened`) and explicit one-to-one `retainedPairs`. One source ID cannot be assigned to multiple targets. Grouped decisions retain split/merged evidence. A complete equivalent mapping preserves verified completion or partial status; rewording does not create new checks. A changed requirement gets fresh pending identity. Explicit reopening preserves evidence while invalidating its completion credit. Unverified done markers cannot become verified through an equivalent mapping.
206
+
207
+ The proposal and assigned identities are persisted before the canonical file is replaced. Retry the same action and payload after a partial write; do not regenerate UUIDs or confirm a different proposal. Present the complete canonical output before sequence approval. Applicable plan and sequence approvals are required again after digest changes. Approval does not resume work: send a fresh `authorize` with the intended mode and scope. Execution authority is also bound to the current runtime epoch.
208
+
209
+ Guided native input adds `plan: { kind: 'execution', authorizationId, milestoneId, mode, revision }` or `{ kind: 'planning', revisionId, invocationId }` to its action envelope. The controller binds this context atomically to the managed thread. Planning starts with the exact authorized native skill. A live thread cannot switch scopes; close it before an explicit resume under a different scope. Queued input retains its original scope and cannot run under stale approval or during revision. Ordinary input on a bound thread remains subject to its current gate. Native permissions are still separate exact-request replies.
210
+
211
+ Selected status/admission/queue observations detect external contract edits or milestone deletion, persist a closed gate and request exact bound-thread interruption. These observations grant no operator authority and report uncertain in-flight effects. The finalized baseline retains identities and completion evidence for explicit reconciliation of direct CLI edits. Invalid artifacts fail explicitly. No directory scan or filesystem watcher is used. Status projects Revising, approval/breakdown requirements, Ready, In progress, Completed and Blocked independently of provider process state.
212
+
213
+ Retained evidence pages bind their collection, page size and exact coordination hash. Reads do not load complete collections into the client; SQLite rebuilds the replaceable projection only when its selected authoritative file changes. The file has a hard size/record bound and rejects growth beyond it without discarding evidence.
214
+
215
+ ## Cross-provider handoffs
216
+
217
+ Use the existing JSON client, `jg-agent-hq request --state-root <directory>`, or `runtime.request({ kind: 'handoff', command })`. All commands are closed contracts exported through `jg-agent-hq/contracts`.
218
+
219
+ | Command | Required fields | Result |
220
+ | --------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
221
+ | `create` | `id` (UUID), `runtimeEpoch`, `sourceThreadId`, `purpose` (`challenge` or `review`); optional `commit` (exact current Git HEAD) | Saved handoff and opposite-provider thread creation receipt. |
222
+ | `show` | `id` | Selected handoff, retained findings and separate creation/review/feedback delivery. |
223
+ | `preview` | `id`, `phase` (`review` or `feedback`) | Exact native invocation, immutable target ID and preview digest; no native input. |
224
+ | `send` | `id`, `phase`, `expectedPreviewDigest` | Explicit delivery through the existing action ledger. |
225
+ | `collect` | `id`, `turnId`, `itemId`; optional `limit`/`cursor` for the selected native history page | One immutable completed reviewer message, with its hash and native references. |
226
+ | `list` | `workspaceRoot`; optional `sourceThreadId`, `limit`, `cursor` | Seek page of summaries, without finding bodies. |
227
+
228
+ Example creation request:
229
+
230
+ ```json
231
+ {
232
+ "kind": "handoff",
233
+ "command": {
234
+ "kind": "create",
235
+ "id": "72dbce82-598b-4aa5-8c5b-2b79157adbcc",
236
+ "runtimeEpoch": "512c7c32-6aaf-417d-89ae-9cd792f65e11",
237
+ "sourceThreadId": "eaa4c6e3-199f-4f70-b683-0e5aa29c4c74",
238
+ "purpose": "challenge"
239
+ }
240
+ }
241
+ ```
242
+
243
+ Use the current runtime epoch and actual managed source ID from the runtime reads. Creation verifies source access through the provider's authoritative history interface, records native/source/repository/revision references, and saves the intent before admitting reviewer creation. `challenge` resolves the installed `jg-challenge-session`; `review` resolves `jg-review-session`. Reviewer input contains exact source references, not a copied transcript. Missing, disabled or ambiguous native skills remain unavailable. No skill-file parser, copied workflow or global installation is added.
244
+
245
+ Creation may still be pending when its response arrives. Read `show` until its creation is delivered, then request a preview. Preview states are `ready`, `missing-skill`, `skill-unavailable`, `target-unavailable`, `source-changed` and `findings-unavailable`. Preview saves no input and grants no native permission. Sending requires the exact ready preview digest. IDs and immutable phase intents make identical retries return the same action receipt; a changed payload or preview with the same identity conflicts. An unavailable or uncertain target is never replaced or resumed by a read or retry. If an intent was saved before native admission and the host restarted, retain it for inspection and create a new handoff only after establishing that no native input was admitted.
246
+
247
+ Collection reads exactly the requested native page through the provider adapter and accepts only one non-truncated agent message from the handoff's completed reviewer turn. Finding bodies are limited to 8 KiB UTF-8, never silently shortened. To select a later page, use the same `limit`, turn filter and preceding cursor as the native items read. A different message or changed body cannot overwrite collected findings. Full histories remain with the native CLIs. Persisted reviewer references retain the exact native session, turn and item identities.
248
+
249
+ Feedback resolves installed `jg-feedback` in the author thread and carries the selected findings with exact source, reviewer, item, revision and commit references. Source contract or selected Git HEAD changes invalidate an unsent preview. The action's optional `expectedPlan` guards the author's captured revision under the existing plan lock; explicit `null` requires an unbound thread. This guard applies only to `message` and `queue`, grants no execution scope, and cannot answer tool permissions. Known native identities cannot be reassigned; existing control admission preserves the exact author for queued feedback. Existing revision gates pause stale queued feedback. Neither handoff delivery nor a completed assessment turn means recommendations were accepted or implementation was authorized.
250
+
251
+ Delivery is `prepared`, `queued`, `submitted`, `delivered`, `uncertain`, `failed` or `canceled`; native `completion` is separately null, `completed`, `failed` or `interrupted`. Acknowledgement alone becomes `delivered`. Busy destinations use native next-turn queues, including while waiting for permissions; feedback is never written as a permission answer. Pending native permissions remain explicit actions on their own channels. No automatic feedback, response loop, approval or publication follows collection.
252
+
253
+ Lists use indexed `createdAt DESC, id DESC` seek ordering, default 32/max 128, and cursors bound to the workspace, source filter and page size. Concurrent newer inserts do not reappear on continuation; deleted unseen records disappear. Summaries do not transfer retained finding bodies through the worker. SQLite owns the small private `handoff` and `handoff_dispatch` records alongside existing actions. No database migration or transcript mirror is required. Reads are fresh and bounded; no separate cache is used.
@@ -0,0 +1,50 @@
1
+ import type { IActionEnvelope, IActionReceipt, IThreadSummary, INativeApproval, IPlanRevisionWorkflow } from '../contracts/index.js';
2
+ import { createClaudeControl, type ICodexProvider } from '../providers/index.js';
3
+ import type { createSkills } from '../skills/index.js';
4
+ import type { IStore } from '../store/index.js';
5
+ import type { createPlans } from '../plans/index.js';
6
+ import { LiveItems } from './live/index.js';
7
+ /**
8
+ * Owns admitted native work across client disconnects, with durable delivery evidence.
9
+ * @returns The runtime-scoped action controller. Close must precede worker shutdown.
10
+ */
11
+ export declare const createActions: (native: ICodexProvider, claude: ReturnType<typeof createClaudeControl>, readClaudeThread: (nativeId: string, workspaceRoot: string) => Promise<IThreadSummary>, store: IStore, roots: string[], epoch: string, actionKey: Uint8Array, skills: ReturnType<typeof createSkills>, plans: ReturnType<typeof createPlans>) => {
12
+ live: LiveItems;
13
+ /**
14
+ * Returns after durable admission; the native operation outlives this client request.
15
+ * @returns The durable admission receipt after validation.
16
+ * @throws
17
+ * - -1: The HQ action conflicts with its recorded state
18
+ * - -1: The HQ skill is unavailable
19
+ * - -1: The HQ request is invalid
20
+ * - -1: The HQ target is outside the allowed workspaces
21
+ * - -1: The Codex integration failed
22
+ * - -1: The Claude integration failed
23
+ * - -1: The Claude history is unavailable
24
+ * - -1: The HQ store failed
25
+ */
26
+ submit(action: IActionEnvelope): Promise<IActionReceipt>;
27
+ /** Reads only current in-memory prompts for the selected managed thread. */
28
+ approvals(threadId: string): INativeApproval[];
29
+ /**
30
+ * Quiesces the selected managed cohort without stopping unrelated controllers.
31
+ * @returns A promise resolved only after interruption, background cleanup and release evidence.
32
+ * @throws
33
+ * - -1: The HQ action conflicts with its recorded state
34
+ * - -1: The HQ target is outside the allowed workspaces
35
+ * - -1: The HQ store failed
36
+ * - -1: The Codex integration failed
37
+ * - -1: The Claude integration failed
38
+ */
39
+ quiescePlan(controls: IPlanRevisionWorkflow["controls"]): Promise<void>;
40
+ /**
41
+ * Stops admission, interrupts active work, cleans native terminals and confirms shutdown.
42
+ * @returns A promise resolved after native exit and release of durable control ownership.
43
+ * @throws
44
+ * - -1: The Codex integration failed
45
+ * - -1: The Claude integration failed
46
+ * - -1: The HQ transport failed
47
+ * - -1: The HQ store failed
48
+ */
49
+ close(): Promise<void>;
50
+ };