lobstah 0.1.1 → 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.
@@ -0,0 +1,139 @@
1
+ # Vocabulary
2
+
3
+ Every closed word-set in lobstah, in one place: what the words are, who says
4
+ them, and where the set is enforced. Each set is deliberately small and the
5
+ write paths reject anything outside it — a new word is a design change, not a
6
+ patch.
7
+
8
+ ## Status verbs
9
+
10
+ What a dispatch *declares* about itself. Workers write them with
11
+ `lobstah report <id> <verb> [note]`; the write path (`appendStatus`) rejects
12
+ anything else. The status log is append-only; the last entry wins.
13
+
14
+ | Verb | Meaning | Who acts next |
15
+ | --- | --- | --- |
16
+ | `working` | Making progress; nothing needed. | Nobody. |
17
+ | `needs-decision` | Blocked on a judgment call only a human (or the orchestrator) can make. The note carries the question. | Human — re-fires every `remindSecs` until answered. |
18
+ | `blocked` | Cannot proceed for an external reason (missing access, broken dependency). | Human. |
19
+ | `paused` | Intentionally idle; resume is expected. | Whoever paused it. |
20
+ | `done` | The brief is fulfilled. Terminal. Merging is never the dispatch's job. | Merge loop / reviewer. |
21
+ | `failed` | Cannot fulfill the brief; work preserved in the worktree. Terminal. | Human. |
22
+
23
+ `done` and `failed` are the **terminal verbs** (`TERMINAL_VERBS`): once
24
+ logged, process state stops mattering and the daemon finalizes.
25
+
26
+ Source of truth: `VERBS` in `packages/core/src/types.ts`.
27
+
28
+ ## Reconciled state
29
+
30
+ What an observer should *believe*, combining the status log with event
31
+ recency. Computed by `reconcile()`; shown by `lobstah status` and `buoys`.
32
+
33
+ The value set is the six verbs plus `unknown`. Precedence, highest first:
34
+
35
+ 1. A terminal verb in the log — final, regardless of anything else.
36
+ 2. Fresh event activity (default window 120s) — `working`, unless the log
37
+ says something more specific (`needs-decision` with recent activity stays
38
+ `needs-decision`).
39
+ 3. The last logged verb.
40
+ 4. Nothing trustworthy → `unknown`. **Absence of signal never means fine** —
41
+ `unknown` is a prompt to look, not a synonym for idle.
42
+
43
+ ## Liveness classification
44
+
45
+ What the *process* is doing, independent of what it claims. Computed by
46
+ `classify()` each daemon tick; drives the restart ladder. Internal to the
47
+ daemon — it never reaches a tracker.
48
+
49
+ | Classification | Evidence | Daemon response |
50
+ | --- | --- | --- |
51
+ | `unclaimed` | Descriptor present, no runner yet. | Spawn a runner. |
52
+ | `busy` | Runner alive, activity within the wedge threshold. | Nothing. |
53
+ | `terminal` | Terminal verb logged. | Finalize once the process is gone. |
54
+ | `dead` | Pid verified gone (pid + process-start-time, so pid reuse can't lie). | Respawn with session resume, bounded by `maxRestartAttempts`; then `failed`. |
55
+ | `wedged` | Alive but no activity past `wedgeThresholdSecs`. | SIGKILL the group, fork the session with a nudge, same bound. |
56
+ | `unknown` | Contradictory or missing evidence. | Touch nothing; log it. |
57
+
58
+ Dead and wedged get opposite treatment on purpose: a dead process is safe to
59
+ respawn; a wedged one must be killed first or two writers share a worktree. A
60
+ pending cancel preempts all of this — a cancelled dispatch finalizes as
61
+ `failed` ("cancelled by request") and never re-enters the ladder.
62
+
63
+ Source of truth: `Classification` in `packages/supervisor/src/liveness.ts`.
64
+
65
+ ## Tend verdicts
66
+
67
+ What the *fleet* needs, computed by `lobstah man tend` from the heartbeat,
68
+ queues, and attention cursors. One verdict, precedence top-down:
69
+
70
+ | Verdict | Meaning |
71
+ | --- | --- |
72
+ | `daemon-down` | No fresh heartbeat — nothing is being supervised. |
73
+ | `stalled` | Work queued, capacity free, daemon alive, nothing claiming. Actually broken. |
74
+ | `needs-attention` | An unanswered `needs-decision`/`blocked` is standing. |
75
+ | `working` | Dispatches active or queued; nothing waiting on a human. |
76
+ | `idle` | Everything drained. The quiet is real — distinguished from `stalled` by evidence, not absence. |
77
+
78
+ ## Merge gates
79
+
80
+ What the merge loop concluded about each open PR on its last tick, persisted
81
+ in the [merge view](pickup.md#merge-view).
82
+
83
+ | Gate | Meaning |
84
+ | --- | --- |
85
+ | `waiting-approval` | No qualifying approval on the current head. The resting state. |
86
+ | `behind-updated` | Behind base, no conflict; branch updated via the forge, gate re-enters next tick. |
87
+ | `conflict-chore:<uuid>` | Real conflict; a rebase chore owns the PR until it completes. |
88
+ | `rebase-failed` | The one bounded rebase attempt failed; `needs-human` label applied. Resting until a human acts. |
89
+ | `blocked` | The forge's rollup says a required check failed. |
90
+ | `draft` | Draft PR; never merged. |
91
+
92
+ A PR that leaves the open set gets a **disposition** instead: `merged` or
93
+ `closed`, recorded with one follow-up lookup so the answer is right even when
94
+ a human pressed the button.
95
+
96
+ ## Tracker mappings
97
+
98
+ How verbs translate to tracker vocabulary is per-source and total — a verb
99
+ with no mapping is a config error at startup, not a silent drop. The tables
100
+ live in [pickup.md](pickup.md#reporting).
101
+
102
+ ## Lanes and buckets
103
+
104
+ Work moves through two **lanes** — `work` (human-originated) and `chore`
105
+ (system-originated maintenance, own concurrency budget, reports to no
106
+ tracker) — and three **buckets** within a lane: `queued`, `active`, `done`.
107
+ Bucket transitions are atomic renames; the directory *is* the state.
108
+
109
+ ## Doctor statuses
110
+
111
+ `lobstah doctor` grades each check with one of three words. **Owner:**
112
+ `apps/cli/src/doctor.ts`. **Enforcement:** any `fail` row exits 1.
113
+
114
+ | Status | Meaning |
115
+ | ------ | ------- |
116
+ | `ok` | Works as configured. |
117
+ | `warn` | Degraded or optional — dispatches may still run (e.g. one harness missing, daemon not running). |
118
+ | `fail` | Broken configuration or missing requirement — fix before relying on lobstah. |
119
+
120
+ ## Watch contract
121
+
122
+ A **watch** is a standing outbound poll on something external (a ume review
123
+ session, a CI run) registered through `lobstah watch add` — the validated
124
+ write path; nothing else touches `watches/`. **Owner:**
125
+ `packages/core/src/watch.ts`. **Enforcement:** check output that doesn't
126
+ parse records `lastError` and advances nothing.
127
+
128
+ | Word | Meaning |
129
+ | ---- | ------- |
130
+ | `check` | Shell command exec'd with `{cursor}` substituted; prints `{ "cursor", "events"?, "done"? }` JSON. Read-only and idempotent — pick and an inline `man wait` coordinate only by the `lastCheckedAt` stamp. |
131
+ | `cursor` | Opaque progress marker, advanced only from successful check output. The stream of record: a crashed watcher resumes from it losslessly. |
132
+ | `owner` | Who the events belong to: `man` (surface via `man wait`/`man haul` + notify) or `dispatch:<uuid>` (fork a continuation of that chain). Events are never unowned work. |
133
+ | `done` | The source is finished (session closed, run complete); the watch retires after its last events are consumed. |
134
+ | `stream` | Optional long-lived NDJSON command held by pick for ms-latency delivery; a pure optimization — appends dedupe by `seq`, the check remains the guarantee. |
135
+
136
+ Delivery is level-triggered and at-least-once, like dispatch attention:
137
+ events stand until the owner consumes them. One continuation dispatch in
138
+ flight per watch; later events buffer and fork from the latest session in
139
+ the chain.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lobstah",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Harness-agnostic, token-efficient supervision framework for coding agents",
5
5
  "license": "MIT",
6
6
  "author": "aequitas labs LLC",
@@ -10,6 +10,7 @@
10
10
  },
11
11
  "files": [
12
12
  "dist",
13
+ "docs",
13
14
  "README.md",
14
15
  "LICENSE"
15
16
  ],