@tablation/crew 0.14.1 → 0.16.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": "@tablation/crew",
3
- "version": "0.14.1",
3
+ "version": "0.16.0",
4
4
  "description": "A standing team of headless agents that picks work off a Tablation board, does it on a machine you control, and reports back.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -200,7 +200,8 @@ since your last comment: an answer to a question, new direction, or a
200
200
  rebasing) — another ship may have pushed to the branch since you left it.
201
201
  If it reports your branch as diverged (local commits not on the remote AND
202
202
  the remote has moved), stop: comment on the ticket with what it printed and
203
- set `needs_info`; do not merge or rebase it yourself.
203
+ park it for a person (`needs_info` plus the operator as assignee — see
204
+ "Stopping: say it in data, not prose"); do not merge or rebase it yourself.
204
205
  - A ticket QA has bounced back to you comes in as `in_progress`,
205
206
  reassigned to your row (or unassigned, when your ship holds it), with a comment saying what still fails. Treat
206
207
  that exactly like new direction from a hold: read the comment, fix what
@@ -228,13 +229,16 @@ before; whether *this* run should too is Step 1's call, not a filesystem
228
229
  check.
229
230
 
230
231
  - For a ticket Step 1 cleared for resumption: if its worktree already
231
- exists, `cd` into it and resume; otherwise this shouldn't normally
232
- happen for an in_progress/fixed ticket (report it as unusual rather than
233
- guessing).
234
- - If an unassigned `in_progress` ticket has *no* worktree left (removed,
235
- or a genuinely new pickup), that's unusual for anything but a
236
- freshly-`accepted` ticket — report it rather than reconstructing state
237
- from nothing.
232
+ exists, `cd` into it and resume. If it does not, apply the next bullet.
233
+ - **"Mine, but nothing exists" is a start, not a stop.** An `in_progress`
234
+ ticket assigned to you (or unassigned) with no worktree here, no
235
+ `origin/<branch>`, and no progress comment from any seat has no state to
236
+ reconstruct: cut the worktree per Step 3.1 and begin, with one comment saying
237
+ you did. If `origin/<branch>` exists, cut the worktree from it instead of
238
+ from the base. Only evidence of work somewhere else — a progress comment
239
+ from another ship, or a branch on the remote this ship did not push — is a
240
+ reason to pause, and then it is a stop for a person (see "Stopping: say it in
241
+ data, not prose"), never a bare comment.
238
242
  - Otherwise, pick a ticket to work from the digest's "Step 2" table, which
239
243
  is already `status=accepted`, already narrowed to your lane, and already
240
244
  in the order below. Absent a digest, fetch those tickets yourself and
@@ -354,9 +358,12 @@ if `report_type` is either of those.
354
358
  branch (local commits the remote lacks, or one that cannot fast-forward)
355
359
  makes `crew sync` print `DO NOT CUT A WORKTREE FROM THIS BASE` and exit
356
360
  non-zero. That is a hard stop: do not run `git worktree add`, do not try to
357
- reconcile it yourself. Post a comment on the ticket naming the repo and the
358
- counts `crew sync` printed, leave the ticket as you found it, and end the
359
- run — the operator reconciles the checkout. Otherwise, from
361
+ reconcile it yourself. `crew sync` has already flagged the ship in data
362
+ (`base_unsafe`, shown by `crew status`). Post a comment on the ticket naming
363
+ the repo and the counts it printed, in the "resumes automatically" form
364
+ ("Resumes automatically when the primary checkout's base is level with the
365
+ remote. No status change needed."), leave the ticket as you found it, and end
366
+ the run — the operator reconciles the checkout and the next run resumes. Otherwise, from
360
367
  the primary checkout, `git worktree add <dir> -b <branch> <remote>/<base>`
361
368
  a sibling worktree for this ticket, on a new branch cut from the base
362
369
  branch's REMOTE-TRACKING ref (`origin/main`, say), never from the primary
@@ -549,6 +556,12 @@ if `report_type` is either of those.
549
556
  `in_progress` and the next `fixed` push again — a plain fast-forward, never
550
557
  `--force`; if the push is rejected, someone else moved the branch, so stop
551
558
  and say so on the ticket instead of forcing it.
559
+ The runner checks this when your session ends: if the ticket is at `fixed`
560
+ and `<remote>/<branch>` is missing or not at your worktree's HEAD, it sets
561
+ the ticket back to `in_progress` (still yours) with an event saying what it
562
+ found, and QA never sees it. When it matches, the runner records
563
+ `pushed <sha> to <remote>/<branch>` on the ticket itself; you still state the
564
+ sha in your last progress comment.
552
565
  Leave the worktree and branch exactly where they are, unmerged: QA boots
553
566
  *your worktree* on its derived ports to test the fix, so removing it
554
567
  would leave QA nothing to test. Your last progress comment is what QA
@@ -727,6 +740,44 @@ to true, and stop that ticket's work for this run. That is a report for the
727
740
  operator, not an accusation to litigate; let them decide what's actually
728
741
  going on.
729
742
 
743
+ ## Stopping: say it in data, not prose
744
+
745
+ A stop that lives only in a comment is invisible to every view that filters on
746
+ data: the operator reads the board's status, assignee and flags, and the ship's
747
+ attention flags, not every ticket's comments. There are two kinds of stop, and
748
+ each is written where the operator looks:
749
+
750
+ 1. **The ticket needs a person** (a question, a decision, an ambiguous spec, a
751
+ branch only a human can reconcile): set `status` to `needs_info` **and**
752
+ `assignee_id` to the operator's Crew row, and `needs_planning` to true when
753
+ it is a decision rather than a fact. These fields are mandatory whenever a
754
+ comment of yours addresses "Operator:" or a named person — a comment alone
755
+ is not a stop.
756
+ 2. **This ship cannot proceed** (the base branch diverged from the remote, a
757
+ tool or hook is missing, no disk, authentication failed) but the ticket
758
+ itself is fine: leave the ticket exactly as it is, `in_progress` and
759
+ assigned to you, so no other ship takes it, and do not set `needs_info`.
760
+ The **ship** carries the flag instead: `crew sync` raises it itself for a
761
+ diverged base (`crew status`, the Ships row and any `hooks.notify` show it
762
+ until the base is level again, and it clears on its own). Post one short
763
+ comment saying which ship is held and why, e.g. "held on <ship>, which
764
+ needs attention: main diverged from origin".
765
+
766
+ **Every stop comment names what un-parks it, and whether anyone has to act.**
767
+ Use one of two templates:
768
+
769
+ - *Resumes on its own:* "Resumes automatically when <condition>. No status
770
+ change needed." Use this for anything a later run can re-check by itself
771
+ (the base is level, a tool is installed, a setup hook passes). The next run
772
+ re-checks the condition first and, once it holds, carries on with the ticket
773
+ with no board edit from anyone.
774
+ - *Needs a person:* "Needs <person> to <action>; set status back to
775
+ `accepted` / clear `needs_info` when done."
776
+
777
+ If an operator sets a ticket you hold back to `accepted` after fixing an
778
+ environment problem, that is a resume, not a new claim: pick it up in its
779
+ existing worktree and note in a comment that the status change was not needed.
780
+
730
781
  ## Guardrails
731
782
 
732
783
  - One ticket at a time. Never mix two tickets' changes in one branch,
@@ -62,6 +62,13 @@ human review, so "probably fine" is not a pass.
62
62
  `git worktree add <the digest's worktree> <name>` from the ticket's repo
63
63
  checkout (git creates the local tracking branch) — and carry on. Only
64
64
  **MISSING** (gone locally and on the remote) means there is nothing to test.
65
+ **Name the sha you test.** Your starting comment states the
66
+ `<remote>/<branch>` tip you fetched. The runner records the pushed tip as an
67
+ event comment on the ticket, `pushed <sha> to <remote>/<branch>`; if the tip
68
+ you fetched differs from the latest such event, say so in that same comment
69
+ and verify the remote tip anyway — the remote is the only git truth, and the
70
+ difference is information, not a reason to refuse. If the branch is not on
71
+ the remote at all, bounce the ticket to `in_progress` with that reason.
65
72
  5. **Run it.** The builder left its worktree in place for you: `cd` into it,
66
73
  `nvm use` if the repository pins a version, and `eval` the **`ports`** hook
67
74
  for this worktree's own ports (anything already listening on them is a dead
@@ -181,7 +181,8 @@ since your last comment: an answer to a question, new direction, or a
181
181
  rebasing) — another ship may have pushed to the branch since you left it.
182
182
  If it reports your branch as diverged (local commits not on the remote AND
183
183
  the remote has moved), stop: comment on the ticket with what it printed and
184
- set `needs_info`; do not merge or rebase it yourself.
184
+ park it for a person (`needs_info` plus the operator as assignee — see
185
+ "Stopping: say it in data, not prose"); do not merge or rebase it yourself.
185
186
  - A ticket QA has bounced back to you comes in as `in_progress`,
186
187
  reassigned to your row (or unassigned, when your ship holds it), with a comment saying what still fails. Treat
187
188
  that exactly like new direction from a hold: read the comment, fix what
@@ -209,13 +210,16 @@ before; whether *this* run should too is Step 1's call, not a filesystem
209
210
  check.
210
211
 
211
212
  - For a ticket Step 1 cleared for resumption: if its worktree already
212
- exists, `cd` into it and resume; otherwise this shouldn't normally
213
- happen for an in_progress/fixed ticket (report it as unusual rather than
214
- guessing).
215
- - If an unassigned `in_progress` ticket has *no* worktree left (removed,
216
- or a genuinely new pickup), that's unusual for anything but a
217
- freshly-`accepted` ticket — report it rather than reconstructing state
218
- from nothing.
213
+ exists, `cd` into it and resume. If it does not, apply the next bullet.
214
+ - **"Mine, but nothing exists" is a start, not a stop.** An `in_progress`
215
+ ticket assigned to you (or unassigned) with no worktree here, no
216
+ `origin/<branch>`, and no progress comment from any seat has no state to
217
+ reconstruct: cut the worktree per Step 3.1 and begin, with one comment saying
218
+ you did. If `origin/<branch>` exists, cut the worktree from it instead of
219
+ from the base. Only evidence of work somewhere else — a progress comment
220
+ from another ship, or a branch on the remote this ship did not push — is a
221
+ reason to pause, and then it is a stop for a person (see "Stopping: say it in
222
+ data, not prose"), never a bare comment.
219
223
  - Otherwise, pick a ticket to work from the digest's "Step 2" table, which
220
224
  is already `status=accepted`, already narrowed to your lane, and already
221
225
  in the order below. Absent a digest, fetch those tickets yourself and
@@ -335,9 +339,12 @@ if `report_type` is either of those.
335
339
  branch (local commits the remote lacks, or one that cannot fast-forward)
336
340
  makes `crew sync` print `DO NOT CUT A WORKTREE FROM THIS BASE` and exit
337
341
  non-zero. That is a hard stop: do not run `git worktree add`, do not try to
338
- reconcile it yourself. Post a comment on the ticket naming the repo and the
339
- counts `crew sync` printed, leave the ticket as you found it, and end the
340
- run — the operator reconciles the checkout. Otherwise, from
342
+ reconcile it yourself. `crew sync` has already flagged the ship in data
343
+ (`base_unsafe`, shown by `crew status`). Post a comment on the ticket naming
344
+ the repo and the counts it printed, in the "resumes automatically" form
345
+ ("Resumes automatically when the primary checkout's base is level with the
346
+ remote. No status change needed."), leave the ticket as you found it, and end
347
+ the run — the operator reconciles the checkout and the next run resumes. Otherwise, from
341
348
  the primary checkout, `git worktree add <dir> -b <branch> <remote>/<base>`
342
349
  a sibling worktree for this ticket, on a new branch cut from the base
343
350
  branch's REMOTE-TRACKING ref (`origin/main`, say), never from the primary
@@ -531,6 +538,12 @@ if `report_type` is either of those.
531
538
  `in_progress` and the next `fixed` push again — a plain fast-forward, never
532
539
  `--force`; if the push is rejected, someone else moved the branch, so stop
533
540
  and say so on the ticket instead of forcing it.
541
+ The runner checks this when your session ends: if the ticket is at `fixed`
542
+ and `<remote>/<branch>` is missing or not at your worktree's HEAD, it sets
543
+ the ticket back to `in_progress` (still yours) with an event saying what it
544
+ found, and QA never sees it. When it matches, the runner records
545
+ `pushed <sha> to <remote>/<branch>` on the ticket itself; you still state the
546
+ sha in your last progress comment.
534
547
  Leave the worktree and branch exactly where they are, unmerged: QA boots
535
548
  *your worktree* on its derived ports to test the fix, so removing it
536
549
  would leave QA nothing to test. Your last progress comment is what QA
@@ -709,6 +722,44 @@ to true, and stop that ticket's work for this run. That is a report for the
709
722
  operator, not an accusation to litigate; let them decide what's actually
710
723
  going on.
711
724
 
725
+ ## Stopping: say it in data, not prose
726
+
727
+ A stop that lives only in a comment is invisible to every view that filters on
728
+ data: the operator reads the board's status, assignee and flags, and the ship's
729
+ attention flags, not every ticket's comments. There are two kinds of stop, and
730
+ each is written where the operator looks:
731
+
732
+ 1. **The ticket needs a person** (a question, a decision, an ambiguous spec, a
733
+ branch only a human can reconcile): set `status` to `needs_info` **and**
734
+ `assignee_id` to the operator's Crew row, and `needs_planning` to true when
735
+ it is a decision rather than a fact. These fields are mandatory whenever a
736
+ comment of yours addresses "Operator:" or a named person — a comment alone
737
+ is not a stop.
738
+ 2. **This ship cannot proceed** (the base branch diverged from the remote, a
739
+ tool or hook is missing, no disk, authentication failed) but the ticket
740
+ itself is fine: leave the ticket exactly as it is, `in_progress` and
741
+ assigned to you, so no other ship takes it, and do not set `needs_info`.
742
+ The **ship** carries the flag instead: `crew sync` raises it itself for a
743
+ diverged base (`crew status`, the Ships row and any `hooks.notify` show it
744
+ until the base is level again, and it clears on its own). Post one short
745
+ comment saying which ship is held and why, e.g. "held on <ship>, which
746
+ needs attention: main diverged from origin".
747
+
748
+ **Every stop comment names what un-parks it, and whether anyone has to act.**
749
+ Use one of two templates:
750
+
751
+ - *Resumes on its own:* "Resumes automatically when <condition>. No status
752
+ change needed." Use this for anything a later run can re-check by itself
753
+ (the base is level, a tool is installed, a setup hook passes). The next run
754
+ re-checks the condition first and, once it holds, carries on with the ticket
755
+ with no board edit from anyone.
756
+ - *Needs a person:* "Needs <person> to <action>; set status back to
757
+ `accepted` / clear `needs_info` when done."
758
+
759
+ If an operator sets a ticket you hold back to `accepted` after fixing an
760
+ environment problem, that is a resume, not a new claim: pick it up in its
761
+ existing worktree and note in a comment that the status change was not needed.
762
+
712
763
  ## Guardrails
713
764
 
714
765
  - One ticket at a time. Never mix two tickets' changes in one branch,
@@ -54,6 +54,13 @@ human review, so "probably fine" is not a pass.
54
54
  Does the change actually do what the comment claims? Does it handle the
55
55
  empty/error/permission path, or only the happy one? Does it touch
56
56
  anything the ticket never mentioned?
57
+ **Name the sha you test.** Your starting comment states the
58
+ `<remote>/<branch>` tip you fetched. The runner records the pushed tip as an
59
+ event comment on the ticket, `pushed <sha> to <remote>/<branch>`; if the tip
60
+ you fetched differs from the latest such event, say so in that same comment
61
+ and verify the remote tip anyway — the remote is the only git truth, and the
62
+ difference is information, not a reason to refuse. If the branch is not on
63
+ the remote at all, bounce the ticket to `in_progress` with that reason.
57
64
  5. **Run it.** The builder left its worktree in place for you: `cd` into it,
58
65
  `nvm use` if the repository pins a version, and `eval` the **`ports`** hook
59
66
  for this worktree's own ports (anything already listening on them is a dead