@hasna/loops 0.4.27 → 0.4.29

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 (79) hide show
  1. package/CHANGELOG.md +205 -1
  2. package/README.md +232 -49
  3. package/dist/api/index.d.ts +20 -19
  4. package/dist/api/index.js +7770 -1342
  5. package/dist/cli/index.js +2976 -966
  6. package/dist/cli/safe-error-context.d.ts +1 -0
  7. package/dist/daemon/daemon.d.ts +1 -0
  8. package/dist/daemon/index.js +1899 -499
  9. package/dist/generated/storage-kit/index.d.ts +1 -1
  10. package/dist/generated/storage-kit/mode.d.ts +6 -12
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.js +5319 -1096
  13. package/dist/lib/advancement.d.ts +52 -0
  14. package/dist/lib/agent-adapter.d.ts +20 -2
  15. package/dist/lib/auth/route-policy.d.ts +14 -0
  16. package/dist/lib/auth/tenant-auth.d.ts +38 -0
  17. package/dist/lib/cloud/mode.d.ts +2 -8
  18. package/dist/lib/cloud/storage.d.ts +1 -2
  19. package/dist/lib/cloud/transport.d.ts +4 -18
  20. package/dist/lib/errors.d.ts +43 -1
  21. package/dist/lib/executor.d.ts +9 -0
  22. package/dist/lib/format.d.ts +2 -2
  23. package/dist/lib/goal/runner.d.ts +36 -3
  24. package/dist/lib/health.d.ts +1 -1
  25. package/dist/lib/labels.d.ts +4 -0
  26. package/dist/lib/loop-status.d.ts +4 -0
  27. package/dist/lib/migration.d.ts +70 -17
  28. package/dist/lib/mode.d.ts +2 -5
  29. package/dist/lib/mode.js +28 -37
  30. package/dist/lib/route/fields.d.ts +8 -0
  31. package/dist/lib/route/index.d.ts +2 -2
  32. package/dist/lib/route/throttle.d.ts +7 -0
  33. package/dist/lib/route/types.d.ts +3 -0
  34. package/dist/lib/run-completion.d.ts +18 -0
  35. package/dist/lib/scheduler.d.ts +5 -11
  36. package/dist/lib/storage/contract.d.ts +15 -1
  37. package/dist/lib/storage/index.d.ts +1 -1
  38. package/dist/lib/storage/index.js +4083 -486
  39. package/dist/lib/storage/pg-executor.d.ts +10 -5
  40. package/dist/lib/storage/postgres-loop-storage.d.ts +52 -26
  41. package/dist/lib/storage/postgres-schema.d.ts +8 -0
  42. package/dist/lib/storage/postgres-schema.js +1326 -1
  43. package/dist/lib/storage/postgres.d.ts +3 -1
  44. package/dist/lib/storage/postgres.js +1356 -27
  45. package/dist/lib/storage/provider-credentials.d.ts +84 -0
  46. package/dist/lib/storage/shared-database-transfer.d.ts +136 -0
  47. package/dist/lib/storage/sqlite.d.ts +15 -2
  48. package/dist/lib/storage/sqlite.js +1379 -217
  49. package/dist/lib/storage/tenant-backfill-s3.d.ts +53 -0
  50. package/dist/lib/storage/tenant-backfill.d.ts +40 -0
  51. package/dist/lib/store/index.d.ts +14 -8
  52. package/dist/lib/store.d.ts +129 -7
  53. package/dist/lib/store.js +1352 -218
  54. package/dist/lib/templates.d.ts +11 -0
  55. package/dist/lib/workflow-events.d.ts +6 -0
  56. package/dist/lib/workflow-provenance.d.ts +8 -0
  57. package/dist/lib/workflow-runner.d.ts +52 -4
  58. package/dist/mcp/index.js +2074 -657
  59. package/dist/runner/index.d.ts +20 -2
  60. package/dist/runner/index.js +2146 -183
  61. package/dist/sdk/http.d.ts +364 -4
  62. package/dist/sdk/http.js +379 -1
  63. package/dist/sdk/index.d.ts +7 -2
  64. package/dist/sdk/index.js +2341 -742
  65. package/dist/serve/index.d.ts +14 -0
  66. package/dist/serve/index.js +13269 -1830
  67. package/dist/types.d.ts +75 -3
  68. package/docs/AUTOMATION_RUNTIME_DESIGN.md +32 -32
  69. package/docs/CUTOVER-RUNBOOK.md +158 -31
  70. package/docs/DEPLOYMENT_MODES.md +84 -56
  71. package/docs/RUNTIME_BOUNDARY.md +26 -26
  72. package/docs/SHARED-DATABASE-TRANSFER.md +95 -0
  73. package/docs/SHARED_KIT_EXTRACTION_INVENTORY.md +631 -0
  74. package/docs/TRANSCRIPT_LOOP_PATTERNS.md +3 -3
  75. package/docs/UNIFIED_PRODUCT_CONTRACT.md +365 -0
  76. package/docs/USAGE.md +150 -56
  77. package/docs/workflows/transcript-feedback-to-loops.json +2 -2
  78. package/package.json +8 -4
  79. package/dist/lib/storage/pg-runner-claim.d.ts +0 -40
@@ -0,0 +1,631 @@
1
+ # Shared Kit Extraction Inventory
2
+
3
+ Date: 2026-07-07
4
+
5
+ Task: `8fd378e0-909c-4d13-8c7d-16b950591c2f`
6
+
7
+ This is a report-only inventory for the P5 shared-kits workstream. It does not
8
+ publish packages, edit Bun release-age exclusions, migrate consumers, or change
9
+ runtime code.
10
+
11
+ Current-status correction (2026-07-20): the cross-repo observations below
12
+ remain the 2026-07-07 inventory. OpenLoops state normalization landed through
13
+ PR #81 at commit `0acb5e79` and merge commit `6d1e9536`. The current strict
14
+ storage kit is version `0.5.2`, established through PR #93 at commit
15
+ `1456b852`, and its validation command is `bun run check:contracts`. PR #84 is
16
+ not current normalization evidence and has its own disposition.
17
+
18
+ ## Summary
19
+
20
+ The strongest extraction candidate is the generated Hasna storage kit. It is
21
+ already a bounded kit, it is stamped into multiple repositories by
22
+ `@hasna/contracts vendor-kit`, and the inspected repos show repeated hashes
23
+ across version cohorts. It should be normalized and extracted before less
24
+ stable runtime, CLI, event, or logging helpers.
25
+
26
+ The CLI, local path/config, logging/redaction, retention, and event surfaces are
27
+ real duplication, but they are not equally ready. Some already have an owning
28
+ package (`@hasna/events`, `@hasna/logs`, `@hasna/contracts`). Others have
29
+ repo-specific behavior that would make a broad extraction risky without a
30
+ human package-boundary decision.
31
+
32
+ Recommended first automation slice:
33
+
34
+ 1. Treat OpenLoops normalization as complete: version `0.5.1` state
35
+ normalization landed through PR #81 at commit `0acb5e79` and merge commit
36
+ `6d1e9536`; the current strict storage kit is version `0.5.2`, established
37
+ through PR #93 at commit `1456b852`. Validate it with
38
+ `bun run check:contracts`.
39
+ 2. After human approval of package ownership/name, extract the generated kit
40
+ into a shared package or stable `@hasna/contracts` subpath.
41
+ 3. Migrate consumers one repo cohort at a time, preserving their local storage
42
+ semantics.
43
+
44
+ ## Repos And Files Inspected
45
+
46
+ Primary repo, writeable worktree:
47
+
48
+ - `open-loops/package.json`
49
+ - `open-loops/docs/AUTOMATION_RUNTIME_DESIGN.md`
50
+ - `open-loops/docs/DEPLOYMENT_MODES.md`
51
+ - `open-loops/docs/RUNTIME_BOUNDARY.md`
52
+ - `open-loops/docs/USAGE.md`
53
+ - `open-loops/src/cli/index.ts`
54
+ - `open-loops/src/api/index.ts`
55
+ - `open-loops/src/serve/index.ts`
56
+ - `open-loops/src/runner/index.ts`
57
+ - `open-loops/src/daemon/index.ts`
58
+ - `open-loops/src/daemon/daemon.ts`
59
+ - `open-loops/src/daemon/install.ts`
60
+ - `open-loops/src/lib/mode.ts`
61
+ - `open-loops/src/lib/paths.ts`
62
+ - `open-loops/src/lib/env.ts`
63
+ - `open-loops/src/lib/storage/contract.ts`
64
+ - `open-loops/src/lib/storage/sqlite.ts`
65
+ - `open-loops/src/lib/storage/postgres.ts`
66
+ - `open-loops/src/lib/storage/postgres-schema.ts`
67
+ - `open-loops/src/lib/hygiene.ts`
68
+ - `open-loops/src/lib/run-artifacts.ts`
69
+ - `open-loops/src/lib/run-receipts.ts`
70
+ - `open-loops/src/lib/cloud/mode.ts`
71
+ - `open-loops/src/lib/cloud/resolve.ts`
72
+ - `open-loops/src/lib/cloud/storage.ts`
73
+ - `open-loops/src/lib/cloud/transport.ts`
74
+ - `open-loops/src/lib/route/options.ts`
75
+ - `open-loops/src/lib/route/route-event.ts`
76
+ - `open-loops/src/lib/route/todos-cli.ts`
77
+ - `open-loops/src/sdk/index.ts`
78
+ - `open-loops/src/generated/storage-kit/*`
79
+
80
+ Sibling repos inspected read-only:
81
+
82
+ - `open-todos/package.json`
83
+ - `open-todos/src/cli/index.tsx`
84
+ - `open-todos/src/cli/helpers.ts`
85
+ - `open-todos/src/cli/cloud-router.ts`
86
+ - `open-todos/src/db/database.ts`
87
+ - `open-todos/src/db/webhooks.ts`
88
+ - `open-todos/src/lib/event-hooks.ts`
89
+ - `open-todos/src/lib/shared-events.ts`
90
+ - `open-todos/src/lib/retention-cleanup.ts`
91
+ - `open-todos/src/storage/config.ts`
92
+ - `open-projects/package.json`
93
+ - `open-projects/src/cli/index.ts`
94
+ - `open-projects/src/cli/commands/storage.ts`
95
+ - `open-projects/src/db/database.ts`
96
+ - `open-projects/src/db/remote-storage.ts`
97
+ - `open-projects/src/db/storage-sync.ts`
98
+ - `open-projects/src/lib/project-store-paths.ts`
99
+ - `open-projects/src/generated/storage-kit/*`
100
+ - `open-conversations/package.json`
101
+ - `open-conversations/src/cli/index.tsx`
102
+ - `open-conversations/src/lib/cloud-store.ts`
103
+ - `open-conversations/src/lib/db.ts`
104
+ - `open-conversations/src/lib/webhooks.ts`
105
+ - `open-conversations/src/generated/storage-kit/*`
106
+ - `open-mementos/package.json`
107
+ - `open-mementos/src/cli/index.tsx`
108
+ - `open-mementos/src/db/database.ts`
109
+ - `open-mementos/src/lib/config.ts`
110
+ - `open-mementos/src/generated/storage-kit/*`
111
+ - `open-knowledge/package.json`
112
+ - `open-knowledge/src/cli.ts`
113
+ - `open-knowledge/src/cloud-store.ts`
114
+ - `open-knowledge/src/knowledge-db.ts`
115
+ - `open-knowledge/src/db/remote-storage.ts`
116
+ - `open-knowledge/src/generated/storage-kit/*`
117
+ - `open-machines/package.json`
118
+ - `open-machines/src/cli/index.ts`
119
+ - `open-machines/src/paths.ts`
120
+ - `open-machines/src/cloud/mode.ts`
121
+ - `open-machines/src/cloud/storage.ts`
122
+ - `open-machines/src/remote-storage.ts`
123
+ - `open-machines/src/generated/storage-kit/*`
124
+ - `open-accounts/package.json`
125
+ - `open-accounts/src/cli.ts`
126
+ - `open-accounts/src/lib/env.ts`
127
+ - `open-accounts/src/lib/events.ts`
128
+ - `open-accounts/src/storage.ts`
129
+ - `open-accounts/src/generated/storage-kit/*`
130
+ - `open-configs/package.json`
131
+ - `open-configs/src/cli/index.tsx`
132
+ - `open-configs/src/cli/storage.ts`
133
+ - `open-configs/src/lib/session-render.ts`
134
+ - `open-configs/src/storage.ts`
135
+ - `open-configs/src/generated/storage-kit/*`
136
+ - `open-logs/package.json`
137
+ - `open-logs/src/cli/index.ts`
138
+ - `open-logs/src/db/index.ts`
139
+ - `open-logs/src/lib/cloud-store.ts`
140
+ - `open-logs/src/lib/event-store.ts`
141
+ - `open-logs/src/lib/redaction.ts`
142
+ - `open-logs/src/lib/retention.ts`
143
+ - `open-logs/src/lib/rotate.ts`
144
+ - `open-logs/src/generated/storage-kit/*`
145
+ - `open-events/package.json`
146
+ - `open-events/src/cli/index.ts`
147
+ - `open-events/src/commander.ts`
148
+ - `open-events/src/index.ts`
149
+ - `open-events/src/storage.ts`
150
+ - `open-events/src/transports.ts`
151
+ - `open-codewith/package.json`
152
+ - `open-codewith/scripts/start-codewith-exec.sh`
153
+ - `open-codewith/scripts/run_tui_with_exec_server.sh`
154
+ - `open-codewith/scripts/test-remote-env.sh`
155
+ - `open-codewith/scripts/install/install.sh`
156
+ - `open-codewith/scripts/mock_responses_websocket_server.py`
157
+
158
+ ## Concrete Duplication Evidence
159
+
160
+ ### Generated Storage Kit
161
+
162
+ `src/generated/storage-kit/README.md` describes this as a generated fleet
163
+ storage kit from `@hasna/contracts vendor-kit`, with mode resolution, TLS,
164
+ pool, query, migrations, health, and no sync/cache behavior. The inspected
165
+ repos carry the same generated file set:
166
+
167
+ - `index.ts`
168
+ - `mode.ts`
169
+ - `pool.ts`
170
+ - `query.ts`
171
+ - `tls.ts`
172
+ - `health.ts`
173
+ - `migrations.ts`
174
+ - `.storage-kit-manifest.json`
175
+ - `README.md`
176
+
177
+ Observed manifest cohorts:
178
+
179
+ - `kitVersion: 0.4.0`: `open-loops`, `open-knowledge`
180
+ - `kitVersion: 0.4.1`: `open-projects`, `open-conversations`,
181
+ `open-mementos`, `open-accounts`
182
+ - `kitVersion: 0.4.2`: `open-machines`, `open-configs`, `open-logs`
183
+
184
+ Observed hash evidence:
185
+
186
+ - `open-projects`, `open-conversations`, `open-mementos`, and
187
+ `open-accounts` have identical hashes for all sampled generated storage kit
188
+ files at `kitVersion: 0.4.1`.
189
+ - `open-machines`, `open-configs`, and `open-logs` have identical hashes for
190
+ all sampled generated storage kit files at `kitVersion: 0.4.2`.
191
+ - `open-loops` and `open-knowledge` share the same `index.ts`, `mode.ts`,
192
+ `pool.ts`, `query.ts`, and `health.ts` hashes at `kitVersion: 0.4.0`; their
193
+ `tls.ts` and `migrations.ts` hashes differ from each other, so they need a
194
+ drift check before extraction.
195
+ - All inspected generated storage-kit `README.md` files use the same hash.
196
+
197
+ This is the best candidate because it is already generated, bounded, and
198
+ versioned. Extraction would reduce vendored drift and stop each repo from
199
+ carrying generated code in source.
200
+
201
+ ### Local Storage And Path Resolution
202
+
203
+ The repos also duplicate local data directory and database path logic:
204
+
205
+ - `open-loops/src/lib/paths.ts` resolves `LOOPS_DATA_DIR` or
206
+ `~/.hasna/loops`, then derives `loops.db`, daemon PID/log paths, and startup
207
+ service paths.
208
+ - `open-todos/src/db/database.ts` resolves `HASNA_TODOS_DB_PATH`, nearest
209
+ `.hasna/todos/todos.db`, git-root `.hasna/todos/todos.db`, and finally
210
+ `~/.hasna/todos/todos.db`.
211
+ - `open-projects/src/db/database.ts` resolves `HASNA_PROJECTS_DB_PATH`, legacy
212
+ `HASNA_WORKSPACES_DB_PATH`, and `~/.hasna/projects/projects.db`, then enables
213
+ WAL and foreign keys.
214
+ - `open-projects/src/lib/project-store-paths.ts` resolves
215
+ `HASNA_PROJECTS_HOME` plus per-workspace `workspaces/<id>` and `data/<id>`
216
+ paths.
217
+ - `open-conversations/src/lib/db.ts` resolves `~/.hasna/conversations`,
218
+ migrates from `~/.conversations`, and honors `HASNA_CONVERSATIONS_DB_PATH`
219
+ and `CONVERSATIONS_DB_PATH`.
220
+ - `open-logs/src/db/index.ts` resolves `HASNA_LOGS_DATA_DIR` or
221
+ `LOGS_DATA_DIR`, migrates from `~/.logs`, enforces `0700`/`0600`, and enables
222
+ WAL/foreign keys with busy retries.
223
+ - `open-events/src/storage.ts` resolves `HASNA_EVENTS_DIR`,
224
+ `HASNA_EVENTS_HOME`, or `~/.hasna/events`, then creates the directory with
225
+ private mode.
226
+
227
+ There is duplication, but local path behavior differs enough by app that it
228
+ should be a small helper inside a broader storage/runtime kit, not a standalone
229
+ package first.
230
+
231
+ ### Cloud Client And Storage Sync
232
+
233
+ The generated storage kit deliberately excludes sync/cache logic, but several
234
+ repos re-implement adjacent cloud transport or remote storage wrappers:
235
+
236
+ - `open-loops/src/lib/cloud/transport.ts` resolves client mode and cloud HTTP
237
+ transport from `HASNA_<APP>_STORAGE_MODE`, API URL, and API key variables.
238
+ - `open-conversations/src/lib/cloud-store.ts` uses
239
+ `@hasna/contracts/client/storage` and adds app-specific implied
240
+ `self_hosted` mode when API URL and API key are present.
241
+ - `open-logs/src/lib/cloud-store.ts` follows the same implied self-hosted
242
+ pattern and wraps a cloud store for logs resources.
243
+ - `open-projects/src/db/remote-storage.ts` implements a local `PgAdapterAsync`
244
+ with placeholder translation, undefined-to-null conversion, and TLS
245
+ detection.
246
+ - `open-projects/src/db/storage-sync.ts`, `open-logs/src/lib/storage-sync.ts`,
247
+ and equivalent storage exports expose similar status, push, pull, sync,
248
+ canonical RDS, and table-selection concepts.
249
+
250
+ This is a second-order candidate after the generated storage kit. A premature
251
+ sync extraction would mix very different app data models.
252
+
253
+ ### CLI Scaffolding
254
+
255
+ The inspected repos duplicate Commander setup, JSON detection, package-version
256
+ lookup, printing helpers, and numeric option parsing:
257
+
258
+ - `open-loops/src/cli/index.ts` has `new Command()`, global `-j/--json`,
259
+ `print`, `reportCliError`, `runAction`, deployment status printing, and many
260
+ repeated option parser helpers.
261
+ - `open-todos/src/cli/index.tsx` has a top-level Commander app, global
262
+ `--project`, `--json`, `--agent`, and `--session`, dynamic command module
263
+ registration, and optional event command fallback logic.
264
+ - `open-todos/src/cli/helpers.ts` has `printJson`; many todo command modules
265
+ also define local parse helpers.
266
+ - `open-projects/src/cli/index.ts` duplicates package-version lookup,
267
+ Commander setup, JSON env toggles, and prompt-mode argument routing.
268
+ - `open-projects/src/cli/commands/storage.ts`,
269
+ `open-configs/src/cli/storage.ts`, and `open-machines/src/cli/index.ts`
270
+ duplicate storage command shapes and JSON printing.
271
+ - `open-events/src/cli/index.ts` is a hand-rolled parser rather than Commander,
272
+ while `open-events/src/commander.ts` provides a reusable Commander
273
+ registration helper for events/channels.
274
+
275
+ This is a real candidate, but not first. The repos differ between Ink CLIs,
276
+ plain Commander CLIs, hand-rolled CLIs, prompt-mode CLIs, and safety-gated
277
+ mutation CLIs. A package boundary needs human approval and a compatibility
278
+ matrix before migration.
279
+
280
+ ### Event And Webhook Functionality
281
+
282
+ `@hasna/events` already exists and is partially adopted:
283
+
284
+ - `open-events/src/index.ts`, `src/transports.ts`, `src/storage.ts`, and
285
+ `src/commander.ts` define the shared EventsClient, storage, transports, and
286
+ Commander registration helper.
287
+ - `open-projects/src/cli/index.ts`,
288
+ `open-conversations/src/cli/index.tsx`, `open-accounts/src/cli.ts`, and
289
+ `open-configs/src/cli/index.tsx` call `registerEventsCommands`.
290
+ - `open-todos/src/lib/shared-events.ts` uses `EventsClient`, but
291
+ `open-todos/src/lib/event-hooks.ts` and `open-todos/src/db/webhooks.ts`
292
+ still retain local event-hook and webhook implementations.
293
+ - `open-conversations/src/lib/webhooks.ts` keeps config-backed app-specific
294
+ webhook dispatch.
295
+ - `open-machines/src/cli/index.ts`, `src/commands/runtime.ts`,
296
+ `src/commands/serve.ts`, and `src/mcp/server.ts` directly use
297
+ `EventsClient` while preserving machine-specific mutation approval gates.
298
+ - `open-loops/src/lib/route/route-event.ts` imports `EventEnvelope` and owns
299
+ route-specific event-to-workflow behavior; `open-loops/src/cli/index.ts`
300
+ exposes deprecated `events` aliases for route commands, not generic events.
301
+
302
+ The correct package proposal is not a new event kit. It is continued adoption
303
+ of `@hasna/events` plus explicit compatibility tasks for app-local webhook
304
+ features.
305
+
306
+ ### Logging, Redaction, Retention, And Evidence
307
+
308
+ There are overlapping diagnostics patterns:
309
+
310
+ - `open-loops/src/daemon/daemon.ts` implements `daemonLogLine`,
311
+ `rotateDaemonLog`, default daemon stderr logging, and daemon lease/run logs.
312
+ - `open-loops/src/lib/run-artifacts.ts` writes workflow run manifests under
313
+ `runs/<project>/<subject>/<workflowRunId>/manifest.json` with staged temp
314
+ promotion.
315
+ - `open-loops/src/lib/run-receipts.ts` normalizes receipts, canonical JSON
316
+ digests, bounded stdout/stderr excerpts, evidence paths, and task/knowledge
317
+ IDs.
318
+ - `open-todos/src/lib/retention-cleanup.ts` owns local cleanup reports for old
319
+ comments, runs, verification evidence, and expired artifact files.
320
+ - `open-logs/src/lib/redaction.ts` owns richer log-entry redaction for tokens,
321
+ URL userinfo, secret assignments, auth flags, query params, emails, and more.
322
+ - `open-logs/src/lib/retention.ts` and `src/lib/rotate.ts` implement per-level
323
+ TTL and max-row log deletion.
324
+ - `open-codewith/scripts/start-codewith-exec.sh`,
325
+ `scripts/run_tui_with_exec_server.sh`, and `scripts/test-remote-env.sh`
326
+ provide shell cleanup/trap patterns; `scripts/mock_responses_websocket_server.py`
327
+ provides mock event streaming helpers. These were inspected as bounded
328
+ script surfaces, but they do not justify a shared Hasna TypeScript kit by
329
+ themselves.
330
+
331
+ This area is security-sensitive and overlaps with the existing `@hasna/logs`
332
+ package. Do not create a separate logging package without deciding whether
333
+ `@hasna/logs` owns redaction/rotation APIs for the fleet.
334
+
335
+ ## Candidate Package Boundaries
336
+
337
+ ### 1. `@hasna/storage-kit`
338
+
339
+ Status: highest-confidence candidate; package publish/name needs human
340
+ approval. OpenLoops normalization is complete: version `0.5.1` state
341
+ normalization landed through PR #81 at commit `0acb5e79` and merge commit
342
+ `6d1e9536`, and the current strict storage kit is version `0.5.2`, established
343
+ through PR #93 at commit `1456b852`. PR #84 is not current normalization
344
+ evidence and has its own disposition.
345
+
346
+ Responsibilities:
347
+
348
+ - Storage mode/env resolution for local vs cloud/self-hosted semantics.
349
+ - Postgres TLS handling that matches libpq `sslmode`.
350
+ - `pg.Pool` factory and typed query helpers.
351
+ - Migration ledger and checksum validation.
352
+ - Health and readiness probes.
353
+ - Optional app path helper for `~/.hasna/<app>/<app>.db` and app-specific env
354
+ key sets, once local path semantics are normalized.
355
+
356
+ Non-responsibilities:
357
+
358
+ - App schema definitions.
359
+ - App-specific local SQLite migrations.
360
+ - Bidirectional sync engines.
361
+ - HTTP API resource mapping.
362
+ - Runtime auth decisions.
363
+ - Release-age exclusion edits.
364
+
365
+ Migration order:
366
+
367
+ 1. Keep `open-loops/src/generated/storage-kit` on the current strict
368
+ `@hasna/contracts` version `0.5.2` and verify it with
369
+ `bun run check:contracts`. The earlier version `0.5.1` state normalization
370
+ landed through PR #81 at commit `0acb5e79` and merge commit `6d1e9536`; PR
371
+ #93 commit `1456b852` established the current strict version.
372
+ 2. Human approval: decide whether the importable boundary is a new
373
+ `@hasna/storage-kit` package or an `@hasna/contracts/storage-kit` subpath.
374
+ 3. Move generator source into the approved package boundary and add package
375
+ metadata only after approval.
376
+ 4. Migrate one consumer cohort at a time:
377
+ `open-loops` plus `open-knowledge` (`0.4.0` cohort),
378
+ `open-projects`/`open-conversations`/`open-mementos`/`open-accounts`
379
+ (`0.4.1` cohort), then
380
+ `open-machines`/`open-configs`/`open-logs` (`0.4.2` cohort).
381
+ 5. Remove vendored generated files only after imports, type declarations, and
382
+ package pack contents are stable.
383
+
384
+ Validation:
385
+
386
+ - For the current OpenLoops checkout: `bun run check:contracts`.
387
+ - Per consumer: `bun run typecheck`, targeted storage tests, and package
388
+ boundary/no-cloud tests where present.
389
+ - For OpenLoops: `bun run typecheck`, `bun test src/lib/storage/*.test.ts`,
390
+ `bun run test:boundary`, and `bun run check:contracts`.
391
+
392
+ Blockers:
393
+
394
+ - Human approval for package name and ownership.
395
+ - Publish step and Bun release-age exclusion updates are out of scope until
396
+ approval.
397
+ - Consumers currently depend on different kit versions; extraction must handle
398
+ version skew explicitly.
399
+
400
+ ### 2. `@hasna/app-runtime`
401
+
402
+ Status: medium-confidence candidate; not ready for immediate extraction.
403
+
404
+ Responsibilities:
405
+
406
+ - Resolve app home/data directories from `HASNA_<APP>_...` env keys.
407
+ - Create private directories and DB files with consistent permissions.
408
+ - Provide legacy-dotdir migration helpers.
409
+ - Normalize package-version lookup.
410
+ - Normalize executable PATH helpers for Bun/Node CLIs.
411
+
412
+ Evidence:
413
+
414
+ - `open-loops/src/lib/paths.ts`
415
+ - `open-loops/src/lib/env.ts`
416
+ - `open-todos/src/db/database.ts`
417
+ - `open-projects/src/db/database.ts`
418
+ - `open-projects/src/lib/project-store-paths.ts`
419
+ - `open-conversations/src/lib/db.ts`
420
+ - `open-logs/src/db/index.ts`
421
+ - `open-events/src/storage.ts`
422
+
423
+ Blockers:
424
+
425
+ - App semantics differ: project-local DBs, global DBs, legacy migration,
426
+ private permissions, launchd/systemd paths, and per-workspace stores are not
427
+ uniform.
428
+ - Should probably be a module inside the storage-kit boundary instead of a
429
+ separate package at first.
430
+
431
+ ### 3. `@hasna/cli-kit`
432
+
433
+ Status: useful but requires human approval and a compatibility matrix.
434
+
435
+ Responsibilities:
436
+
437
+ - Commander registration helpers for global JSON, version, error envelopes,
438
+ option parsing, and consistent text/JSON output.
439
+ - Optional command module registration pattern.
440
+ - Shared storage command scaffolding where the underlying storage API matches.
441
+ - Shared validation helpers for positive integers, durations, and list flags.
442
+
443
+ Evidence:
444
+
445
+ - `open-loops/src/cli/index.ts`
446
+ - `open-todos/src/cli/index.tsx`
447
+ - `open-todos/src/cli/helpers.ts`
448
+ - `open-projects/src/cli/index.ts`
449
+ - `open-projects/src/cli/commands/storage.ts`
450
+ - `open-configs/src/cli/storage.ts`
451
+ - `open-machines/src/cli/index.ts`
452
+ - `open-events/src/commander.ts`
453
+
454
+ Blockers:
455
+
456
+ - CLI UX differs materially across apps.
457
+ - Some repos use Ink and React, some use plain Commander, and `open-events`
458
+ has both hand-rolled and Commander embedding surfaces.
459
+ - Extracting too early could create a heavy dependency for simple binaries.
460
+
461
+ ### 4. Existing `@hasna/events` Adoption Kit
462
+
463
+ Status: no new package needed. Adoption tasks are partially automation-ready,
464
+ but each repo needs a compatibility check.
465
+
466
+ Responsibilities already owned by `@hasna/events`:
467
+
468
+ - Event envelopes.
469
+ - Local event/channel storage.
470
+ - Delivery transports.
471
+ - Filters and replay.
472
+ - Commander command registration through `@hasna/events/commander`.
473
+
474
+ Migration order:
475
+
476
+ 1. Document app-local event features that `@hasna/events` does not cover yet.
477
+ 2. Preserve `open-loops` route-event behavior separately; it is workflow route
478
+ admission, not generic event recording.
479
+ 3. Migrate local webhook implementations only where `@hasna/events` can
480
+ preserve filtering, approval gates, and nonblocking dispatch behavior.
481
+ 4. Retire compatibility aliases only with explicit deprecation docs/tests.
482
+
483
+ Blockers:
484
+
485
+ - `open-todos` and `open-conversations` have local webhook/event-hook behavior
486
+ that may not map 1:1 to `@hasna/events`.
487
+ - `open-machines` has mutation approval gates around shared event webhooks.
488
+ - `open-loops` currently uses `events` aliases for route operations, so a
489
+ generic events command group could conflict with existing operator workflows.
490
+
491
+ ### 5. Existing `@hasna/logs` Or `@hasna/diagnostics-kit`
492
+
493
+ Status: approval-gated and security-sensitive.
494
+
495
+ Responsibilities to consider:
496
+
497
+ - Structured log line helpers.
498
+ - Log rotation.
499
+ - Redaction primitives.
500
+ - Bounded output/excerpt helpers.
501
+ - Retention report formats.
502
+
503
+ Evidence:
504
+
505
+ - `open-loops/src/daemon/daemon.ts`
506
+ - `open-loops/src/lib/run-receipts.ts`
507
+ - `open-todos/src/lib/retention-cleanup.ts`
508
+ - `open-logs/src/lib/redaction.ts`
509
+ - `open-logs/src/lib/retention.ts`
510
+ - `open-logs/src/lib/rotate.ts`
511
+
512
+ Blockers:
513
+
514
+ - `@hasna/logs` already exists and likely owns much of this domain.
515
+ - Redaction changes require security review and regression fixtures.
516
+ - Log retention is app-specific and should not be centralized until schemas are
517
+ aligned.
518
+
519
+ ## Automation Readiness
520
+
521
+ Ready for automation now:
522
+
523
+ - OpenLoops generated storage-kit normalization is complete. Version `0.5.1`
524
+ state normalization landed through PR #81 at commit `0acb5e79` and merge
525
+ commit `6d1e9536`; PR #93 commit `1456b852` established the current strict
526
+ version `0.5.2`. PR #84 is not current normalization evidence and has its own
527
+ disposition. Do not auto-route a duplicate normalization task.
528
+
529
+ Ready after human approval:
530
+
531
+ - Create an importable storage-kit package/subpath.
532
+ - Migrate consumers from vendored generated storage-kit files to imports.
533
+ - Extract a CLI helper package.
534
+ - Define any new `@hasna/*` package name and publish plan.
535
+
536
+ Not ready yet:
537
+
538
+ - Logging/redaction centralization.
539
+ - Retention cleanup centralization.
540
+ - OpenLoops route-event migration.
541
+ - Broad local path/runtime extraction.
542
+
543
+ ## Follow-Up Todo Plan
544
+
545
+ Created follow-up task:
546
+
547
+ 1. OpenLoops storage-kit normalization.
548
+ Task: `2b166a36-1e7c-4882-be7f-610c4f478d39`
549
+ Fingerprint: `open-loops:p5:shared-kit:storage-kit:open-loops-normalize`
550
+ Dependency: this inventory task.
551
+ Historical output: PR #84 (`https://github.com/hasna/loops/pull/84`).
552
+ Current status: version `0.5.1` state normalization landed through PR #81
553
+ at commit `0acb5e79` and merge commit `6d1e9536`; PR #93 commit `1456b852`
554
+ established the current strict version `0.5.2`. PR #84 is not current
555
+ normalization evidence and has its own disposition.
556
+
557
+ Recommended follow-up tasks that were not created in this worker step:
558
+
559
+ 2. Storage-kit package approval checkpoint.
560
+ Fingerprint: `open-loops:p5:shared-kit:storage-kit:approval`
561
+ Dependency: storage-kit normalization evidence.
562
+ Status: human approval required; do not auto-route until approved.
563
+
564
+ 3. Events compatibility inventory for OpenLoops route aliases.
565
+ Fingerprint: `open-loops:p5:shared-kit:events:open-loops-compat`
566
+ Dependency: this inventory task and current `@hasna/events` behavior.
567
+ Status: automation-ready as a report/test inventory only; implementation
568
+ should wait until alias compatibility is proven.
569
+
570
+ 4. CLI-kit compatibility matrix.
571
+ Fingerprint: `open-loops:p5:shared-kit:cli-kit:matrix`
572
+ Dependency: storage-kit normalization is not required, but human approval is
573
+ needed before package creation.
574
+ Status: report-only unless approved.
575
+
576
+ The first item has already run and must not be auto-routed again. The other
577
+ items remain documented until package ownership or compatibility decisions are
578
+ made.
579
+
580
+ ## Validation Requirements For Later Implementation
581
+
582
+ For any follow-up that changes package metadata:
583
+
584
+ - `git diff --check`
585
+ - `bun install --frozen-lockfile` only when lockfile changes require it
586
+ - `bun run typecheck`
587
+ - `bun test`
588
+ - `bun run test:boundary` where present
589
+ - `bun pm pack --dry-run` before publishable package changes
590
+ - Staged secrets scan before commit
591
+
592
+ For storage-kit consumer migrations:
593
+
594
+ - Verify generated-kit or import boundary check.
595
+ - Run per-repo storage tests.
596
+ - Run any local/cloud/no-cloud boundary tests.
597
+ - Validate package export maps and declaration files.
598
+ - Do not remove vendored files until import paths work from a packed package or
599
+ approved workspace dependency.
600
+
601
+ For event adoption:
602
+
603
+ - Verify CLI help and JSON output for `events`/`channels` commands.
604
+ - Preserve local webhook filtering, nonblocking behavior, and approval gates.
605
+ - Add regression tests for legacy aliases before retiring them.
606
+
607
+ For logging/redaction:
608
+
609
+ - Add canary tests for tokens, URL userinfo, auth headers, query params, and
610
+ secret-looking assignment strings.
611
+ - Confirm no raw secrets appear in task comments, logs, receipts, event
612
+ envelopes, or API responses.
613
+
614
+ ## Human Approval And Publishing Blockers
615
+
616
+ - New package names require approval before package metadata, npm publish, or
617
+ Bun release-age exclusion edits.
618
+ - `@hasna/storage-kit` vs `@hasna/contracts/storage-kit` is an ownership
619
+ decision.
620
+ - `@hasna/cli-kit` must not centralize repo-specific prompt-mode or Ink UI
621
+ behavior without a compatibility matrix.
622
+ - `@hasna/logs` ownership must be resolved before creating diagnostics or
623
+ redaction packages.
624
+ - No consumer migration should be routed until the package boundary and package
625
+ source of truth are approved.
626
+
627
+ ## Naming Note (2026-07-21)
628
+
629
+ The current product display name is **Loops**. The dated inventory above retains
630
+ its historical naming as provenance, and compatibility identifiers remain
631
+ unchanged.
@@ -1,8 +1,8 @@
1
1
  # Transcript-Driven Loop Patterns
2
2
 
3
- This guide turns long-form transcripts, meeting recordings, interviews, and product feedback videos into durable OpenLoops work. It pairs `iapp-transcriber` for media ingestion with OpenLoops workflows for recurring review, implementation, and verification.
3
+ This guide turns long-form transcripts, meeting recordings, interviews, and product feedback videos into durable Loops work. It pairs `iapp-transcriber` for media ingestion with Loops workflows for recurring review, implementation, and verification.
4
4
 
5
- The pattern came from reviewing a Claude Code fireside chat transcript. The useful operational takeaway was not just "use agents more"; it was that recurring agents need narrow scope, evidence, review gates, and clear ROI. In OpenLoops terms, that means using workflows and goals to move from transcript insight to scheduled loop safely.
5
+ The pattern came from reviewing a Claude Code fireside chat transcript. The useful operational takeaway was not just "use agents more"; it was that recurring agents need narrow scope, evidence, review gates, and clear ROI. In Loops terms, that means using workflows and goals to move from transcript insight to scheduled loop safely.
6
6
 
7
7
  ## Baseline Workflow
8
8
 
@@ -20,7 +20,7 @@ The transcribe step writes `.openloops/transcripts/latest-transcript.json`. The
20
20
 
21
21
  The workflow includes non-shell `check-transcriber` and `check-loops` command steps so `loops workflows validate --preflight` can catch those missing CLIs. Shell command bodies, provider credentials, and media access are still checked by the transcriber step at runtime.
22
22
 
23
- The ingestion template intentionally does not wrap the whole workflow in an OpenLoops goal. Goal wrappers execute the underlying target for each ready goal-plan node, which is useful for implementation workflows but too surprising for media ingestion. Use goals in the generated follow-up workflows after the transcript has been converted into a concrete backlog.
23
+ The ingestion template intentionally does not wrap the whole workflow in a Loops goal. Goal wrappers execute the underlying target for each ready goal-plan node, which is useful for implementation workflows but too surprising for media ingestion. Use goals in the generated follow-up workflows after the transcript has been converted into a concrete backlog.
24
24
 
25
25
  Schedule the workflow only after a manual run produces useful backlog items:
26
26