jg-agent-hq 0.5.2 → 1.1.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.
- package/CHANGELOG.md +16 -0
- package/README.md +11 -1
- package/api/README.md +24 -8
- package/dist/actions/actions.d.ts +17 -17
- package/dist/actions/actions.js +47 -34
- package/dist/actions/reads.d.ts +4 -4
- package/dist/actions/reads.js +16 -9
- package/dist/cli/cli.js +80 -21
- package/dist/contracts/browser/types.d.ts +24 -0
- package/dist/contracts/constants.d.ts +9 -0
- package/dist/contracts/constants.js +10 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/index.js +1 -1
- package/dist/contracts/plans/types.d.ts +26 -0
- package/dist/contracts/plans/types.js +4 -1
- package/dist/contracts/types.d.ts +39 -3
- package/dist/errors/utilities.js +2 -2
- package/dist/handoffs/handoffs.d.ts +25 -25
- package/dist/handoffs/handoffs.js +93 -77
- package/dist/ipc/client.d.ts +13 -13
- package/dist/ipc/client.js +53 -25
- package/dist/ipc/framing.d.ts +1 -1
- package/dist/ipc/framing.js +15 -5
- package/dist/ipc/server.d.ts +1 -1
- package/dist/ipc/server.js +26 -8
- package/dist/locks/locks.d.ts +38 -38
- package/dist/locks/locks.js +168 -108
- package/dist/plans/admission.d.ts +38 -38
- package/dist/plans/admission.js +184 -137
- package/dist/plans/authority.d.ts +1 -1
- package/dist/plans/authority.js +12 -5
- package/dist/plans/documents.d.ts +71 -0
- package/dist/plans/documents.js +263 -0
- package/dist/plans/evidence.d.ts +4 -4
- package/dist/plans/evidence.js +64 -29
- package/dist/plans/files.d.ts +26 -11
- package/dist/plans/files.js +146 -63
- package/dist/plans/finalization.d.ts +3 -3
- package/dist/plans/finalization.js +12 -17
- package/dist/plans/plans.d.ts +78 -78
- package/dist/plans/plans.js +305 -126
- package/dist/plans/projections.d.ts +2 -2
- package/dist/plans/projections.js +18 -7
- package/dist/plans/reconciliation.d.ts +4 -4
- package/dist/plans/reconciliation.js +33 -26
- package/dist/plans/revisions.d.ts +7 -7
- package/dist/plans/revisions.js +13 -10
- package/dist/plans/types.d.ts +15 -4
- package/dist/plans/types.js +11 -3
- package/dist/plans/utilities.d.ts +18 -9
- package/dist/plans/utilities.js +46 -157
- package/dist/providers/claude/claude.d.ts +6 -6
- package/dist/providers/claude/claude.js +27 -14
- package/dist/providers/claude/control/control.d.ts +19 -19
- package/dist/providers/claude/control/control.js +45 -33
- package/dist/providers/claude/control/permissions.js +5 -2
- package/dist/providers/claude/control/skills.d.ts +1 -1
- package/dist/providers/claude/control/skills.js +12 -5
- package/dist/providers/claude/control/stream.d.ts +1 -1
- package/dist/providers/claude/control/stream.js +6 -3
- package/dist/providers/claude/history/history.model.d.ts +2 -2
- package/dist/providers/claude/history/history.model.js +30 -13
- package/dist/providers/claude/history/types.d.ts +19 -1
- package/dist/providers/claude/history/utilities.d.ts +3 -3
- package/dist/providers/claude/history/utilities.js +34 -16
- package/dist/providers/claude/rpc.d.ts +3 -3
- package/dist/providers/claude/rpc.js +56 -19
- package/dist/providers/claude/transformers.d.ts +1 -1
- package/dist/providers/claude/transformers.js +7 -4
- package/dist/providers/codex/approvals/utilities.d.ts +1 -1
- package/dist/providers/codex/approvals/utilities.js +6 -3
- package/dist/providers/codex/codex.d.ts +2 -2
- package/dist/providers/codex/codex.js +48 -21
- package/dist/providers/codex/rpc.d.ts +2 -2
- package/dist/providers/codex/rpc.js +60 -19
- package/dist/providers/codex/transformers.d.ts +4 -4
- package/dist/providers/codex/transformers.js +4 -4
- package/dist/providers/codex/types.d.ts +12 -12
- package/dist/providers/codex/validations.d.ts +1 -1
- package/dist/providers/codex/validations.js +7 -3
- package/dist/providers/process.d.ts +1 -1
- package/dist/providers/process.js +16 -7
- package/dist/providers/types.d.ts +3 -3
- package/dist/runtime/browser/browser.js +14 -5
- package/dist/runtime/runtime.d.ts +13 -13
- package/dist/runtime/runtime.js +49 -24
- package/dist/runtime/state/state.d.ts +18 -18
- package/dist/runtime/state/state.js +100 -45
- package/dist/runtime/types.d.ts +37 -37
- package/dist/sessions/sessions.d.ts +4 -4
- package/dist/sessions/sessions.js +15 -9
- package/dist/sessions/utilities.d.ts +1 -1
- package/dist/sessions/utilities.js +16 -6
- package/dist/skills/skills.d.ts +10 -10
- package/dist/skills/skills.js +27 -17
- package/dist/store/browser/browser.model.d.ts +1 -1
- package/dist/store/browser/browser.model.js +7 -4
- package/dist/store/control/control.model.d.ts +4 -4
- package/dist/store/control/control.model.js +10 -7
- package/dist/store/handoffs/handoffs.model.d.ts +3 -3
- package/dist/store/handoffs/handoffs.model.js +9 -6
- package/dist/store/plans/plans.model.d.ts +3 -3
- package/dist/store/plans/plans.model.js +31 -15
- package/dist/store/store.d.ts +1 -1
- package/dist/store/store.js +60 -14
- package/dist/store/store.worker.js +8 -4
- package/dist/store/types.d.ts +72 -54
- package/dist/store/types.js +3 -1
- package/errors/README.md +63 -63
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
- Rebuild the homepage around a native-session visual, local setup and three complete source-backed walkthroughs. Show cross-provider reviews and retained revision evidence with explicit host decisions.
|
|
6
|
+
- Queue local metadata-lock acquisitions in order, preventing frequent status reads from starving a revision checkpoint. Preserve exact owner checks, wait deadlines and explicit recovery.
|
|
7
|
+
- Coordinate journaled private writes with public document locks, explicit keep/write/remove intents and durable completion acknowledgement recovery. Prepare aggregate and milestone progress before native admission; preserve exact replay output and completion evidence.
|
|
8
|
+
|
|
9
|
+
- Use jg-plans for document observations, guarded edit preparation and explicit milestone identity assignment. Preserve complete shared requirements and JSON-safe contract metadata; report skills binding freshness without blocking the revision approval flow; require current bindings for finalization and execution.
|
|
10
|
+
- Keep exact body and requirement bytes in execution digests, with deterministic metadata serialization. Stop regenerating derived Overview tables.
|
|
11
|
+
- Add three complete public-client source examples, packed-consumer contract qualification and fixture-backed native flows. Expose the exact pending correspondence proposal ID for explicit client confirmation.
|
|
12
|
+
|
|
13
|
+
## 1.0.0
|
|
14
|
+
|
|
15
|
+
- Use `jg-exception` with named string codes for runtime, lock, plan, provider, client and tooling failures. Preserve codes through SQLite-worker responses and publish browser-safe client codes alongside their safe messages. This changes the Node error contract; callers should handle the documented named codes.
|
|
16
|
+
- Use the shared Astro UI 0.4.0, `jg-site` metadata helpers and `jg-playwright` browser checks. Remove `error-message-utils` from the runtime and website.
|
|
17
|
+
- Redesign the public website around Claude Code and Codex collaboration, a copyable API example, the available runtime capabilities and section navigation for the documentation.
|
|
18
|
+
|
|
3
19
|
## 0.5.2
|
|
4
20
|
|
|
5
21
|
- Resume inactive managed Codex sessions retained as loaded by native unsubscribe, preserving explicit handoff and active/uncertain ownership guards.
|
package/README.md
CHANGED
|
@@ -31,6 +31,8 @@ Short metadata operations use `withHqLock`. Long-lived runtime ownership must us
|
|
|
31
31
|
|
|
32
32
|
See the [API reference](api/README.md) and [error contracts](errors/README.md).
|
|
33
33
|
|
|
34
|
+
Intentional failures use `Exception` from `jg-exception`, with the named string codes in the error reference. Local clients use `PUBLIC_ERROR_CODES` and `PUBLIC_ERROR_MESSAGES` from `jg-agent-hq/contracts` for errors translated at the IPC boundary. Safe classifications remain separate from private diagnostic causes.
|
|
35
|
+
|
|
34
36
|
## Local controller
|
|
35
37
|
|
|
36
38
|
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.
|
|
@@ -59,7 +61,7 @@ Use `jg-agent-hq request --state-root <directory>` with a closed HQ command on s
|
|
|
59
61
|
|
|
60
62
|
`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).
|
|
61
63
|
|
|
62
|
-
Finalization assigns milestone UUIDs and returns the complete canonical sequence when a breakdown exists. A plan without a breakdown remains one unit: finalization returns null content, plan approval suffices, and whole-plan execution uses an empty milestone selection with a null milestone ID. No milestone file is created merely to make a small plan executable. 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.
|
|
64
|
+
HQ uses jg-plans to observe and prepare ordinary Markdown plans. The default profile retains unknown contractual metadata and all shared requirement sections while excluding only declared administrative fields. Status reports skills bindings as absent, current or stale. A stale binding keeps the plan readable and approvable during revision, but closes finalization and execution until jg-breakdown refreshes coverage; bindings never grant HQ approval. Finalization assigns milestone UUIDs and returns the complete canonical sequence when a breakdown exists. A plan without a breakdown remains one unit: finalization returns null content, plan approval suffices, and whole-plan execution uses an empty milestone selection with a null milestone ID. No milestone file is created merely to make a small plan executable. 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. Document locks release before the write journal is completed. Checked replacements are private (0600), and progress preserves revision while recording one prepared updated_at. A pending write blocks further mutation until its original action is reconciled.
|
|
63
65
|
|
|
64
66
|
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.
|
|
65
67
|
|
|
@@ -73,6 +75,14 @@ Collect one completed reviewer message by its exact native turn/item reference.
|
|
|
73
75
|
|
|
74
76
|
`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.
|
|
75
77
|
|
|
78
|
+
## Source examples
|
|
79
|
+
|
|
80
|
+
Follow the [three complete walkthroughs](https://jg-agent-hq.jesusgraterol.dev/examples/), with copyable source, visual results and explicit host decisions.
|
|
81
|
+
|
|
82
|
+
`examples/control-session.ts` creates a native session and reads its actual delivery, output, permission and usage observations. `examples/review-handoff.ts` presents exact cross-provider review/feedback previews and delivers selected findings. `examples/revise-plan.ts` runs the planning skills through the revision lease, retains verified work through explicit correspondence, and obtains fresh approvals and execution scope.
|
|
83
|
+
|
|
84
|
+
These complete TypeScript examples use the public client and contracts. Start the local controller, sign in to the native CLIs, and install the required skills and supported project-local jg-plans CLI first. The host supplies actual user decisions and keeps native permission handling separate. Retain request identities before submission; after an interrupted client call, inspect those receipts instead of rerunning a whole example. Examples are development sources, not package exports or automatic website actions.
|
|
85
|
+
|
|
76
86
|
## Project blueprint
|
|
77
87
|
|
|
78
88
|
- `src/index.ts`: the explicit public package boundary.
|
package/api/README.md
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Import the named exports from `jg-agent-hq`. Internal module paths are private.
|
|
4
4
|
|
|
5
|
+
Intentional Node API failures use `Exception` from `jg-exception`. The [error reference](../errors/README.md) defines their named string codes and stable messages. `PUBLIC_ERROR_CODES` and `PUBLIC_ERROR_MESSAGES` are available from `jg-agent-hq/contracts` for the seven safe client classifications. SQLite-worker responses retain the originating application code; arbitrary worker failures become `JG_AGENT_HQ_STORE_FAILED`. Browser and IPC error bodies expose only their established safe classification and message.
|
|
6
|
+
|
|
5
7
|
## Lock lifecycle
|
|
6
8
|
|
|
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.
|
|
9
|
+
- `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. Acquisitions in one process queue by their normalized lock path, so later status polling cannot overtake a waiting checkpoint. Cross-process exclusion still uses the same file and exact owner; no cross-process ordering is promised. Timed-out or failed waiters leave the local queue.
|
|
8
10
|
- `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
11
|
- `readHqLockState(root, now?)` reports free, held or unreadable without acquiring or reclaiming the lock. Held state includes the owner, liveness and age.
|
|
10
12
|
- `getOwnerLiveness(pid)` reports alive, dead or unknown. An unverifiable owner is not evidence that recovery is safe.
|
|
@@ -166,13 +168,17 @@ Output is one JSON line with `schemaVersion: 1`. Read output includes the comman
|
|
|
166
168
|
|
|
167
169
|
## Plan coordination
|
|
168
170
|
|
|
169
|
-
`computePlanRevision({ body, metadata, milestones })` is the pure Node API for execution identity. `metadata` contains `scope`, `repositories` and `
|
|
171
|
+
`computePlanRevision({ body, metadata, milestones })` is the pure Node API for execution identity. `metadata` contains `scope`, `repositories`, `errorReservations` and JSON-safe `extensions`. 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; object keys use strict deterministic JSON. The exact parsed body, including its line endings, is contractual.
|
|
172
|
+
|
|
173
|
+
Send `{ kind: 'plan', command }` through the existing local request API. Every command selects `target: { directory }`, an absolute directory inside an allowed workspace. The default profile uses jg-plans observations: absent HQ fields default to local scope and empty repository/reservation lists; unknown fields, including plan `id`, remain in `extensions`. Only `created_at`, `updated_at`, `revision` and `status` are administrative. Malformed, non-mapping or non-JSON metadata fails closed. No preferred-document conformance gate is imposed.
|
|
170
174
|
|
|
171
|
-
|
|
175
|
+
A trusted private host may supply `parsePlanContract({ directory, content })`. It must return exactly the body observed by jg-plans and valid HQ metadata. That host owns its alternative metadata profile and must put its contractual extension fields in `extensions`. It cannot exclude body prose. The private server resolves operator identity itself and never forwards browser-supplied roots, contract exclusions or metadata.
|
|
176
|
+
|
|
177
|
+
Milestone contracts retain every requirement byte outside observed status/identity lines, plus preamble and all intervening/trailing shared sections. Only recognized Overview table spans and the three valid `jg_skills` binding fields are excluded; other milestone metadata remains contractual. HQ does not regenerate Overview tables. Statuses must be exactly pending, in progress or done, and milestone IDs/order participate in sequence identity. Ordinal renumbering alone does not change a milestone's identity. Missing IDs are assigned explicitly by jg-plans and saved before application. When present, a skills binding must match the current plan id, revision and fingerprint excluding exactly the four administrative keys. A matching binding never grants HQ approval or execution permission.
|
|
172
178
|
|
|
173
179
|
| Command kind | Required fields and result |
|
|
174
180
|
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
175
|
-
| `status` | `target`. Returns current execution revisions, full inspection hashes, approval state and a bounded coordination summary and retained-evidence counts.
|
|
181
|
+
| `status` | `target`. Returns current execution revisions, full inspection hashes, `skillsBinding` (`absent`, `current` or `stale`), approval state and a bounded coordination summary and retained-evidence counts. |
|
|
176
182
|
| `milestones` | `target`, optional `limit` (default 32, maximum 128) and `cursor`. Returns a bounded ordered seek page. |
|
|
177
183
|
| `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. |
|
|
178
184
|
| `begin-revision` | `target`, `action`, `expected`, `intent: 'plan' \| 'breakdown'`, `threadIds`, `checkouts`. Closes execution admission and starts owned interruption/checkpoint work. |
|
|
@@ -188,13 +194,23 @@ Send `{ kind: 'plan', command }` through the existing local request API. Every c
|
|
|
188
194
|
|
|
189
195
|
Milestones are optional. Finalizing a plan with no milestone file returns `content: null` and does not create a file. That unit needs plan approval and explicit execution authorization, with `milestoneIds: []`; execution checks, completion and native execution scopes select it with `milestoneId: null`. A real breakdown requires a nonempty selection of its stable IDs and its separate sequence approval. Null cannot select a milestone or bypass sequence approval. Whole-plan completion retains its exact plan contract/digest, actual check references and checkout evidence, with null shared-sequence digest. Completed work cannot be authorized again under that unchanged contract.
|
|
190
196
|
|
|
191
|
-
|
|
197
|
+
Skills bindings are optional for generic HQ plans. When present, their syntax must be valid and their plan ID, revision and structural fingerprint must match before finalization or execution. A valid but stale binding remains visible in status: plan approval and explicit revision invocations remain available so jg-plan can retain the old sequence until jg-breakdown refreshes its coverage. Malformed bindings fail as invalid artifacts. A stale binding never supplies sequence approval or completion, even when semantic execution digests are unchanged.
|
|
198
|
+
|
|
199
|
+
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 preserves existing Overview text 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.
|
|
192
200
|
|
|
193
|
-
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
|
|
201
|
+
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 semantic execution revisions. Administrative frontmatter excluded by the trusted contract parser, session labels, status advancement and coordination receipts do not change execution digests.
|
|
194
202
|
|
|
195
203
|
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.
|
|
196
204
|
|
|
197
|
-
Mutations
|
|
205
|
+
Mutations acquire the HQ metadata lock at `<coordinationRoot>/.runtime/hq.lock` (`coordinationRoot` defaults to `stateRoot`), then the public jg-plans document locks in plan-before-milestones order. Use `serve --coordination-root <directory>` when coordination ownership is separate from runtime storage. Locks cover bounded observation, preparation, journaling and file application; no model turn or native stop wait holds them. A busy document lock becomes `JG_AGENT_HQ_ACTION_CONFLICT` with the safe `document-locked` reason. There is no automatic stale-lock takeover.
|
|
206
|
+
|
|
207
|
+
SQLite persists exact prepared plan/milestone sources, assigned IDs and timestamps before application. A plan source of null means keep; milestone operations are explicitly keep, write with source, or remove. A null recorded before-plan hash permits only coordination work. Replay accepts only each recorded baseline or its exact desired state. Markdown is applied before coordination. Every HQ replacement uses jg-fs checked atomic writes with explicit 0600; absent targets are created exclusively and privately before content is written. Strict bounded, same-handle, single-link reads remain in HQ. Inspection alone never changes file permissions.
|
|
208
|
+
|
|
209
|
+
After file durability succeeds, document locks must release successfully before SQLite marks the intent completed and clears its write bodies; HQ metadata ownership remains held through completion. A write, sync or release failure retains the prepared payload and closes admission. A crash after release and before completion is replayable. A failed completion acknowledgement is reconciled against the durable ledger: confirmed completion succeeds, an uncommitted intent stays pending, and an unknown outcome remains closed. Retry only the same original action and payload after inspection; changed files or payloads conflict. Nonparticipating writers still have a final comparison-to-replacement/removal race; these operations are not a multi-file transaction.
|
|
210
|
+
|
|
211
|
+
Accepted implementation input prepares aggregate and selected pending milestone progress before native admission. Message, queue and steering requests record accepted implementation scope; an in-progress marker does not assert that a provider has started or completed a turn. Progress is journaled and released before current authority is checked again for native admission. A retry of the same native action can finish its retained progress intent without regenerating timestamps; it still needs current runtime/authorization checks. Native control and permission actions do not advance progress.
|
|
212
|
+
|
|
213
|
+
Only accepted completion evidence advances a milestone to done. Aggregate done requires the complete current execution contract, applicable current approval/finalization and verified completion; administrative done markers alone do not provide them. Progress-only plan changes preserve revision and set updated_at once in the saved prepared source. An unchanged plan preserves its timestamp. The current finalization receipt retains the operator event, semantic revision, nullable canonical file hash and timestamp independently of write recovery bodies. Status reads expose pendingActionId for unresolved writes and never approve or resume work.
|
|
198
214
|
|
|
199
215
|
`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.
|
|
200
216
|
|
|
@@ -206,7 +222,7 @@ Begin revision before invoking a planning skill. Execution admission closes unde
|
|
|
206
222
|
|
|
207
223
|
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.
|
|
208
224
|
|
|
209
|
-
After native `jg-plan` revises the contract and an explicitly requested `jg-breakdown` regenerates a needed sequence, close the planning controller before finalization. Only unique exact
|
|
225
|
+
After native `jg-plan` revises the contract and an explicitly requested `jg-breakdown` regenerates a needed sequence, close the planning controller before finalization. Only unique exact title and complete-contract matches retain identity automatically. Every unmatched checkpoint source, including done and partial work, appears in one saved proposal. Status exposes its nullable `coordination.revision.proposalId`; clients use the paged reconciliation reads to present correspondence and confirm that exact saved identity. 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.
|
|
210
226
|
|
|
211
227
|
A whole-plan checkpoint retains null milestones and an empty milestone inventory. If a revision removes a sequence because the remaining scope no longer needs one, every unmatched checkpoint milestone still requires explicit omission confirmation. Its verified evidence remains available; absence alone never resets progress or authorizes whole-plan execution.
|
|
212
228
|
|
|
@@ -14,14 +14,14 @@ export declare const createActions: (native: ICodexProvider, claude: ReturnType<
|
|
|
14
14
|
* Returns after durable admission; the native operation outlives this client request.
|
|
15
15
|
* @returns The durable admission receipt after validation.
|
|
16
16
|
* @throws
|
|
17
|
-
* -
|
|
18
|
-
* -
|
|
19
|
-
* -
|
|
20
|
-
* -
|
|
21
|
-
* -
|
|
22
|
-
* -
|
|
23
|
-
* -
|
|
24
|
-
* -
|
|
17
|
+
* - JG_AGENT_HQ_ACTION_CONFLICT: The HQ action conflicts with its recorded state
|
|
18
|
+
* - JG_AGENT_HQ_SKILL_UNAVAILABLE: The HQ skill is unavailable
|
|
19
|
+
* - JG_AGENT_HQ_REQUEST_INVALID: The HQ request is invalid
|
|
20
|
+
* - JG_AGENT_HQ_TARGET_FORBIDDEN: The HQ target is outside the allowed workspaces
|
|
21
|
+
* - JG_AGENT_HQ_CODEX_FAILED: The Codex integration failed
|
|
22
|
+
* - JG_AGENT_HQ_CLAUDE_FAILED: The Claude integration failed
|
|
23
|
+
* - JG_AGENT_HQ_CLAUDE_HISTORY_UNAVAILABLE: The Claude history is unavailable
|
|
24
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
25
25
|
*/
|
|
26
26
|
submit(action: IActionEnvelope): Promise<IActionReceipt>;
|
|
27
27
|
/** Reads only current in-memory prompts for the selected managed thread. */
|
|
@@ -30,21 +30,21 @@ export declare const createActions: (native: ICodexProvider, claude: ReturnType<
|
|
|
30
30
|
* Quiesces the selected managed cohort without stopping unrelated controllers.
|
|
31
31
|
* @returns A promise resolved only after interruption, background cleanup and release evidence.
|
|
32
32
|
* @throws
|
|
33
|
-
* -
|
|
34
|
-
* -
|
|
35
|
-
* -
|
|
36
|
-
* -
|
|
37
|
-
* -
|
|
33
|
+
* - JG_AGENT_HQ_ACTION_CONFLICT: The HQ action conflicts with its recorded state
|
|
34
|
+
* - JG_AGENT_HQ_TARGET_FORBIDDEN: The HQ target is outside the allowed workspaces
|
|
35
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
36
|
+
* - JG_AGENT_HQ_CODEX_FAILED: The Codex integration failed
|
|
37
|
+
* - JG_AGENT_HQ_CLAUDE_FAILED: The Claude integration failed
|
|
38
38
|
*/
|
|
39
39
|
quiescePlan(controls: IPlanRevisionWorkflow["controls"]): Promise<void>;
|
|
40
40
|
/**
|
|
41
41
|
* Stops admission, interrupts active work, cleans native terminals and confirms shutdown.
|
|
42
42
|
* @returns A promise resolved after native exit and release of durable control ownership.
|
|
43
43
|
* @throws
|
|
44
|
-
* -
|
|
45
|
-
* -
|
|
46
|
-
* -
|
|
47
|
-
* -
|
|
44
|
+
* - JG_AGENT_HQ_CODEX_FAILED: The Codex integration failed
|
|
45
|
+
* - JG_AGENT_HQ_CLAUDE_FAILED: The Claude integration failed
|
|
46
|
+
* - JG_AGENT_HQ_TRANSPORT_FAILED: The HQ transport failed
|
|
47
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
48
48
|
*/
|
|
49
49
|
close(): Promise<void>;
|
|
50
50
|
};
|
package/dist/actions/actions.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHmac, randomUUID } from 'node:crypto';
|
|
2
|
-
import { Exception, extractMessage } from '
|
|
2
|
+
import { Exception, extractMessage, isException } from 'jg-exception';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { setTimeout as wait } from 'node:timers/promises';
|
|
5
5
|
import { getErrorKind } from '../errors/index.js';
|
|
@@ -40,12 +40,18 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
40
40
|
let unavailable = false;
|
|
41
41
|
let eventFailure;
|
|
42
42
|
const conflict = () => {
|
|
43
|
-
throw new Exception('The HQ action conflicts with its recorded state',
|
|
44
|
-
|
|
43
|
+
throw new Exception('The HQ action conflicts with its recorded state', {
|
|
44
|
+
code: 'JG_AGENT_HQ_ACTION_CONFLICT',
|
|
45
|
+
data: {
|
|
46
|
+
kind: 'state-conflict',
|
|
47
|
+
},
|
|
45
48
|
});
|
|
46
49
|
};
|
|
47
50
|
const agentUnavailable = () => {
|
|
48
|
-
throw new Exception('The Codex integration failed',
|
|
51
|
+
throw new Exception('The Codex integration failed', {
|
|
52
|
+
code: 'JG_AGENT_HQ_CODEX_FAILED',
|
|
53
|
+
data: { kind: 'agent-unavailable' },
|
|
54
|
+
});
|
|
49
55
|
};
|
|
50
56
|
/** Quarantines controls after a lifecycle gap and stops the native transport. */
|
|
51
57
|
const failEvents = (cause) => {
|
|
@@ -111,7 +117,10 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
111
117
|
if (unavailable)
|
|
112
118
|
return;
|
|
113
119
|
if (eventCount >= 128) {
|
|
114
|
-
failEvents(new Exception('The Codex integration failed',
|
|
120
|
+
failEvents(new Exception('The Codex integration failed', {
|
|
121
|
+
code: 'JG_AGENT_HQ_CODEX_FAILED',
|
|
122
|
+
data: { kind: 'agent-unavailable' },
|
|
123
|
+
}));
|
|
115
124
|
return;
|
|
116
125
|
}
|
|
117
126
|
eventCount += 1;
|
|
@@ -179,8 +188,8 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
179
188
|
* Dispatches one admitted intent once and records delivery without replaying it.
|
|
180
189
|
* @returns A promise resolved after delivery evidence or uncertainty is persisted.
|
|
181
190
|
* @throws
|
|
182
|
-
* -
|
|
183
|
-
* -
|
|
191
|
+
* - JG_AGENT_HQ_ACTION_CONFLICT: The HQ action conflicts with its recorded state
|
|
192
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
184
193
|
*/
|
|
185
194
|
const dispatch = async (initial, originalThread, command, input) => {
|
|
186
195
|
let receipt = initial;
|
|
@@ -295,7 +304,7 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
295
304
|
}
|
|
296
305
|
catch (error) {
|
|
297
306
|
// Only a matching native error response proves rejection. Transport loss and malformed results remain uncertain.
|
|
298
|
-
const explicit = error
|
|
307
|
+
const explicit = isException(error) && NativeRejectionSchema.safeParse(error.data).success;
|
|
299
308
|
const kind = getErrorKind(error);
|
|
300
309
|
const failure = kind === 'state-conflict' || kind === 'access-denied' || kind === 'agent-unavailable'
|
|
301
310
|
? kind
|
|
@@ -620,14 +629,14 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
620
629
|
* Validates the current target and separates new dispatch from idempotent receipt reads.
|
|
621
630
|
* @returns The durable admission receipt; native work runs independently.
|
|
622
631
|
* @throws
|
|
623
|
-
* -
|
|
624
|
-
* -
|
|
625
|
-
* -
|
|
626
|
-
* -
|
|
627
|
-
* -
|
|
628
|
-
* -
|
|
629
|
-
* -
|
|
630
|
-
* -
|
|
632
|
+
* - JG_AGENT_HQ_ACTION_CONFLICT: The HQ action conflicts with its recorded state
|
|
633
|
+
* - JG_AGENT_HQ_SKILL_UNAVAILABLE: The HQ skill is unavailable
|
|
634
|
+
* - JG_AGENT_HQ_REQUEST_INVALID: The HQ request is invalid
|
|
635
|
+
* - JG_AGENT_HQ_TARGET_FORBIDDEN: The HQ target is outside the allowed workspaces
|
|
636
|
+
* - JG_AGENT_HQ_CODEX_FAILED: The Codex integration failed
|
|
637
|
+
* - JG_AGENT_HQ_CLAUDE_FAILED: The Claude integration failed
|
|
638
|
+
* - JG_AGENT_HQ_CLAUDE_HISTORY_UNAVAILABLE: The Claude history is unavailable
|
|
639
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
631
640
|
*/
|
|
632
641
|
const admitAndDispatch = async (action) => {
|
|
633
642
|
// The worker verifies the complete digest before returning any existing receipt.
|
|
@@ -810,14 +819,14 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
810
819
|
* Returns after durable admission; the native operation outlives this client request.
|
|
811
820
|
* @returns The durable admission receipt after validation.
|
|
812
821
|
* @throws
|
|
813
|
-
* -
|
|
814
|
-
* -
|
|
815
|
-
* -
|
|
816
|
-
* -
|
|
817
|
-
* -
|
|
818
|
-
* -
|
|
819
|
-
* -
|
|
820
|
-
* -
|
|
822
|
+
* - JG_AGENT_HQ_ACTION_CONFLICT: The HQ action conflicts with its recorded state
|
|
823
|
+
* - JG_AGENT_HQ_SKILL_UNAVAILABLE: The HQ skill is unavailable
|
|
824
|
+
* - JG_AGENT_HQ_REQUEST_INVALID: The HQ request is invalid
|
|
825
|
+
* - JG_AGENT_HQ_TARGET_FORBIDDEN: The HQ target is outside the allowed workspaces
|
|
826
|
+
* - JG_AGENT_HQ_CODEX_FAILED: The Codex integration failed
|
|
827
|
+
* - JG_AGENT_HQ_CLAUDE_FAILED: The Claude integration failed
|
|
828
|
+
* - JG_AGENT_HQ_CLAUDE_HISTORY_UNAVAILABLE: The Claude history is unavailable
|
|
829
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
821
830
|
*/
|
|
822
831
|
async submit(action) {
|
|
823
832
|
const admission = admitAndDispatch(action);
|
|
@@ -839,11 +848,11 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
839
848
|
* Quiesces the selected managed cohort without stopping unrelated controllers.
|
|
840
849
|
* @returns A promise resolved only after interruption, background cleanup and release evidence.
|
|
841
850
|
* @throws
|
|
842
|
-
* -
|
|
843
|
-
* -
|
|
844
|
-
* -
|
|
845
|
-
* -
|
|
846
|
-
* -
|
|
851
|
+
* - JG_AGENT_HQ_ACTION_CONFLICT: The HQ action conflicts with its recorded state
|
|
852
|
+
* - JG_AGENT_HQ_TARGET_FORBIDDEN: The HQ target is outside the allowed workspaces
|
|
853
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
854
|
+
* - JG_AGENT_HQ_CODEX_FAILED: The Codex integration failed
|
|
855
|
+
* - JG_AGENT_HQ_CLAUDE_FAILED: The Claude integration failed
|
|
847
856
|
*/
|
|
848
857
|
async quiescePlan(controls) {
|
|
849
858
|
const failures = [];
|
|
@@ -860,10 +869,10 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
860
869
|
* Stops admission, interrupts active work, cleans native terminals and confirms shutdown.
|
|
861
870
|
* @returns A promise resolved after native exit and release of durable control ownership.
|
|
862
871
|
* @throws
|
|
863
|
-
* -
|
|
864
|
-
* -
|
|
865
|
-
* -
|
|
866
|
-
* -
|
|
872
|
+
* - JG_AGENT_HQ_CODEX_FAILED: The Codex integration failed
|
|
873
|
+
* - JG_AGENT_HQ_CLAUDE_FAILED: The Claude integration failed
|
|
874
|
+
* - JG_AGENT_HQ_TRANSPORT_FAILED: The HQ transport failed
|
|
875
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
867
876
|
*/
|
|
868
877
|
async close() {
|
|
869
878
|
closing = true;
|
|
@@ -902,7 +911,11 @@ export const createActions = (native, claude, readClaudeThread, store, roots, ep
|
|
|
902
911
|
await lane.catch(() => undefined);
|
|
903
912
|
const failedExit = nativeExit.find((result) => result.status === 'rejected');
|
|
904
913
|
if (failedExit?.status === 'rejected')
|
|
905
|
-
throw new Exception(`The HQ transport failed: ${extractMessage(failedExit.reason)}`,
|
|
914
|
+
throw new Exception(`The HQ transport failed: ${extractMessage(failedExit.reason)}`, {
|
|
915
|
+
code: 'JG_AGENT_HQ_TRANSPORT_FAILED',
|
|
916
|
+
data: { kind: 'operation-failed' },
|
|
917
|
+
cause: cleanupFailure ?? failedExit.reason,
|
|
918
|
+
});
|
|
906
919
|
}
|
|
907
920
|
if (cleanupFailure)
|
|
908
921
|
throw cleanupFailure;
|
package/dist/actions/reads.d.ts
CHANGED
|
@@ -8,10 +8,10 @@ type IControlRead = Extract<IHqRequest, {
|
|
|
8
8
|
* Authorizes bounded control reads and binds seek positions to their exact query.
|
|
9
9
|
* @returns The selected record or bounded page.
|
|
10
10
|
* @throws
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
11
|
+
* - JG_AGENT_HQ_ACTION_CONFLICT: The HQ action conflicts with its recorded state
|
|
12
|
+
* - JG_AGENT_HQ_CURSOR_INVALID: The HQ cursor does not match this request
|
|
13
|
+
* - JG_AGENT_HQ_TARGET_FORBIDDEN: The HQ target is outside the allowed workspaces
|
|
14
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
15
15
|
*/
|
|
16
16
|
export declare const readControl: (command: IControlRead, store: IStore, actions: ReturnType<typeof createActions>, roots: string[]) => Promise<IHqResponse>;
|
|
17
17
|
export {};
|
package/dist/actions/reads.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Exception } from '
|
|
1
|
+
import { Exception } from 'jg-exception';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { resolveWorkspaceTarget } from '../runtime/state/index.js';
|
|
4
4
|
import { decodeHistoryCursor, encodeHistoryCursor } from '../sessions/index.js';
|
|
@@ -6,7 +6,7 @@ const PositionSchema = z.strictObject({ createdAt: z.number().int(), id: z.uuid(
|
|
|
6
6
|
/**
|
|
7
7
|
* Validates the application-owned seek position after the shared query-binding check.
|
|
8
8
|
* @throws
|
|
9
|
-
* -
|
|
9
|
+
* - JG_AGENT_HQ_CURSOR_INVALID: The HQ cursor does not match this request
|
|
10
10
|
*/
|
|
11
11
|
const readPosition = (cursor, filters) => {
|
|
12
12
|
const decoded = decodeHistoryCursor(cursor, filters);
|
|
@@ -16,7 +16,11 @@ const readPosition = (cursor, filters) => {
|
|
|
16
16
|
return PositionSchema.parse(JSON.parse(decoded));
|
|
17
17
|
}
|
|
18
18
|
catch (cause) {
|
|
19
|
-
throw new Exception('The HQ cursor does not match this request',
|
|
19
|
+
throw new Exception('The HQ cursor does not match this request', {
|
|
20
|
+
code: 'JG_AGENT_HQ_CURSOR_INVALID',
|
|
21
|
+
data: { kind: 'invalid-request' },
|
|
22
|
+
cause,
|
|
23
|
+
});
|
|
20
24
|
}
|
|
21
25
|
};
|
|
22
26
|
/** Encodes the final row's complete ordering tuple only when another page exists. */
|
|
@@ -28,10 +32,10 @@ const nextPageCursor = (page, filters) => {
|
|
|
28
32
|
* Authorizes bounded control reads and binds seek positions to their exact query.
|
|
29
33
|
* @returns The selected record or bounded page.
|
|
30
34
|
* @throws
|
|
31
|
-
* -
|
|
32
|
-
* -
|
|
33
|
-
* -
|
|
34
|
-
* -
|
|
35
|
+
* - JG_AGENT_HQ_ACTION_CONFLICT: The HQ action conflicts with its recorded state
|
|
36
|
+
* - JG_AGENT_HQ_CURSOR_INVALID: The HQ cursor does not match this request
|
|
37
|
+
* - JG_AGENT_HQ_TARGET_FORBIDDEN: The HQ target is outside the allowed workspaces
|
|
38
|
+
* - JG_AGENT_HQ_STORE_FAILED: The HQ store failed
|
|
35
39
|
*/
|
|
36
40
|
export const readControl = async (command, store, actions, roots) => {
|
|
37
41
|
const authorize = async (thread) => {
|
|
@@ -80,8 +84,11 @@ export const readControl = async (command, store, actions, roots) => {
|
|
|
80
84
|
if (command.kind === 'managed-thread')
|
|
81
85
|
return { kind: command.kind, result: thread };
|
|
82
86
|
if (!thread)
|
|
83
|
-
throw new Exception('The HQ action conflicts with its recorded state',
|
|
84
|
-
|
|
87
|
+
throw new Exception('The HQ action conflicts with its recorded state', {
|
|
88
|
+
code: 'JG_AGENT_HQ_ACTION_CONFLICT',
|
|
89
|
+
data: {
|
|
90
|
+
kind: 'state-conflict',
|
|
91
|
+
},
|
|
85
92
|
});
|
|
86
93
|
if (command.kind === 'events')
|
|
87
94
|
return {
|