jjhub 0.1.14 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jjhub",
3
- "version": "0.1.14",
3
+ "version": "0.2.0",
4
4
  "description": "jjhub — GitHub CLI with Jujutsu-native superpowers: stable change IDs, stacks, platform-wide undo, and conflicts that wait, layered over plain GitHub repos by a JJHub server.",
5
5
  "bin": {
6
6
  "jjhub": "./dist/cli/jjhub.mjs"
@@ -10,7 +10,7 @@
10
10
  "node": ">=22.6.0"
11
11
  },
12
12
  "license": "UNLICENSED",
13
- "homepage": "https://jjhub.johnhenry.me",
13
+ "homepage": "https://jjhub.erisera.com",
14
14
  "keywords": [
15
15
  "jujutsu",
16
16
  "jj",
@@ -51,7 +51,11 @@ repo delete hard-delete incl. op log (ops credential
51
51
 
52
52
  user list list known users (identity is GitHub-federated)
53
53
 
54
- change new <title> [--parent CHG-x] [--stack id]
54
+ change new <title> [--parent CHG-x] [--stack id] [--route same-repo|unprojected|fork:<owner/name>]
55
+ --route (issue #277): same-repo is the default; unprojected
56
+ creates the change with no GitHub branch/PR ever; fork:<owner/name>
57
+ is recorded but refused at projection time until real fork-PR
58
+ projection ships
55
59
  change list
56
60
  change show <changeId>
57
61
  change describe <changeId> [--title t] [--description d]
@@ -59,33 +63,113 @@ change amend <changeId>
59
63
  change squash <changeId>
60
64
  change abandon <changeId>
61
65
  change restack <changeId> rebase a needs-restack change onto its rewritten ancestor
62
- change commit <changeId> [<file...>] [-m msg] [--delete <path>]...
66
+ change commit <changeId> [<file...>] [-m msg] [--delete <path>]... [--expect-head <sha>]
63
67
  commit working-tree files onto the change's branch;
64
- --delete removes a path in the same commit (repeatable)
68
+ --delete removes a path in the same commit (repeatable);
69
+ --expect-head refuses (409) if the change moved since <sha>
70
+ change propose <title> [<file...>] [--parent CHG-x] [--stack id] [-m msg]
71
+ [--delete <path>]... [--expect-base <sha>]
72
+ issue #374: create + commit in one call, printing the diff
73
+ summary and PR link; --expect-base checks --parent's current
74
+ commit; on partial failure the error names the created change
75
+ id (still listed/abandon-able)
65
76
  change diff <changeId> per-file diffs of what the change contains
66
77
  change files <changeId> list locally-stored files (contentMode "local" repos only)
67
- change land <changeId> [--force] waits for real CI triggered by its own ready flip,
68
- re-syncs a behind branch, then merges; --force bypasses
78
+ change land <changeId> [--force] [--expect-head <sha>]
79
+ waits for real CI triggered by its own ready flip,
80
+ re-syncs a behind branch, then merges; --force bypasses;
81
+ --expect-head refuses (409) if the change moved since <sha>
82
+ change enqueue <changeId> add a review-ready pull request to GitHub's merge queue;
83
+ GitHub owns the merge from here, JJHub marks the change
84
+ landed once GitHub reports it merged
85
+ change dequeue <changeId> withdraw a JJHub-queued pull request back to explicit review
86
+ change queue-status <changeId> print the merge-queue receipt (position/state/merge-group
87
+ sha/checks/removed reason) plus whether GitHub auto-merge
88
+ is armed on the pull request
69
89
  change split <changeId> <newTitle>
70
90
  change checks <changeId> list GitHub check runs for a change
71
91
  change actions <changeId> show bounded GitHub Actions workflow and job evidence
92
+ change actions rerun <changeId> <runId>
93
+ ask GitHub to re-run a workflow run shown by "change actions"
94
+ change actions cancel <changeId> <runId>
95
+ ask GitHub to cancel a workflow run shown by "change actions"
72
96
  change deployments <changeId> show bounded GitHub deployment evidence
73
97
  change security <changeId> show bounded GitHub code-scanning evidence
74
98
  change issues <changeId> show linked GitHub issue context for a change
99
+ change reviewers <changeId> reviewer-routing audit trail: every request/remove that
100
+ actually succeeded against GitHub, who did it, and when
101
+ change recommend-reviewers <changeId> advisory-only reviewer suggestions from CODEOWNERS, prior
102
+ review history, and recent file authorship — never requests
103
+ a reviewer; use "change reviewers" to see actual requests
104
+ change review-health <changeId> live GitHub review-collaboration summary: state, requested
105
+ reviewers, stale/dismissed approvals, unresolved threads,
106
+ CODEOWNERS evidence, and GitHub's effective merge requirement
107
+ change landability <changeId> show the effective GitHub landability policy report — every
108
+ gate's state and resolution, plus the overall verdict
109
+ change projects <changeId> show bounded GitHub Projects v2 evidence for linked issues
110
+ change handoff <changeId> durable task-handoff log (issue #373): findings, validation
111
+ evidence, outstanding work, or a verified commit SHA another
112
+ agent (or the same one later) can pick up without reconstructing
113
+ a chat transcript; works against a landed or abandoned change too
114
+ change handoff <changeId> --add <kind> -m <body>
115
+ append one entry (never updates/deletes an existing one);
116
+ kind: note | status | question | decision | blocker | plan
117
+ change deps <changeId> list a change's declared read-only external dependencies
118
+ (issue #277); with no flag, lists current state
119
+ change deps <changeId> --set kind:owner/repo#ref [--set ...]
120
+ replace-all declaration of external dependency edges
121
+ (kind is issue|pull_request|release|bookmark); never itself
122
+ reads GitHub and never gates landing (advisory only)
123
+ change deps <changeId> --refresh best-effort live GitHub read of every declared dependency's
124
+ current state (open/closed, released/draft, exists/missing)
125
+ change evolution <changeId> auditable logical-change timeline (issue #275): kind, related
126
+ change ids, before/after evidence, remote recovery limits
127
+ change recover <changeId> --keep left|right|both
128
+ resolve a recorded divergence (issue #275) between two live
129
+ changeIds that both claim the same underlying jj change id;
130
+ left/right abandons the other side, both marks it resolved
131
+ without abandoning either; refuses (409) if either is landed
75
132
 
76
133
  stack create <title> [--id x] [--changes CHG-1,CHG-2]
77
134
  stack list
78
135
  stack land <stackId> [--force] same check-run gate as change land
136
+ stack enqueue <stackId> queue a LINEAR stack root->tip via change enqueue's own path;
137
+ refuses (409) before any GitHub call if the stack isn't linear
138
+ (a member with more than one parent, an unprojected member, or
139
+ a base that doesn't chain onto the previous member); prints each
140
+ member's own outcome (queued/skipped/failed) rather than an
141
+ all-or-nothing result
79
142
  stack delete <stackId> disband — members become loose changes (undoable)
80
143
  stack reorder <stackId> <changeId,changeId,...>
81
144
  stack checks <stackId> every member's GitHub check runs, one batched round trip
82
145
  stack issues <stackId> linked issue and external-blocker summary for a stack
146
+ stack review-health <stackId> per-member review-health summary, one batched round trip
147
+ stack landability <stackId> per-member effective GitHub landability policy report plus
148
+ the overall verdict, one batched round trip; a member blocked
149
+ behind an earlier, not-yet-landable member carries its own
150
+ "stack-order" requirement
151
+
152
+ project rules list list this repo's Projects v2 lifecycle->field mapping rules
153
+ project rules set --project <projectNodeId> --field <fieldNodeId> --option <optionId>
154
+ --when <draft|in_review|queued|landed|abandoned|blocked> [--id <ruleId>] [--disabled]
155
+ project rules delete <ruleId>
156
+ project preview <changeId> preview what "project apply" would do right now, without writing
157
+ project apply <changeId> evaluate and write matching rules now; automatic dispatch already
158
+ runs this on land
83
159
 
84
160
  bookmark list
85
161
  bookmark delete <name> [--force] --force required for the default (trunk) bookmark
86
162
  bookmark set <name> <tracked|view> [--target CHG-x]
87
163
 
164
+ view save <name> <revsetExpression> save a named jj revset expression for later reuse (storage
165
+ only — evaluate it with "jjhub revset")
166
+ view list list saved views in this repo
167
+ view delete <name>
168
+
88
169
  op log "@" marks the current head operation
170
+ op diff <fromOpId> <toOpId> structural diff between two operations' immutable snapshots
171
+ (which changes/stacks/bookmarks/conflicts were created,
172
+ modified, or removed); works for adjacent or far-apart ops
89
173
  undo [--force] refused when the head op is a "land" (real merge can't be unwound); --force reverts local state anyway
90
174
  redo
91
175
 
@@ -105,7 +189,18 @@ auth sessions list your live sessions; auth revoke <id>
105
189
  auth logout forget the saved connection/token
106
190
  auth status who the saved credential authenticates as
107
191
 
108
- mcp serve MCP server over stdio (77 tools) for agent clients
192
+ ai models --provider <p> [--api-key <key>] [--base-url <url>]
193
+ live model list for one AI provider (issue #472); the key
194
+ is used for this one request only and never saved. Without
195
+ --api-key, falls back to your already-saved AI connection's
196
+ key for that same provider, if any. Always succeeds — a
197
+ live-lookup failure shows source: static_fallback with a
198
+ detail message rather than an error, since a free-text model
199
+ id always works when configuring AI, listed or not
200
+ ai status where AI is coming from for you: your own saved connection,
201
+ the server operator's default, or not configured at all
202
+
203
+ mcp serve MCP server over stdio (125 tools) for agent clients
109
204
  mcp serve --http <port> the same tools over Streamable HTTP (POST /)
110
205
  acp serve Agent Client Protocol agent over stdio (Zed's agent
111
206
  panel, ...) — every operation as a slash command
@@ -124,13 +219,31 @@ topology <localRepoPath> [--engine subprocess]
124
219
  revset <localRepoPath> <expression> [--engine subprocess]
125
220
  evaluate the installed jj binary's revset in exactly the named workspace;
126
221
  this is local, read-only discovery rather than a server-side approximation
222
+ revset <expression> --workspace <workspaceId> [--repo owner/name] [--limit N]
223
+ REMOTE form (issue #274): relays the query through the JJHub server to
224
+ that exact workspace's own "jjhub daemon" and polls for the result — use
225
+ when you're not on the machine with the workspace checked out. Slower
226
+ (bound by the daemon's sync interval) and needs that daemon healthy;
227
+ same result shape/error taxonomy as the local form above
127
228
 
128
229
  content preview <localRepoPath> <split|absorb|squash|duplicate|restore>
129
230
  --source <jj-change-id> [--destination <jj-change-id>] [--path <relative-path>]...
130
231
  content apply <localRepoPath> <split|absorb|squash|duplicate|restore>
131
232
  same selection plus --expected-operation <jj-operation-id> returned by preview
132
233
  local-only jj content curation; checked against jj's immutable policy and
133
- never implemented as a browser patch transform
234
+ never implemented as a browser patch transform; records a durable receipt
235
+ on the JJHub server (best-effort — see "content receipts" below)
236
+ content preview|apply --workspace <workspaceId> <split|absorb|squash|duplicate|restore>
237
+ --op <json> | (--source <jj-change-id> [--destination <jj-change-id>]
238
+ [--path <relative-path>]... [--title <title>]) [--expected-operation <id>]
239
+ REMOTE form (issue #276): relays the preview/apply through the JJHub server to
240
+ that exact workspace's own "jjhub daemon" and polls for the result — use
241
+ when you're not on the machine with the workspace checked out. jj's own
242
+ immutable-commits check and JJHub's landed-change guard both apply; a
243
+ successful apply also appends a durable content_op_receipts entry
244
+ content receipts [--repo owner/name|repoId]
245
+ list this repo's content-op receipt trail: every content apply invocation,
246
+ successful or rejected, with its kind, revisions, and outcome
134
247
  ```
135
248
 
136
249
  Anything else (`pr`, `issue`, ...) is passed through to `gh` — e.g. `jjhub pr view 7`. `jjhub auth`
@@ -200,6 +313,25 @@ npm run jjhub -- stack land "Fix bundle"
200
313
 
201
314
  A single change not part of a stack lands directly: `npm run jjhub -- change land CHG-1`.
202
315
 
316
+ ### Use GitHub's merge queue instead of a direct land
317
+
318
+ When the target branch requires it, add a review-ready change to GitHub's
319
+ merge queue rather than merging it directly — GitHub owns the merge from
320
+ there, and JJHub only marks the change landed once GitHub reports it merged:
321
+
322
+ ```bash
323
+ npm run jjhub -- change request-review CHG-1
324
+ npm run jjhub -- change enqueue CHG-1
325
+ npm run jjhub -- change queue-status CHG-1 # position/state/merge-group evidence,
326
+ # removal reason if GitHub removed it,
327
+ # and whether GitHub auto-merge is armed
328
+ npm run jjhub -- change dequeue CHG-1 # withdraw back to explicit review
329
+ ```
330
+
331
+ A change JJHub knows is queued cannot be rewritten (`describe`/`amend`/
332
+ `restack`/...) or landed directly until it is dequeued — `change land`
333
+ refuses with a message naming the queue.
334
+
203
335
  ### Sync a local jj working copy into JJHub
204
336
 
205
337
  ```bash
@@ -243,6 +375,15 @@ targets are refused without `--ignore-immutable`. `--path` selects complete
243
375
  relative paths; interactive hunk selection remains jj's configured diff editor.
244
376
  Run `jjhub daemon . --once` afterwards to reconcile the local graph.
245
377
 
378
+ Each `content apply` invocation — successful or rejected (e.g. a stale
379
+ `--expected-operation`) — records a durable receipt on the JJHub server
380
+ (best-effort: a missing repo context or unreachable server only produces a
381
+ warning, never blocks the local jj mutation). Review the trail with:
382
+
383
+ ```bash
384
+ npm run jjhub -- content receipts
385
+ ```
386
+
246
387
  ### Resolve a conflict
247
388
 
248
389
  ```bash