@lmctl-ai/lmctl 0.2.37 → 0.2.39

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.
Files changed (199) hide show
  1. package/README.md +16 -0
  2. package/THIRD_PARTY_NOTICES.md +35 -0
  3. package/bin/lmbee +2 -0
  4. package/bin/lmscript +3 -0
  5. package/build-info.json +1 -0
  6. package/dist/cli/index.js +569 -494
  7. package/dist/cli/schema.sql +0 -169
  8. package/dist/cli/script.js +273 -266
  9. package/dist/lmbee.js +960 -0
  10. package/dist/lmscript.js +388 -0
  11. package/dist/public/app.js +379 -0
  12. package/dist/public/index.html +78 -0
  13. package/dist/public/styles.css +160 -0
  14. package/dist/schema.sql +455 -0
  15. package/dist/vendor-webui/index.html +18 -0
  16. package/dist/vendor-webui/local.js +231 -0
  17. package/dist/vendor-webui/styles.css +1852 -0
  18. package/package.json +12 -7
  19. package/dist/cli/batch.d.ts +0 -2
  20. package/dist/cli/busy-evidence.d.ts +0 -27
  21. package/dist/cli/chat-cycle.d.ts +0 -59
  22. package/dist/cli/chat-exec.d.ts +0 -91
  23. package/dist/cli/chat-policy.d.ts +0 -22
  24. package/dist/cli/chat.d.ts +0 -14
  25. package/dist/cli/code-resolver.d.ts +0 -8
  26. package/dist/cli/common.d.ts +0 -57
  27. package/dist/cli/context.d.ts +0 -12
  28. package/dist/cli/cost.d.ts +0 -2
  29. package/dist/cli/export.d.ts +0 -2
  30. package/dist/cli/hello.d.ts +0 -10
  31. package/dist/cli/index.d.ts +0 -3
  32. package/dist/cli/infra.d.ts +0 -78
  33. package/dist/cli/init.d.ts +0 -21
  34. package/dist/cli/intent-input.d.ts +0 -16
  35. package/dist/cli/intent-match.d.ts +0 -30
  36. package/dist/cli/intent-sessions.d.ts +0 -24
  37. package/dist/cli/intent-team.d.ts +0 -25
  38. package/dist/cli/intent.d.ts +0 -22
  39. package/dist/cli/ls.d.ts +0 -2
  40. package/dist/cli/mailbox-cli.d.ts +0 -6
  41. package/dist/cli/managed.d.ts +0 -62
  42. package/dist/cli/mcp-install.d.ts +0 -23
  43. package/dist/cli/mcp.d.ts +0 -2
  44. package/dist/cli/model.d.ts +0 -21
  45. package/dist/cli/paths.d.ts +0 -50
  46. package/dist/cli/plan-wizard.d.ts +0 -42
  47. package/dist/cli/plan.d.ts +0 -20
  48. package/dist/cli/queue-delivery.d.ts +0 -122
  49. package/dist/cli/quickrun.d.ts +0 -14
  50. package/dist/cli/ratelimit.d.ts +0 -2
  51. package/dist/cli/remote-fetch.d.ts +0 -7
  52. package/dist/cli/run-queries.d.ts +0 -82
  53. package/dist/cli/running.d.ts +0 -5
  54. package/dist/cli/save-script.d.ts +0 -41
  55. package/dist/cli/script.d.ts +0 -6
  56. package/dist/cli/seed-flight.d.ts +0 -2
  57. package/dist/cli/self-identity.d.ts +0 -25
  58. package/dist/cli/session-idle.d.ts +0 -118
  59. package/dist/cli/status.d.ts +0 -22
  60. package/dist/cli/tail.d.ts +0 -18
  61. package/dist/cli/target-resolver.d.ts +0 -139
  62. package/dist/cli/team-status.d.ts +0 -91
  63. package/dist/cli/teamfile-compat.d.ts +0 -116
  64. package/dist/cli/teamfile-store.d.ts +0 -18
  65. package/dist/cli/teamfile-template.d.ts +0 -47
  66. package/dist/cli/template-env.d.ts +0 -25
  67. package/dist/cli/terminal-lock.d.ts +0 -25
  68. package/dist/cli/terminal.d.ts +0 -23
  69. package/dist/cli/time-filter.d.ts +0 -10
  70. package/dist/cli/update-notifier.d.ts +0 -11
  71. package/dist/cli/version-util.d.ts +0 -23
  72. package/dist/config/seed_templates.d.ts +0 -1
  73. package/dist/db/backfill-event-log.d.ts +0 -26
  74. package/dist/db/delegation.d.ts +0 -37
  75. package/dist/db/escalation_vocab.d.ts +0 -45
  76. package/dist/db/event-log.d.ts +0 -40
  77. package/dist/db/index.d.ts +0 -1213
  78. package/dist/db/inflight-acquire.d.ts +0 -70
  79. package/dist/db/invocation-event-projections.d.ts +0 -65
  80. package/dist/db/ledger-identity.test.d.ts +0 -1
  81. package/dist/db/live-event-projections.d.ts +0 -92
  82. package/dist/db/migrate.d.ts +0 -51
  83. package/dist/db/open-readonly.d.ts +0 -2
  84. package/dist/db/process-liveness.d.ts +0 -37
  85. package/dist/db/sqlite.d.ts +0 -53
  86. package/dist/db/sqlite.test.d.ts +0 -1
  87. package/dist/db/terminal-lock.d.ts +0 -14
  88. package/dist/db/tracked-invocation-reconcile.d.ts +0 -52
  89. package/dist/db/tracked-invocation.d.ts +0 -116
  90. package/dist/mcp/dispatch.d.ts +0 -45
  91. package/dist/mcp/mediation.d.ts +0 -128
  92. package/dist/mcp/path-warning.d.ts +0 -7
  93. package/dist/mcp/server.d.ts +0 -63
  94. package/dist/mcp/tools.d.ts +0 -24
  95. package/dist/providers/adapter.d.ts +0 -271
  96. package/dist/providers/adapters/agy-adapter.d.ts +0 -18
  97. package/dist/providers/adapters/claude-adapter.d.ts +0 -20
  98. package/dist/providers/adapters/codex-adapter.d.ts +0 -22
  99. package/dist/providers/adapters/copilot-adapter.d.ts +0 -16
  100. package/dist/providers/adapters/dsh-adapter.d.ts +0 -89
  101. package/dist/providers/adapters/gemini-adapter.d.ts +0 -44
  102. package/dist/providers/adapters/hermes-adapter.d.ts +0 -71
  103. package/dist/providers/adapters/index.d.ts +0 -35
  104. package/dist/providers/adapters/kimi-adapter.d.ts +0 -16
  105. package/dist/providers/adapters/lmplayer-adapter.d.ts +0 -14
  106. package/dist/providers/adapters/opencode-adapter.d.ts +0 -11
  107. package/dist/providers/adapters/pi-adapter.d.ts +0 -17
  108. package/dist/providers/adapters/print-turn.d.ts +0 -29
  109. package/dist/providers/adapters/qwen-adapter.d.ts +0 -11
  110. package/dist/providers/agy.d.ts +0 -32
  111. package/dist/providers/base-adapter.d.ts +0 -110
  112. package/dist/providers/base.d.ts +0 -12
  113. package/dist/providers/binary-check.d.ts +0 -102
  114. package/dist/providers/bundle.d.ts +0 -124
  115. package/dist/providers/claude-mock.d.ts +0 -90
  116. package/dist/providers/claude.d.ts +0 -21
  117. package/dist/providers/codex-config.d.ts +0 -15
  118. package/dist/providers/codex.d.ts +0 -25
  119. package/dist/providers/config/init-config.d.ts +0 -43
  120. package/dist/providers/config/model-selection-lint.d.ts +0 -70
  121. package/dist/providers/config/team-config.d.ts +0 -184
  122. package/dist/providers/config/types.d.ts +0 -146
  123. package/dist/providers/config/user-config.d.ts +0 -88
  124. package/dist/providers/copilot.d.ts +0 -21
  125. package/dist/providers/debug.d.ts +0 -128
  126. package/dist/providers/dsh-sidecar.d.ts +0 -65
  127. package/dist/providers/dsh-zstd.d.ts +0 -27
  128. package/dist/providers/dsh.d.ts +0 -37
  129. package/dist/providers/frontmatter.d.ts +0 -46
  130. package/dist/providers/gemini-session-reader.d.ts +0 -151
  131. package/dist/providers/gemini.d.ts +0 -39
  132. package/dist/providers/hermes.d.ts +0 -90
  133. package/dist/providers/index.d.ts +0 -423
  134. package/dist/providers/kimi.d.ts +0 -37
  135. package/dist/providers/model-catalog.d.ts +0 -145
  136. package/dist/providers/model-suggestions.d.ts +0 -4
  137. package/dist/providers/one-shot-timeout.d.ts +0 -1
  138. package/dist/providers/opencode-config.d.ts +0 -62
  139. package/dist/providers/opencode.d.ts +0 -40
  140. package/dist/providers/parsers/acp.d.ts +0 -71
  141. package/dist/providers/parsers/codex-app-server.d.ts +0 -60
  142. package/dist/providers/parsers/stream-json.d.ts +0 -57
  143. package/dist/providers/passive-readers/agy.d.ts +0 -155
  144. package/dist/providers/passive-readers/copilot.d.ts +0 -173
  145. package/dist/providers/passive-readers/dsh.d.ts +0 -34
  146. package/dist/providers/passive-readers/kimi.d.ts +0 -44
  147. package/dist/providers/passive-readers/opencode.d.ts +0 -89
  148. package/dist/providers/passive-readers/qwen.d.ts +0 -151
  149. package/dist/providers/passive-readers/shared.d.ts +0 -138
  150. package/dist/providers/passive-session-reader.d.ts +0 -188
  151. package/dist/providers/path-utils.d.ts +0 -1
  152. package/dist/providers/pi.d.ts +0 -32
  153. package/dist/providers/pricing.d.ts +0 -107
  154. package/dist/providers/qwen.d.ts +0 -22
  155. package/dist/providers/ratelimit/agy.d.ts +0 -22
  156. package/dist/providers/ratelimit/claude-auth.d.ts +0 -13
  157. package/dist/providers/ratelimit/claude.d.ts +0 -6
  158. package/dist/providers/ratelimit/codex.d.ts +0 -7
  159. package/dist/providers/ratelimit/kimi-auth.d.ts +0 -15
  160. package/dist/providers/ratelimit/kimi.d.ts +0 -6
  161. package/dist/providers/ratelimit/schema.d.ts +0 -28
  162. package/dist/providers/ratelimit-readings.d.ts +0 -19
  163. package/dist/providers/registry.d.ts +0 -31
  164. package/dist/providers/resume.d.ts +0 -43
  165. package/dist/providers/seed-instruction.d.ts +0 -3
  166. package/dist/providers/self-session-env.d.ts +0 -21
  167. package/dist/providers/session-limit.d.ts +0 -9
  168. package/dist/providers/strip-ansi.d.ts +0 -5
  169. package/dist/providers/transport-errors.d.ts +0 -94
  170. package/dist/providers/transport-lifecycle.d.ts +0 -63
  171. package/dist/providers/transport-wrappers.d.ts +0 -110
  172. package/dist/providers/transports/acp-profiles/config-option-step.d.ts +0 -24
  173. package/dist/providers/transports/acp-profiles/copilot.d.ts +0 -12
  174. package/dist/providers/transports/acp-profiles/gemini.d.ts +0 -22
  175. package/dist/providers/transports/acp-profiles/hermes.d.ts +0 -27
  176. package/dist/providers/transports/acp-profiles/index.d.ts +0 -19
  177. package/dist/providers/transports/acp-profiles/kimi.d.ts +0 -24
  178. package/dist/providers/transports/acp-profiles/opencode.d.ts +0 -26
  179. package/dist/providers/transports/acp-profiles/types.d.ts +0 -258
  180. package/dist/providers/transports/acp-rpc.d.ts +0 -18
  181. package/dist/providers/transports/acp.d.ts +0 -217
  182. package/dist/providers/transports/codex-app-server.d.ts +0 -190
  183. package/dist/providers/transports/hold-open.d.ts +0 -120
  184. package/dist/providers/transports/manager.d.ts +0 -21
  185. package/dist/providers/transports/stream-json.d.ts +0 -162
  186. package/dist/providers/transports/types.d.ts +0 -56
  187. package/dist/providers/types.d.ts +0 -154
  188. package/dist/providers/yolo-contract.d.ts +0 -131
  189. package/dist/script/adapter.d.ts +0 -104
  190. package/dist/script/batch-script.d.ts +0 -7
  191. package/dist/script/index.d.ts +0 -3
  192. package/dist/script/lmbee-module.d.ts +0 -2
  193. package/dist/script/lmscript.d.ts +0 -616
  194. package/dist/shared/policy.d.ts +0 -74
  195. package/dist/shared-lib/db.d.ts +0 -25
  196. package/dist/shared-lib/passive-session-reader.d.ts +0 -2
  197. package/dist/shared-lib/provider-parse.d.ts +0 -6
  198. package/dist/templates/basedir.d.ts +0 -52
  199. package/dist/uri/lmctl_uri.d.ts +0 -38
@@ -0,0 +1,455 @@
1
+
2
+ CREATE TABLE IF NOT EXISTS team_state(
3
+ team TEXT PRIMARY KEY,
4
+ status TEXT NOT NULL,
5
+ changed_ts TEXT NOT NULL,
6
+ last_ts TEXT NOT NULL
7
+ );
8
+
9
+ CREATE TABLE IF NOT EXISTS kv(
10
+ k TEXT PRIMARY KEY,
11
+ v TEXT NOT NULL
12
+ );
13
+
14
+ CREATE TABLE IF NOT EXISTS session_reservation(
15
+ team TEXT NOT NULL,
16
+ alias TEXT NOT NULL,
17
+ holder_pid INTEGER NOT NULL,
18
+ reserved_at TEXT NOT NULL,
19
+ lease_until TEXT NOT NULL,
20
+ reason TEXT,
21
+ PRIMARY KEY (team, alias)
22
+ );
23
+
24
+ CREATE TABLE IF NOT EXISTS events(
25
+ id INTEGER PRIMARY KEY,
26
+ ts TEXT NOT NULL,
27
+ scan INTEGER,
28
+ team TEXT NOT NULL,
29
+ status TEXT NOT NULL,
30
+ note TEXT
31
+ );
32
+ CREATE INDEX IF NOT EXISTS idx_events_team_ts ON events(team, ts);
33
+
34
+ CREATE TABLE IF NOT EXISTS queue(
35
+ id INTEGER PRIMARY KEY,
36
+ from_id TEXT NOT NULL,
37
+ to_id TEXT NOT NULL,
38
+ prompt_file TEXT NOT NULL,
39
+ status TEXT NOT NULL DEFAULT 'pending',
40
+ created_ts TEXT NOT NULL,
41
+ sent_ts TEXT,
42
+ retrieved_ts TEXT,
43
+ subject_id TEXT,
44
+ dedupe_key TEXT UNIQUE,
45
+ delivered_via_escalation INTEGER NOT NULL DEFAULT 0,
46
+ escalation_claimed_ts TEXT,
47
+ escalation_claim_token TEXT,
48
+ escalation_only INTEGER NOT NULL DEFAULT 0,
49
+ admission_fingerprint TEXT,
50
+ expects_response INTEGER NOT NULL DEFAULT 0,
51
+ to_alias TEXT,
52
+ retracted_ts TEXT,
53
+ retracted_reason TEXT,
54
+ retraction_notice INTEGER NOT NULL DEFAULT 0,
55
+ in_reply_to INTEGER,
56
+ operator_priority INTEGER NOT NULL DEFAULT 0,
57
+ merged_into_id INTEGER
58
+ );
59
+ CREATE INDEX IF NOT EXISTS idx_queue_to_status ON queue(to_id, status);
60
+
61
+ CREATE TABLE IF NOT EXISTS answers(
62
+ id INTEGER PRIMARY KEY,
63
+ prompt_queue_id INTEGER NOT NULL REFERENCES queue(id),
64
+ answer_text TEXT NOT NULL,
65
+ answered_at TEXT NOT NULL,
66
+ created_at TEXT NOT NULL,
67
+ superseded_at TEXT
68
+ );
69
+ CREATE INDEX IF NOT EXISTS idx_answers_answered_at ON answers(answered_at);
70
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_answers_current ON answers(prompt_queue_id) WHERE superseded_at IS NULL;
71
+
72
+ CREATE TABLE IF NOT EXISTS sources(
73
+ id INTEGER PRIMARY KEY,
74
+ path TEXT NOT NULL UNIQUE,
75
+ label TEXT,
76
+ added_ts TEXT NOT NULL
77
+ );
78
+
79
+ CREATE TABLE IF NOT EXISTS team_progress(
80
+ team TEXT PRIMARY KEY,
81
+ progress_status TEXT,
82
+ progress_changed_ts TEXT,
83
+ last_scan_ts TEXT,
84
+ confirmed_done_ts TEXT,
85
+ surfaced_ts TEXT,
86
+ last_miniplayer_reply_hash TEXT,
87
+ blocked_surfaced_ts TEXT,
88
+ last_escalation_attempt_ts TEXT,
89
+ escalation_attempt_count INTEGER NOT NULL DEFAULT 0,
90
+ fault_surfaced_ts TEXT,
91
+ epic_closed_surfaced_ts TEXT,
92
+ quota_exhausted_last_seen_ts TEXT,
93
+ quota_exhausted_message TEXT,
94
+ miniplayer_verdict_label TEXT,
95
+ miniplayer_verdict_reason TEXT,
96
+ miniplayer_verdict_ts TEXT,
97
+ miniplayer_verdict_input_hash TEXT,
98
+ miniplayer_verdict_structural_hash TEXT,
99
+ holder_watch_pid INTEGER,
100
+ holder_watch_started_at TEXT,
101
+ holder_watch_cpu_ticks INTEGER,
102
+ holder_watch_observed_at TEXT,
103
+ holder_watch_low_cpu_streak INTEGER,
104
+ hung_holder_flagged_ts TEXT,
105
+ hung_holder_reason TEXT,
106
+ last_cli_activity_ts TEXT
107
+ );
108
+
109
+ CREATE TABLE IF NOT EXISTS orphan_watch(
110
+ target TEXT NOT NULL,
111
+ started_at_ms INTEGER NOT NULL,
112
+ pid INTEGER NOT NULL,
113
+ cpu_ticks INTEGER,
114
+ low_cpu_streak INTEGER NOT NULL DEFAULT 0,
115
+ observed_at TEXT NOT NULL,
116
+ PRIMARY KEY (target, started_at_ms, pid)
117
+ );
118
+
119
+ CREATE TABLE IF NOT EXISTS hang_probe_observation(
120
+ target TEXT NOT NULL,
121
+ started_at_ms INTEGER NOT NULL,
122
+ pid INTEGER NOT NULL,
123
+ observed_at TEXT NOT NULL,
124
+ cpu_ticks INTEGER,
125
+ io_bytes INTEGER,
126
+ PRIMARY KEY (target, started_at_ms, pid, observed_at)
127
+ );
128
+ CREATE INDEX IF NOT EXISTS idx_hang_probe_observation_target ON hang_probe_observation(target, started_at_ms, pid);
129
+
130
+ CREATE TABLE IF NOT EXISTS hang_probe_outcome(
131
+ target TEXT NOT NULL,
132
+ started_at_ms INTEGER NOT NULL,
133
+ pid INTEGER NOT NULL,
134
+ outcome TEXT NOT NULL,
135
+ recorded_at TEXT NOT NULL,
136
+ PRIMARY KEY (target, started_at_ms, pid)
137
+ );
138
+
139
+ CREATE TABLE IF NOT EXISTS mail_ledger(
140
+ id INTEGER PRIMARY KEY,
141
+ msg_id TEXT NOT NULL UNIQUE,
142
+ seq INTEGER NOT NULL,
143
+ state TEXT NOT NULL DEFAULT 'persisted',
144
+ to_site TEXT NOT NULL,
145
+ to_team TEXT NOT NULL,
146
+ to_alias TEXT NOT NULL,
147
+ from_site TEXT NOT NULL,
148
+ from_team TEXT NOT NULL,
149
+ from_alias TEXT NOT NULL,
150
+ sender_user_id TEXT NOT NULL,
151
+ sent_at TEXT NOT NULL,
152
+ payload TEXT NOT NULL,
153
+ received_ts TEXT NOT NULL,
154
+ dispatched_ts TEXT,
155
+ replied_ts TEXT,
156
+ failed_ts TEXT,
157
+ failure_reason TEXT,
158
+ retry_count INTEGER NOT NULL DEFAULT 0,
159
+ ack_sent_ts TEXT,
160
+ delivery_error TEXT,
161
+ delivery_error_ts TEXT
162
+ );
163
+ CREATE INDEX IF NOT EXISTS idx_mail_ledger_state ON mail_ledger(state);
164
+
165
+ CREATE TABLE IF NOT EXISTS mail_outbound_ledger(
166
+ id INTEGER PRIMARY KEY,
167
+ msg_id TEXT NOT NULL UNIQUE,
168
+ to_site TEXT NOT NULL,
169
+ to_team TEXT NOT NULL,
170
+ to_alias TEXT NOT NULL,
171
+ from_site TEXT NOT NULL,
172
+ from_team TEXT NOT NULL,
173
+ from_alias TEXT NOT NULL,
174
+ state TEXT NOT NULL DEFAULT 'sent',
175
+ sent_ts TEXT NOT NULL,
176
+ acked_ts TEXT,
177
+ replied_ts TEXT,
178
+ queue_id INTEGER
179
+ );
180
+ CREATE INDEX IF NOT EXISTS idx_mail_outbound_ledger_to ON mail_outbound_ledger(to_site, to_team, to_alias);
181
+
182
+ CREATE TABLE IF NOT EXISTS entities(
183
+ id INTEGER PRIMARY KEY AUTOINCREMENT CHECK(id > 0),
184
+ kind TEXT NOT NULL CHECK(kind IN ('epic','task','subtask')),
185
+ project TEXT NOT NULL CHECK(length(trim(project)) > 0),
186
+ parent_id INTEGER REFERENCES entities(id) ON DELETE RESTRICT,
187
+ title TEXT NOT NULL CHECK(length(trim(title)) > 0),
188
+ description TEXT NOT NULL DEFAULT '',
189
+ requirements TEXT NOT NULL DEFAULT '',
190
+ acceptance_criteria TEXT NOT NULL DEFAULT '',
191
+ status TEXT NOT NULL DEFAULT 'todo' CHECK(length(trim(status)) > 0),
192
+ owner_team_path TEXT,
193
+ owner_alias TEXT,
194
+ created_at TEXT NOT NULL,
195
+ updated_at TEXT NOT NULL,
196
+ revision INTEGER NOT NULL DEFAULT 1 CHECK(typeof(revision)='integer' AND revision > 0),
197
+ delivered_ts TEXT,
198
+ review_time TEXT,
199
+ needs_review INTEGER NOT NULL DEFAULT 0 CHECK(needs_review IN (0,1)),
200
+ review_reason TEXT,
201
+ review_input_hash TEXT,
202
+ hold_until TEXT,
203
+ hold_reason TEXT,
204
+ blocked_on TEXT,
205
+ CHECK ((owner_team_path IS NULL AND owner_alias IS NULL) OR
206
+ (owner_team_path IS NOT NULL AND owner_alias IS NOT NULL AND
207
+ length(trim(owner_team_path)) > 0 AND length(trim(owner_alias)) > 0)),
208
+ CHECK ((kind='epic' AND parent_id IS NULL) OR kind='task' OR (kind='subtask' AND parent_id IS NOT NULL))
209
+ );
210
+ CREATE INDEX IF NOT EXISTS idx_entities_parent ON entities(parent_id);
211
+ CREATE INDEX IF NOT EXISTS idx_entities_project_status ON entities(project, status);
212
+ CREATE INDEX IF NOT EXISTS idx_entities_owner ON entities(owner_team_path, owner_alias);
213
+
214
+ CREATE TRIGGER IF NOT EXISTS trg_entities_immutable
215
+ BEFORE UPDATE OF id, kind, project ON entities
216
+ WHEN NEW.id IS NOT OLD.id OR NEW.kind IS NOT OLD.kind OR NEW.project IS NOT OLD.project
217
+ BEGIN
218
+ SELECT RAISE(ABORT, 'IMMUTABLE_FIELD');
219
+ END;
220
+
221
+ CREATE TRIGGER IF NOT EXISTS trg_entities_parent_insert
222
+ BEFORE INSERT ON entities
223
+ WHEN NEW.parent_id IS NOT NULL
224
+ BEGIN
225
+ SELECT CASE WHEN NOT EXISTS(SELECT 1 FROM entities WHERE id = NEW.parent_id)
226
+ THEN RAISE(ABORT, 'MISSING_PARENT') END;
227
+ SELECT CASE WHEN NOT EXISTS(
228
+ SELECT 1 FROM entities WHERE id = NEW.parent_id AND
229
+ ((NEW.kind = 'task' AND kind = 'epic') OR (NEW.kind = 'subtask' AND kind = 'task')))
230
+ THEN RAISE(ABORT, 'INVALID_PARENT_KIND') END;
231
+ SELECT CASE WHEN (SELECT project FROM entities WHERE id = NEW.parent_id) <> NEW.project
232
+ THEN RAISE(ABORT, 'PROJECT_MISMATCH') END;
233
+ END;
234
+ CREATE TRIGGER IF NOT EXISTS trg_entities_parent_update
235
+ BEFORE UPDATE OF parent_id ON entities
236
+ WHEN NEW.parent_id IS NOT NULL
237
+ BEGIN
238
+ SELECT CASE WHEN NOT EXISTS(SELECT 1 FROM entities WHERE id = NEW.parent_id)
239
+ THEN RAISE(ABORT, 'MISSING_PARENT') END;
240
+ SELECT CASE WHEN NOT EXISTS(
241
+ SELECT 1 FROM entities WHERE id = NEW.parent_id AND
242
+ ((NEW.kind = 'task' AND kind = 'epic') OR (NEW.kind = 'subtask' AND kind = 'task')))
243
+ THEN RAISE(ABORT, 'INVALID_PARENT_KIND') END;
244
+ SELECT CASE WHEN (SELECT project FROM entities WHERE id = NEW.parent_id) <> NEW.project
245
+ THEN RAISE(ABORT, 'PROJECT_MISMATCH') END;
246
+ END;
247
+
248
+ CREATE TABLE IF NOT EXISTS dependencies(
249
+ entity_id INTEGER NOT NULL REFERENCES entities(id) ON DELETE RESTRICT,
250
+ depends_on_id INTEGER NOT NULL REFERENCES entities(id) ON DELETE RESTRICT,
251
+ created_at TEXT NOT NULL,
252
+ PRIMARY KEY(entity_id, depends_on_id),
253
+ CHECK(entity_id <> depends_on_id)
254
+ );
255
+ CREATE INDEX IF NOT EXISTS idx_dependencies_incoming ON dependencies(depends_on_id, entity_id);
256
+
257
+ CREATE TRIGGER IF NOT EXISTS trg_dependencies_immutable
258
+ BEFORE UPDATE ON dependencies
259
+ BEGIN
260
+ SELECT RAISE(ABORT, 'IMMUTABLE_EDGE');
261
+ END;
262
+
263
+ CREATE TRIGGER IF NOT EXISTS trg_dependencies_cycle
264
+ BEFORE INSERT ON dependencies
265
+ WHEN EXISTS (
266
+ WITH RECURSIVE reachable(id) AS (
267
+ SELECT NEW.depends_on_id
268
+ UNION
269
+ SELECT d.depends_on_id FROM dependencies d JOIN reachable r ON d.entity_id = r.id
270
+ )
271
+ SELECT 1 FROM reachable WHERE id = NEW.entity_id
272
+ )
273
+ BEGIN
274
+ SELECT RAISE(ABORT, 'DEPENDENCY_CYCLE');
275
+ END;
276
+
277
+ CREATE TABLE IF NOT EXISTS notes(
278
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
279
+ entity_id INTEGER NOT NULL REFERENCES entities(id) ON DELETE RESTRICT,
280
+ body TEXT NOT NULL CHECK(length(trim(body)) > 0),
281
+ author_team_path TEXT,
282
+ author_alias TEXT,
283
+ created_at TEXT NOT NULL,
284
+ CHECK ((author_team_path IS NULL AND author_alias IS NULL) OR
285
+ (author_team_path IS NOT NULL AND author_alias IS NOT NULL AND
286
+ length(trim(author_team_path)) > 0 AND length(trim(author_alias)) > 0))
287
+ );
288
+ CREATE INDEX IF NOT EXISTS idx_notes_entity ON notes(entity_id, id);
289
+
290
+ CREATE TABLE IF NOT EXISTS cron_jobs(
291
+ id INTEGER PRIMARY KEY AUTOINCREMENT CHECK(id > 0),
292
+ title TEXT NOT NULL CHECK(length(trim(title)) > 0),
293
+ schedule_expr TEXT NOT NULL CHECK(length(trim(schedule_expr)) > 0),
294
+ action_kind TEXT NOT NULL CHECK(action_kind IN ('enqueue', 'command', 'script', 'session', 'miniplayer')),
295
+ action_payload TEXT NOT NULL CHECK(length(trim(action_payload)) > 0),
296
+ provider TEXT,
297
+ model TEXT,
298
+ working_directory TEXT,
299
+ escalation_owner TEXT,
300
+ session_teamfile TEXT,
301
+ session_alias TEXT,
302
+ session_seeded_at TEXT,
303
+ session_generation INTEGER NOT NULL DEFAULT 0,
304
+ enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0, 1)),
305
+ last_checked_ts TEXT,
306
+ last_fired_ts TEXT,
307
+ last_fire_status TEXT CHECK(last_fire_status IS NULL OR
308
+ last_fire_status IN ('ok', 'error', 'skipped_overlap', 'skipped_stale', 'reconciled', 'blocked_escalation')),
309
+ last_fire_error TEXT,
310
+ running_systemd_unit TEXT,
311
+ timezone TEXT,
312
+ running_since_ts TEXT,
313
+ created_at TEXT NOT NULL,
314
+ updated_at TEXT NOT NULL,
315
+ revision INTEGER NOT NULL DEFAULT 1 CHECK(typeof(revision)='integer' AND revision > 0)
316
+ );
317
+ CREATE INDEX IF NOT EXISTS idx_cron_jobs_enabled ON cron_jobs(enabled);
318
+
319
+ CREATE TABLE IF NOT EXISTS cron_runs(
320
+ id INTEGER PRIMARY KEY AUTOINCREMENT CHECK(id > 0),
321
+ job_id INTEGER NOT NULL,
322
+ run_token_hash TEXT NOT NULL UNIQUE,
323
+ status TEXT NOT NULL CHECK(status IN ('pending', 'running', 'succeeded', 'failed', 'escalated')),
324
+ execution_state TEXT NOT NULL CHECK(execution_state IN ('active', 'uncertain', 'gone')),
325
+ trigger_kind TEXT NOT NULL,
326
+ config_snapshot TEXT NOT NULL,
327
+ execution_identity TEXT,
328
+ pid INTEGER,
329
+ summary TEXT,
330
+ artifacts TEXT,
331
+ escalation_reason TEXT,
332
+ escalation_action TEXT,
333
+ escalation_owner TEXT,
334
+ escalation_resolved_at TEXT,
335
+ escalation_resolution TEXT,
336
+ escalation_resolution_actor TEXT,
337
+ escalation_resolution_note TEXT,
338
+ execution_gone_at TEXT,
339
+ execution_uncertain_reason TEXT,
340
+ execution_confirmation_note TEXT,
341
+ reported_at TEXT,
342
+ created_at TEXT NOT NULL,
343
+ started_at TEXT,
344
+ finished_at TEXT,
345
+ updated_at TEXT NOT NULL
346
+ );
347
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_cron_runs_active_job ON cron_runs(job_id)
348
+ WHERE execution_state != 'gone' OR (status = 'escalated' AND escalation_resolved_at IS NULL);
349
+ CREATE INDEX IF NOT EXISTS idx_cron_runs_job ON cron_runs(job_id);
350
+ CREATE INDEX IF NOT EXISTS idx_cron_runs_status ON cron_runs(status);
351
+
352
+ CREATE TABLE IF NOT EXISTS logical_names(
353
+ name TEXT PRIMARY KEY CHECK(length(trim(name)) > 0 AND name != 'operator'),
354
+ teamfile_path TEXT NOT NULL CHECK(length(trim(teamfile_path)) > 0),
355
+ alias TEXT NOT NULL CHECK(length(trim(alias)) > 0),
356
+ updated_at TEXT NOT NULL
357
+ );
358
+
359
+ CREATE TABLE IF NOT EXISTS rate_limit_readings(
360
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
361
+ provider TEXT NOT NULL,
362
+ status TEXT NOT NULL CHECK(status IN ('ok', 'provider_unavailable', 'auth_expired', 'not_applicable', 'reader_throttled')),
363
+ source TEXT,
364
+ read_at INTEGER NOT NULL,
365
+ reason TEXT,
366
+ detail TEXT,
367
+ retry_after_seconds INTEGER,
368
+ inserted_at INTEGER NOT NULL
369
+ );
370
+ CREATE INDEX IF NOT EXISTS idx_rate_limit_readings_provider_read_at ON rate_limit_readings(provider, read_at);
371
+
372
+ CREATE TABLE IF NOT EXISTS rate_limit_bucket_samples(
373
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
374
+ reading_id INTEGER NOT NULL REFERENCES rate_limit_readings(id),
375
+ provider TEXT NOT NULL,
376
+ bucket_id TEXT NOT NULL,
377
+ window_type TEXT NOT NULL CHECK(window_type IN ('five_hour', 'weekly', 'unknown')),
378
+ group_name TEXT,
379
+ used_fraction REAL NOT NULL,
380
+ resets_at INTEGER NOT NULL,
381
+ resets_at_iso TEXT,
382
+ raw_value TEXT,
383
+ raw_scale TEXT,
384
+ is_exhausted INTEGER,
385
+ read_at INTEGER NOT NULL
386
+ );
387
+ CREATE INDEX IF NOT EXISTS idx_rate_limit_bucket_samples_series ON rate_limit_bucket_samples(provider, bucket_id, resets_at, read_at);
388
+
389
+ CREATE TABLE IF NOT EXISTS rate_limit_policy_arm(
390
+ provider TEXT NOT NULL,
391
+ bucket_id TEXT NOT NULL,
392
+ resets_at INTEGER NOT NULL,
393
+ rule TEXT NOT NULL CHECK(rule IN ('five_hour_15m', 'weekly_1h')),
394
+ armed_at INTEGER NOT NULL,
395
+ armed_latest_read_at INTEGER NOT NULL,
396
+ armed_used_fraction REAL NOT NULL,
397
+ forecast_at INTEGER NOT NULL,
398
+ PRIMARY KEY (provider, bucket_id, resets_at)
399
+ );
400
+
401
+ CREATE TABLE IF NOT EXISTS rate_limit_policy_log(
402
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
403
+ ts INTEGER NOT NULL,
404
+ provider TEXT NOT NULL,
405
+ bucket_id TEXT NOT NULL,
406
+ window_type TEXT NOT NULL,
407
+ outcome TEXT NOT NULL CHECK(outcome IN ('armed', 'disarmed', 'confirmed_fired', 'confirmed_deferred_existing_disable', 'confirmed_would_fire_policy_disabled')),
408
+ detail TEXT NOT NULL
409
+ );
410
+ CREATE INDEX IF NOT EXISTS idx_rate_limit_policy_log_provider_ts ON rate_limit_policy_log(provider, ts);
411
+
412
+ CREATE TABLE IF NOT EXISTS prompt_tasks(
413
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
414
+ parent_id INTEGER REFERENCES prompt_tasks(id),
415
+ kind TEXT NOT NULL DEFAULT 'task' CHECK(kind IN ('epic', 'task')),
416
+ title TEXT NOT NULL,
417
+ description TEXT NOT NULL DEFAULT '',
418
+ created_at TEXT NOT NULL
419
+ );
420
+ CREATE INDEX IF NOT EXISTS idx_prompt_tasks_parent ON prompt_tasks(parent_id);
421
+
422
+ CREATE TABLE IF NOT EXISTS task_prompts(
423
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
424
+ task_id INTEGER REFERENCES prompt_tasks(id),
425
+ from_id TEXT NOT NULL,
426
+ to_id TEXT NOT NULL,
427
+ prompt TEXT NOT NULL,
428
+ created_at TEXT NOT NULL,
429
+ retrieved_ts TEXT
430
+ );
431
+ CREATE INDEX IF NOT EXISTS idx_task_prompts_task ON task_prompts(task_id);
432
+ CREATE INDEX IF NOT EXISTS idx_task_prompts_to ON task_prompts(to_id, created_at);
433
+
434
+ CREATE TABLE IF NOT EXISTS prompt_task_reassignments(
435
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
436
+ prompt_id INTEGER NOT NULL REFERENCES task_prompts(id),
437
+ from_task_id INTEGER REFERENCES prompt_tasks(id),
438
+ to_task_id INTEGER NOT NULL REFERENCES prompt_tasks(id),
439
+ reassigned_by TEXT NOT NULL,
440
+ reassigned_at TEXT NOT NULL
441
+ );
442
+ CREATE INDEX IF NOT EXISTS idx_prompt_task_reassignments_prompt ON prompt_task_reassignments(prompt_id);
443
+
444
+ CREATE TABLE IF NOT EXISTS auto_nudge_suspended(
445
+ team TEXT PRIMARY KEY,
446
+ reason TEXT NOT NULL,
447
+ detail TEXT NOT NULL,
448
+ suspended_at TEXT NOT NULL
449
+ );
450
+
451
+ CREATE TABLE IF NOT EXISTS unresolvable_teamfile_watch(
452
+ team TEXT PRIMARY KEY,
453
+ first_observed_ts TEXT NOT NULL,
454
+ surfaced_ts TEXT
455
+ );
@@ -0,0 +1,18 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>lmauto</title>
7
+ <link rel="stylesheet" href="styles.css">
8
+ </head>
9
+ <body>
10
+ <main id="app"></main>
11
+ <noscript>
12
+ <main class="home-panel">
13
+ <p class="muted">lmauto's local web requires JavaScript.</p>
14
+ </main>
15
+ </noscript>
16
+ <script src="local.js" defer></script>
17
+ </body>
18
+ </html>