@@ -122,6 +122,7 @@ Array is a thin layer over jj. It stores almost nothing.
122122- Track stack state (jj DAG has it)
123123- Store enabled changesets (jj merge parents)
124124- Store PR mappings (derived from branch names)
125+ - Store repo-level config (no ` .array/ ` directory)
125126
126127** Benefits:**
127128- Can't get out of sync with jj
@@ -132,22 +133,29 @@ Array is a thin layer over jj. It stores almost nothing.
132133** Only state Array stores:**
133134- ` ~/.config/array/auth.json ` — GitHub token
134135
136+ ** Derived state:**
137+
138+ | Data | Source |
139+ | ------| --------|
140+ | Changes, stack, DAG | jj |
141+ | Trunk branch | jj's ` trunk() ` revset |
142+ | PR ↔ change mapping | Derived from branch name |
143+ | Enabled changesets | jj DAG (merge parents) |
144+
135145---
136146
137147## Onboarding
138148
139149### Repository Detection
140- - When I run array in a directory with ` .git ` , it detects it as a git repo
141- - When I run array in a directory without ` .git ` , it prompts to initialize
142- - When I run array in a directory with ` .jj ` , it's ready to use
143- - Array requires jj, that's it
150+ - When I run array in a directory with ` .git ` only, it prompts me to run ` jj git init --colocate `
151+ - When I run array in a directory without ` .git ` , it prompts to run ` git init && jj git init --colocate `
152+ - When I run array in a jj-colocated repo, it's ready to use (no ` arr init ` needed)
144153
145154### Initialization
146155- When I initialize git, a ` .git ` directory is created with an initial commit
147156- When I initialize jj in a git repo, a ` .jj ` directory is created alongside ` .git `
148157- When I initialize jj, my existing git commits are imported
149- - When I initialize jj, trunk is auto-detected (` main ` or ` master ` ) and set as ` trunk() ` revset
150- - Array has no separate initialization — if jj is set up, Array works
158+ - When jj is initialized, trunk is auto-detected via jj's built-in ` trunk() ` revset
151159
152160### Prerequisites
153161- When jj is installed, I can check its version
@@ -180,19 +188,20 @@ Array is a thin layer over jj. It stores almost nothing.
180188- Branch name format is ` MM-DD-description_slug ` (e.g., ` 12-22-add_user_auth ` )
181189
182190### Prerequisites
183- - When @ has no changes and I create, I get an error ("No changes to save")
184191- When I provide an empty message, I get an error
192+ - When @ has no file changes, I get an error "No changes to save"
185193
186194### Multiple Stacks
187195- When I create from trunk (empty @ above main), it starts a new stack
188196- I can have multiple independent stacks off trunk
189197- Each stack is a linear chain of changes
190198
191199### Viewing Multiple Stacks
192- - When I run ` arr log ` , I see ALL mutable stacks (not just current)
200+ - When I run ` arr log ` , I see only mutable stacks (not just current)
193201- Each stack is visually separated with branch prefixes
194202- I can see which stack I'm currently in (marked with ◉)
195- - Immutable/orphaned branches are NOT shown (they're historical artifacts)
203+ - Immutable commits (pushed to remote) are NOT shown - use ` jj log ` to see them
204+ - Remote-tracking branches that have been merged/deleted are filtered out via ` mutable() ` revset
196205
197206### Switching Between Stacks
198207- When I run ` arr checkout ` with a change from another stack, I switch to that stack
@@ -212,7 +221,8 @@ Array is a thin layer over jj. It stores almost nothing.
212221- When my change has multiple children and I go up, I get an error (ambiguous)
213222
214223### Jumping to Ends
215- - When I go to top, I get an empty @ above the topmost change (ready for new work)
224+ - When I go to top and @ is already empty/undescribed with no children, I stay where I am
225+ - When I go to top otherwise, I get an empty @ above the topmost change (via ` jj new ` )
216226- When I go to bottom, @ becomes the first change above trunk
217227- When my stack branches and I go to top, I get an error (ambiguous path)
218228
@@ -248,8 +258,8 @@ Array is a thin layer over jj. It stores almost nothing.
248258- When I continue with no pending operation, I get an error
249259
250260### Quick Amend (arr modify)
251- - When I run ` arr modify ` , my edits squash into @- (parent)
252- - When @ has no changes , I get an error
261+ - When I run ` arr modify ` , my edits squash into @- (parent) via ` jj squash `
262+ - When @ is empty AND has no description , I get an error "No changes to squash"
253263- After modify, I'm still on empty @ (ready for more work)
254264- Descendants of the modified change auto-rebase
255265
@@ -381,8 +391,8 @@ Array is a thin layer over jj. It stores almost nothing.
381391### After Merge
382392- When I sync after a PR merged, the merged branch is deleted locally
383393- When I sync after a PR merged, my stack is rebased onto trunk
384- - When I sync after a PR merged, remaining PRs have bases updated
385- - When I sync after a PR merged, stack comments are updated on remaining PRs
394+ - When I sync after a PR merged, remaining PRs have their base branches updated to trunk via GitHub API
395+ - When I sync after a PR merged, stack comments are updated on remaining PRs (showing full history including merged)
386396
387397### Branch Naming on GitHub
388398- Branches are named ` MM-DD-description_slug `
@@ -402,8 +412,8 @@ Array is a thin layer over jj. It stores almost nothing.
402412- When I sync after a PR merged, trunk includes my merged changes
403413- When I sync, rebasing onto new trunk makes merged changes EMPTY (no diff)
404414- When I sync, empty changes are detected and abandoned (` jj abandon ` )
405- - When I sync, the next PR's base is updated to trunk
406- - When I sync, stack comments are updated on remaining PRs
415+ - When I sync, the next PR's base branch is updated to trunk via GitHub API ( ` gh pr edit --base ` )
416+ - When I sync, stack comments are updated on remaining PRs (showing full history including merged)
407417
408418### How Merged Detection Works
409419
@@ -642,48 +652,3 @@ This is stateless. jj handles the merge. Your working directory shows the combin
642652- Array commands are wrappers around jj, not a replacement
643653- If array gets confused, ` jj log ` shows the true state
644654
645- ---
646-
647- ## Configuration
648-
649- ### Philosophy: Stateless
650-
651- Array stores almost nothing. jj is the source of truth.
652-
653- | Data | Source | Not stored by Array |
654- | ------| --------| ---------------------|
655- | Changes, stack, DAG | jj | ✓ |
656- | Trunk branch | jj's ` trunk() ` revset | ✓ |
657- | PR ↔ change mapping | Derived from branch name | ✓ |
658- | Enabled changesets | jj DAG (merge parents) | ✓ |
659-
660- ** Why:** Less state = less bugs. jj's data model is battle-tested. Our JSON files are not.
661-
662- ### User Config (` ~/.config/array/ ` )
663- - ` auth.json ` — GitHub token (only required state)
664-
665- ### Repo Config
666- - None. Array is stateless at repo level.
667- - Trunk comes from jj's ` trunk() ` (auto-detected or user-configured in jj)
668- - Branch naming is hardcoded: ` MM-DD-slug `
669- - Merge strategy defaults to squash (flag override if needed)
670-
671- ### Deriving State
672-
673- ** PR mapping:**
674- ``` typescript
675- // Branch name is deterministic from description
676- const branch = generateBranchName (change .description , change .date );
677- // Query GitHub for PR with that branch
678- const pr = await github .findPRByBranch (branch );
679- ```
680-
681- ** Enabled changesets:**
682- ```
683- @ (your working copy)
684- ├── your-stack-tip
685- ├── agent-change ← enabled = it's a merge parent of @
686- ```
687- - Enable = add as merge parent
688- - Disable = remove as merge parent
689- - Query = check @'s parents
0 commit comments