@lumenflow/cli 5.5.0 → 5.7.12
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/README.md +42 -40
- package/dist/db-journal-recover.js +400 -0
- package/dist/db-journal-recover.js.map +1 -0
- package/dist/docs-sync.js +8 -3
- package/dist/docs-sync.js.map +1 -1
- package/dist/gate-defaults.js +37 -0
- package/dist/gate-defaults.js.map +1 -1
- package/dist/gates/monolithic-file-contention-guard.js +167 -0
- package/dist/gates/monolithic-file-contention-guard.js.map +1 -0
- package/dist/gates/prod-migration-drift.js +207 -0
- package/dist/gates/prod-migration-drift.js.map +1 -0
- package/dist/gates/test-over-deletion-guard.js +255 -0
- package/dist/gates/test-over-deletion-guard.js.map +1 -0
- package/dist/gates-runners.js +44 -3
- package/dist/gates-runners.js.map +1 -1
- package/dist/gates.js +3 -2
- package/dist/gates.js.map +1 -1
- package/dist/lumenflow-setup.js +144 -0
- package/dist/lumenflow-setup.js.map +1 -0
- package/dist/lumenflow-upgrade.js +2 -1
- package/dist/lumenflow-upgrade.js.map +1 -1
- package/dist/mem-create.js +10 -1
- package/dist/mem-create.js.map +1 -1
- package/dist/mem-signal.js +21 -4
- package/dist/mem-signal.js.map +1 -1
- package/dist/orchestrate-initiative.js +28 -3
- package/dist/orchestrate-initiative.js.map +1 -1
- package/dist/public-manifest.js +17 -0
- package/dist/public-manifest.js.map +1 -1
- package/dist/release.js +53 -18
- package/dist/release.js.map +1 -1
- package/dist/wu-done-gates.js +13 -9
- package/dist/wu-done-gates.js.map +1 -1
- package/dist/wu-edit-operations.js +74 -0
- package/dist/wu-edit-operations.js.map +1 -1
- package/dist/wu-edit-validators.js +58 -0
- package/dist/wu-edit-validators.js.map +1 -1
- package/dist/wu-edit.js +106 -4
- package/dist/wu-edit.js.map +1 -1
- package/dist/wu-prep.js +41 -7
- package/dist/wu-prep.js.map +1 -1
- package/dist/wu-recover.js +6 -0
- package/dist/wu-recover.js.map +1 -1
- package/dist/wu-release.js +120 -2
- package/dist/wu-release.js.map +1 -1
- package/dist/wu-sizing-validation.js +47 -17
- package/dist/wu-sizing-validation.js.map +1 -1
- package/dist/wu-status.js +33 -0
- package/dist/wu-status.js.map +1 -1
- package/package.json +13 -11
- package/packs/agent-runtime/package.json +1 -1
- package/packs/sidekick/package.json +1 -1
- package/packs/software-delivery/package.json +1 -1
- package/templates/core/AGENTS.md.template +67 -3
- package/templates/core/LUMENFLOW.md.template +197 -47
- package/packs/agent-runtime/agent-heartbeat.ts +0 -163
- package/packs/agent-runtime/auto-session-integration.ts +0 -888
- package/packs/agent-runtime/capability-factory.ts +0 -104
- package/packs/agent-runtime/constants.ts +0 -21
- package/packs/agent-runtime/delegation-registry-schema.ts +0 -220
- package/packs/agent-runtime/delegation-registry-store.ts +0 -269
- package/packs/agent-runtime/delegation-tree.ts +0 -328
- package/packs/agent-runtime/index.ts +0 -20
- package/packs/agent-runtime/manifest.ts +0 -348
- package/packs/agent-runtime/memory-coordination-contract.ts +0 -86
- package/packs/agent-runtime/orchestration.ts +0 -2027
- package/packs/agent-runtime/pack-registration.ts +0 -110
- package/packs/agent-runtime/policy-factory.ts +0 -165
- package/packs/agent-runtime/remote-controls/index.ts +0 -7
- package/packs/agent-runtime/remote-controls/operations.ts +0 -405
- package/packs/agent-runtime/remote-controls/port.ts +0 -48
- package/packs/agent-runtime/remote-controls/state-store.ts +0 -258
- package/packs/agent-runtime/remote-controls/types.ts +0 -105
- package/packs/agent-runtime/session-schema.ts +0 -467
- package/packs/agent-runtime/tool-impl/agent-turn-tools.ts +0 -793
- package/packs/agent-runtime/tool-impl/index.ts +0 -6
- package/packs/agent-runtime/tool-impl/provider-adapters.ts +0 -1245
- package/packs/agent-runtime/tool-impl/remote-controls.mock.ts +0 -256
- package/packs/agent-runtime/tool-impl/remote-controls.ts +0 -273
- package/packs/agent-runtime/tools/index.ts +0 -4
- package/packs/agent-runtime/tools/types.ts +0 -47
- package/packs/agent-runtime/turn-lifecycle-events.ts +0 -590
- package/packs/agent-runtime/types.ts +0 -128
- package/packs/agent-runtime/vitest.config.ts +0 -11
- package/packs/sidekick/channel-ingress.ts +0 -137
- package/packs/sidekick/constants.ts +0 -10
- package/packs/sidekick/index.ts +0 -8
- package/packs/sidekick/manifest-schema.ts +0 -49
- package/packs/sidekick/manifest.ts +0 -512
- package/packs/sidekick/pack-registration.ts +0 -110
- package/packs/sidekick/policy-factory.ts +0 -38
- package/packs/sidekick/sidekick-events.ts +0 -694
- package/packs/sidekick/src/adapters/cloud-queue.ts +0 -101
- package/packs/sidekick/src/adapters/control-plane-bridge.adapter.ts +0 -386
- package/packs/sidekick/src/adapters/filesystem-bridge.adapter.ts +0 -228
- package/packs/sidekick/src/domain/channel.types.ts +0 -64
- package/packs/sidekick/src/ports/channel-bridge.port.ts +0 -92
- package/packs/sidekick/src/routines/commit.ts +0 -74
- package/packs/sidekick/tool-impl/channel-tools.ts +0 -577
- package/packs/sidekick/tool-impl/channel-transports.ts +0 -75
- package/packs/sidekick/tool-impl/index.ts +0 -29
- package/packs/sidekick/tool-impl/memory-tools.ts +0 -290
- package/packs/sidekick/tool-impl/routine-commit.ts +0 -102
- package/packs/sidekick/tool-impl/routine-tools.ts +0 -440
- package/packs/sidekick/tool-impl/runtime-context.ts +0 -28
- package/packs/sidekick/tool-impl/shared.ts +0 -125
- package/packs/sidekick/tool-impl/storage.ts +0 -325
- package/packs/sidekick/tool-impl/system-tools.ts +0 -160
- package/packs/sidekick/tool-impl/task-tools.ts +0 -506
- package/packs/sidekick/tools/channel-tools.ts +0 -53
- package/packs/sidekick/tools/index.ts +0 -9
- package/packs/sidekick/tools/memory-tools.ts +0 -53
- package/packs/sidekick/tools/routine-tools.ts +0 -53
- package/packs/sidekick/tools/system-tools.ts +0 -47
- package/packs/sidekick/tools/task-tools.ts +0 -61
- package/packs/sidekick/tools/types.ts +0 -57
- package/packs/sidekick/vitest.config.ts +0 -11
- package/packs/software-delivery/constants.ts +0 -10
- package/packs/software-delivery/extensions.ts +0 -140
- package/packs/software-delivery/gate-policies.ts +0 -134
- package/packs/software-delivery/index.ts +0 -8
- package/packs/software-delivery/manifest-schema.ts +0 -268
- package/packs/software-delivery/manifest.ts +0 -657
- package/packs/software-delivery/pack-registration.ts +0 -113
- package/packs/software-delivery/src/commands/index.ts +0 -5
- package/packs/software-delivery/src/config/delivery-review-contract.ts +0 -256
- package/packs/software-delivery/src/config/env-accessors.ts +0 -66
- package/packs/software-delivery/src/config/index.ts +0 -8
- package/packs/software-delivery/src/config/normalize-config-keys.ts +0 -9
- package/packs/software-delivery/src/config/schemas/lumenflow-config-schema-types.ts +0 -460
- package/packs/software-delivery/src/config/workspace-reader.ts +0 -375
- package/packs/software-delivery/src/constants/backlog-patterns.ts +0 -31
- package/packs/software-delivery/src/constants/client-ids.ts +0 -19
- package/packs/software-delivery/src/constants/config-contract.ts +0 -7
- package/packs/software-delivery/src/constants/docs-layout-presets.ts +0 -50
- package/packs/software-delivery/src/constants/duration-constants.ts +0 -20
- package/packs/software-delivery/src/constants/gate-constants.ts +0 -32
- package/packs/software-delivery/src/constants/index.ts +0 -29
- package/packs/software-delivery/src/constants/lock-constants.ts +0 -35
- package/packs/software-delivery/src/constants/object-guards.ts +0 -12
- package/packs/software-delivery/src/constants/section-headings.ts +0 -107
- package/packs/software-delivery/src/constants/wu-cli-constants.ts +0 -500
- package/packs/software-delivery/src/constants/wu-domain-constants.ts +0 -466
- package/packs/software-delivery/src/constants/wu-git-constants.ts +0 -7
- package/packs/software-delivery/src/constants/wu-id-format.ts +0 -327
- package/packs/software-delivery/src/constants/wu-paths-constants.ts +0 -384
- package/packs/software-delivery/src/constants/wu-statuses.ts +0 -287
- package/packs/software-delivery/src/constants/wu-type-helpers.ts +0 -67
- package/packs/software-delivery/src/constants/wu-ui-constants.ts +0 -267
- package/packs/software-delivery/src/constants/wu-validation-constants.ts +0 -73
- package/packs/software-delivery/src/domain/index.ts +0 -5
- package/packs/software-delivery/src/domain/orchestration.constants.ts +0 -166
- package/packs/software-delivery/src/domain/orchestration.schemas.ts +0 -238
- package/packs/software-delivery/src/domain/orchestration.types.ts +0 -176
- package/packs/software-delivery/src/methodology/incremental-test.ts +0 -122
- package/packs/software-delivery/src/methodology/index.ts +0 -6
- package/packs/software-delivery/src/methodology/manual-test-validator.ts +0 -292
- package/packs/software-delivery/src/policy/coverage-gate.ts +0 -270
- package/packs/software-delivery/src/policy/gates-agent-mode.ts +0 -223
- package/packs/software-delivery/src/policy/gates-config-internal.ts +0 -121
- package/packs/software-delivery/src/policy/gates-config.ts +0 -300
- package/packs/software-delivery/src/policy/gates-coverage.ts +0 -356
- package/packs/software-delivery/src/policy/gates-presets.ts +0 -134
- package/packs/software-delivery/src/policy/gates-schemas.ts +0 -173
- package/packs/software-delivery/src/policy/index.ts +0 -22
- package/packs/software-delivery/src/policy/package-manager-resolver.ts +0 -319
- package/packs/software-delivery/src/policy/resolve-policy.ts +0 -601
- package/packs/software-delivery/src/ports/config.ports.ts +0 -90
- package/packs/software-delivery/src/ports/dashboard-renderer.port.ts +0 -125
- package/packs/software-delivery/src/ports/index.ts +0 -10
- package/packs/software-delivery/src/ports/sync-validator.ports.ts +0 -59
- package/packs/software-delivery/src/ports/wu-helpers.ports.ts +0 -168
- package/packs/software-delivery/src/ports/wu-state.ports.ts +0 -241
- package/packs/software-delivery/src/primitives/index.ts +0 -5
- package/packs/software-delivery/src/runtime/index.ts +0 -6
- package/packs/software-delivery/src/runtime/work-classifier.ts +0 -561
- package/packs/software-delivery/src/sandbox/index.ts +0 -10
- package/packs/software-delivery/src/sandbox/sandbox-allowlist.ts +0 -118
- package/packs/software-delivery/src/sandbox/sandbox-backend-linux.ts +0 -88
- package/packs/software-delivery/src/sandbox/sandbox-backend-macos.ts +0 -154
- package/packs/software-delivery/src/sandbox/sandbox-backend-windows.ts +0 -47
- package/packs/software-delivery/src/sandbox/sandbox-profile.ts +0 -153
- package/packs/software-delivery/src/schemas/index.ts +0 -5
- package/packs/software-delivery/src/state/date-utils.ts +0 -158
- package/packs/software-delivery/src/state/index.ts +0 -15
- package/packs/software-delivery/src/state/state-machine.ts +0 -119
- package/packs/software-delivery/src/state/wu-doc-types.ts +0 -51
- package/packs/software-delivery/src/state/wu-paths.ts +0 -381
- package/packs/software-delivery/src/state/wu-schema.ts +0 -1139
- package/packs/software-delivery/src/state/wu-state-schema.ts +0 -255
- package/packs/software-delivery/src/state/wu-yaml.ts +0 -338
- package/packs/software-delivery/tool-impl/agent-tools.ts +0 -263
- package/packs/software-delivery/tool-impl/delegation-tools.ts +0 -66
- package/packs/software-delivery/tool-impl/flow-metrics-tools.ts +0 -219
- package/packs/software-delivery/tool-impl/git-runner.ts +0 -113
- package/packs/software-delivery/tool-impl/git-tools.ts +0 -316
- package/packs/software-delivery/tool-impl/index.ts +0 -15
- package/packs/software-delivery/tool-impl/initiative-orchestration-tools.ts +0 -720
- package/packs/software-delivery/tool-impl/lane-lock.ts +0 -246
- package/packs/software-delivery/tool-impl/memory-tools.ts +0 -470
- package/packs/software-delivery/tool-impl/pending-runtime-tools.ts +0 -21
- package/packs/software-delivery/tool-impl/runtime-cli-adapter.ts +0 -329
- package/packs/software-delivery/tool-impl/runtime-native-tools.ts +0 -687
- package/packs/software-delivery/tool-impl/worker-loader.ts +0 -52
- package/packs/software-delivery/tool-impl/worktree-tools.ts +0 -46
- package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +0 -807
- package/packs/software-delivery/tools/delegation-tools.ts +0 -23
- package/packs/software-delivery/tools/git-tools.ts +0 -55
- package/packs/software-delivery/tools/index.ts +0 -8
- package/packs/software-delivery/tools/lane-lock-tool.ts +0 -37
- package/packs/software-delivery/tools/types.ts +0 -71
- package/packs/software-delivery/tools/worktree-tools.ts +0 -49
- package/packs/software-delivery/vitest.config.ts +0 -11
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Universal Agent Instructions
|
|
4
4
|
|
|
5
|
-
**Last updated:** {{DATE}}
|
|
5
|
+
**Last updated:** {{DATE}} (5.6.0 — INIT-069 vocabulary: `--estimated-files`, `--interrupt-class`, `test-over-deletion`, `monolithic-file-contention`, `prod-migration-drift`, `db:journal-recover`, file-overlap & lane-fit preflight)
|
|
6
6
|
|
|
7
7
|
> **Works with any AI coding assistant.** This file provides instructions that work regardless of which AI tool you're using -- Claude Code, Cursor, Windsurf, Cline, Codex, Aider, or any other. Just read this file and follow the workflow.
|
|
8
8
|
|
|
@@ -81,10 +81,22 @@ Capture findings in shared memory so other agents (and other vendors) can see th
|
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
83
|
pnpm mem:create --type discovery --wu WU-XXXX --tags <csv> --priority P? --title '<prose>'
|
|
84
|
+
# Pre-Phase Audits (WU-2940): omit --wu to capture findings before any WU exists.
|
|
85
|
+
pnpm mem:create --type discovery --tags pre-phase-audit --title 'orchestrator finding'
|
|
84
86
|
pnpm mem:signal '<short status>' --wu WU-XXXX
|
|
87
|
+
# WU-2940: --interrupt-class is canonical; --interrupt remains a back-compat alias.
|
|
88
|
+
pnpm mem:signal 'urgent: build break on main' --wu WU-XXXX --interrupt-class urgent
|
|
85
89
|
pnpm mem:checkpoint --wu WU-XXXX --note '<progress>' --next-steps '<what is next>'
|
|
86
90
|
```
|
|
87
91
|
|
|
92
|
+
For mid-flight scope correction (WU-2940), `pnpm wu:edit` accepts sizing flags
|
|
93
|
+
(`--estimated-files`, `--estimated-tool-calls`, `--sizing-strategy`,
|
|
94
|
+
`--sizing-exception-type`, `--sizing-exception-reason`) and allows
|
|
95
|
+
non-destructive edits (`--description`, `--notes`, sizing) on in-progress WUs
|
|
96
|
+
**from the main checkout** without the wu:release/wu:recover dance. Structural
|
|
97
|
+
edits (`--lane`, `--code-paths` replace, `--priority`, `--type`,
|
|
98
|
+
`--initiative`) still require the dance.
|
|
99
|
+
|
|
88
100
|
**Classification rule:** if the fact would help _another_ agent vendor working this repo, it belongs in shared memory (`mem:create`), not your vendor's personal memory folder. Examples of shared: bug discoveries, architecture decisions, CI/gates gotchas, initiative direction, cross-WU scope flags. Examples of vendor-personal: behavioural feedback, user preferences, tool-invocation mechanics.
|
|
89
101
|
|
|
90
102
|
**Shell-quoting footgun:** always **single-quote** the `--title` value. Bash expands `$var`, `$0`, backticks, and `!hist` inside double-quoted strings, silently corrupting prose containing prices (`$49`), positional refs, or exclamation marks. See [Memory section in LUMENFLOW.md](LUMENFLOW.md#memory-shared-vs-vendor-personal) for the full mem:\* contract.
|
|
@@ -137,6 +149,17 @@ pnpm mem:triage --archive mem-XXXX --reason '<why>' # drop non-actio
|
|
|
137
149
|
|
|
138
150
|
`wu:done` does not auto-triage. Unreviewed discoveries rot — always check the list before completing.
|
|
139
151
|
|
|
152
|
+
### Database Workflow Primitives (WU-2945)
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
pnpm db:journal-recover # detect drizzle journal collisions (dry-run by default)
|
|
156
|
+
pnpm db:journal-recover --confirm # apply resequence + write audit log under .lumenflow/db-recovery/
|
|
157
|
+
pnpm lumenflow:setup-prereqs # show external prereqs (e.g. Supabase CLI) — runs at end of pnpm setup
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
- `db:journal-recover` is idempotent — re-running on a healthy chain is a no-op.
|
|
161
|
+
- If your project uses Supabase, install the Supabase CLI before `pnpm db:reset`.
|
|
162
|
+
|
|
140
163
|
## Quick Start (Cloud / Branch-PR)
|
|
141
164
|
|
|
142
165
|
Cloud agents (Codex, Claude web, CI bots) that cannot use local worktrees use the **branch-pr** mode. This is a first-class lifecycle, not a workaround.
|
|
@@ -186,6 +209,13 @@ The completion workflow is a two-step process. Run `wu:prep` from the worktree (
|
|
|
186
209
|
|
|
187
210
|
For detailed troubleshooting, see [troubleshooting-wu-done.md]({{DOCS_ONBOARDING_PATH}}/troubleshooting-wu-done.md).
|
|
188
211
|
|
|
212
|
+
**Plan-time preflight (WU-2942):** `pnpm orchestrate:initiative` emits two extra sections after the wave breakdown:
|
|
213
|
+
|
|
214
|
+
- _File-overlap preflight_ — WU pairs sharing a `code_paths` entry inside the same wave (silently serial; resolve before claim).
|
|
215
|
+
- _Lane-fit suggestions_ — WUs stacked on a WIP=1 lane with concrete re-lane recommendations from `wu:infer-lane`.
|
|
216
|
+
|
|
217
|
+
Read these BEFORE claiming a wave. Default mode is advisory; configure via `software_delivery.orchestrate.preflight: 'advisory' | 'strict' | 'off'` or pass `--strict-preflight` to make warnings blocking for one run. See [LUMENFLOW.md "Plan-time preflight"](LUMENFLOW.md#plan-time-preflight-wu-2942).
|
|
218
|
+
|
|
189
219
|
---
|
|
190
220
|
|
|
191
221
|
## Core Principles
|
|
@@ -196,8 +226,10 @@ For detailed troubleshooting, see [troubleshooting-wu-done.md]({{DOCS_ONBOARDING
|
|
|
196
226
|
(`--skip-gate <name>`, repeatable) is the preferred bypass surface as of
|
|
197
227
|
WU-2925; legacy `--skip-gates` is deprecated for one minor cycle. Only gates
|
|
198
228
|
marked `skippable: true` (allow-list: `migration-verify`, `lane-health`,
|
|
199
|
-
`tdd-diff-evidence`,
|
|
200
|
-
`integration-test`, `e2e-smoke
|
|
229
|
+
`tdd-diff-evidence`, the WU-2927 opt-in local-prep gates `build`,
|
|
230
|
+
`integration-test`, `e2e-smoke`, the WU-2943 advisory heuristic gates
|
|
231
|
+
`test-over-deletion`, `monolithic-file-contention`, and the WU-2944
|
|
232
|
+
opt-in `prod-migration-drift` gate) or overridden via
|
|
201
233
|
`software_delivery.gates.overrides.<gate_id>.skippable=true` may be skipped.
|
|
202
234
|
Both flags require `--reason` and `--fix-wu`.
|
|
203
235
|
|
|
@@ -231,6 +263,31 @@ For detailed troubleshooting, see [troubleshooting-wu-done.md]({{DOCS_ONBOARDING
|
|
|
231
263
|
See [LUMENFLOW.md gates section](LUMENFLOW.md#extended-local-prep-profile-wu-2927)
|
|
232
264
|
for the schema and latency budget.
|
|
233
265
|
|
|
266
|
+
**Heuristic guard gates (WU-2943).** Two advisory gates run on every
|
|
267
|
+
`wu:prep`, both `skippable: true` (allow-listed) with
|
|
268
|
+
`prereq_strategy: 'auto-skip'`:
|
|
269
|
+
- `test-over-deletion` — flags deleted `.test.ts(x)` whose `describe()` /
|
|
270
|
+
`describe.each()` strings reference symbols outside the current WU's
|
|
271
|
+
`code_paths` (scope-creep deletion).
|
|
272
|
+
- `monolithic-file-contention` — flags files appearing in 2+ active WUs'
|
|
273
|
+
`code_paths` (statuses `in_progress` + `ready`) when the current WU is
|
|
274
|
+
one of the claimants. Output names the file, the contending WUs, and
|
|
275
|
+
suggests splitting the module to enable parallelism.
|
|
276
|
+
|
|
277
|
+
Both auto-skip cleanly when the heuristic does not fire. Per-repo override
|
|
278
|
+
to BLOCK on trigger:
|
|
279
|
+
`pnpm config:set software_delivery.gates.overrides.<gate>.skippable=false`.
|
|
280
|
+
|
|
281
|
+
**Prod-migration-drift gate (WU-2944).** Optional CI-scheduled gate that
|
|
282
|
+
detects when the production database is N+ migrations behind the canonical
|
|
283
|
+
`migrations/` directory on main. Auto-skips `not-applicable` until the
|
|
284
|
+
repo opts in by setting
|
|
285
|
+
`software_delivery.gates.overrides.prod-migration-drift.connection_string_env_var`
|
|
286
|
+
(e.g. `PROD_DATABASE_URL`). Requires the configured env var to be set and
|
|
287
|
+
the prod DB to be reachable; otherwise auto-skips under
|
|
288
|
+
`prereq_strategy: 'auto-skip'`. Threshold is configurable
|
|
289
|
+
(`overrides.prod-migration-drift.threshold`, default 5).
|
|
290
|
+
|
|
234
291
|
4. **Never Bypass Hooks**: No `--no-verify`
|
|
235
292
|
5. **Vendor-Agnostic Dirty-Main Guard**: `wu:prep` and `wu:done` hard-block when main has non-allowlisted dirty files during worktree WUs (including MCP/tool-originated writes). `branch-pr` mode is exempt.
|
|
236
293
|
6. **Docs Parity For Behavior Changes**: If you change LumenFlow behavior or workflow guidance, update internal docs, Starlight docs, or both as appropriate. Generated reference docs do not cover narrative behavior changes by themselves.
|
|
@@ -276,6 +333,13 @@ LumenFlow enforces safety at the repository level via git wrappers and hooks. Fo
|
|
|
276
333
|
|
|
277
334
|
**Key rule:** Always use `wu:` commands for worktree and branch management -- never raw `git worktree` or `git branch -D` commands. Use `wu:recover` for state inconsistencies, `wu:release` for abandoned WUs, and `wu:prune` for stale worktrees.
|
|
278
335
|
|
|
336
|
+
**WU-2941:** `wu:release` resets both the YAML status and the lane branch
|
|
337
|
+
(default: delete branch locally + on `origin`). Pass `--keep-branch` to retain
|
|
338
|
+
the branch for diagnostic recovery, or set
|
|
339
|
+
`software_delivery.wu_release.branch_action: 'keep'` in `workspace.yaml` for
|
|
340
|
+
air-gapped/offline repos. `wu:status` surfaces residual main↔worktree drift
|
|
341
|
+
inline with a `Run pnpm wu:recover --id WU-X --action reset` hint.
|
|
342
|
+
|
|
279
343
|
---
|
|
280
344
|
|
|
281
345
|
## Vendor-Specific Overlays
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# LumenFlow Workflow Guide
|
|
2
2
|
|
|
3
|
-
**Last updated:** {{DATE}}
|
|
3
|
+
**Last updated:** {{DATE}} (5.6.0 — INIT-069: workflow ergonomics, smart guard gates, db primitives, prod drift CI gate)
|
|
4
4
|
|
|
5
5
|
LumenFlow is a vendor-agnostic workflow framework for AI-native software development.
|
|
6
6
|
|
|
@@ -283,7 +283,8 @@ runtime metadata. When it is absent, receipt state falls back to the ephemeral
|
|
|
283
283
|
|
|
284
284
|
A2A signal semantics are structured, not prose-only. `mem:signal` supports
|
|
285
285
|
`--thread`, `--reply-to`, `--intent INFO|PROPOSE|COUNTER|AGREE|REJECT`,
|
|
286
|
-
`--interrupt advisory|priority|urgent|soon|immediate
|
|
286
|
+
`--interrupt-class advisory|priority|urgent|soon|immediate` (canonical name;
|
|
287
|
+
`--interrupt` remains as a back-compat alias — WU-2940), and `--requires-ack`.
|
|
287
288
|
Directed root signals default to `interrupt_class: priority` and get a generated
|
|
288
289
|
`thread_id`; broadcasts default to `interrupt_class: advisory`. Replies inherit
|
|
289
290
|
the parent thread unless `--thread` is explicit. When a recipient posts
|
|
@@ -543,28 +544,75 @@ For the full worktree lifecycle (parallel execution, bootstrap, isolation guaran
|
|
|
543
544
|
|
|
544
545
|
### WU Lifecycle
|
|
545
546
|
|
|
546
|
-
| Command | Description
|
|
547
|
-
| ----------------------- |
|
|
548
|
-
| `pnpm wu:create` | Create new WU spec (ID auto-generated)
|
|
549
|
-
| `pnpm wu:claim` | Claim WU, update canonical state, create worktree (or `--cloud`)
|
|
550
|
-
| `pnpm wu:sandbox` | Run command through hardened WU sandbox backend
|
|
551
|
-
| `pnpm wu:prep` | Run gates in worktree, prep for wu:done
|
|
552
|
-
| `pnpm wu:done` | Complete WU (merge, stamp, cleanup)
|
|
553
|
-
| `pnpm wu:edit` | Edit WU spec fields
|
|
554
|
-
| `pnpm wu:block` | Block WU (transitions to blocked, frees lane)
|
|
555
|
-
| `pnpm wu:unblock` | Unblock WU (transitions to in_progress)
|
|
556
|
-
| `pnpm wu:release` | Release orphaned WU (in_progress to ready
|
|
557
|
-
| `pnpm wu:status` | Show WU status, location, and valid commands
|
|
558
|
-
| `pnpm wu:brief` | **MANDATORY after wu:claim.** Generate handoff prompt + record evidence
|
|
559
|
-
| `pnpm wu:delegate` | Generate prompt + record lineage + brief hash attestation
|
|
560
|
-
| `pnpm wu:validate` | Validate WU spec completeness and schema
|
|
561
|
-
| `pnpm wu:recover` | Analyze and fix WU state inconsistencies
|
|
562
|
-
| `pnpm wu:verify` | Verify WU completion (stamp, commit, clean tree)
|
|
563
|
-
| `pnpm wu:escalate` | Show or resolve WU escalation status
|
|
564
|
-
| `pnpm wu:delete` | Delete WU spec and cleanup
|
|
565
|
-
| `pnpm approval:request` | Request control-plane approval for a workflow action
|
|
566
|
-
| `pnpm approval:review` | Resolve a control-plane approval decision
|
|
567
|
-
| `pnpm approval:list` | List control-plane approvals with optional filters
|
|
547
|
+
| Command | Description |
|
|
548
|
+
| ----------------------- | ------------------------------------------------------------------------------- |
|
|
549
|
+
| `pnpm wu:create` | Create new WU spec (ID auto-generated) |
|
|
550
|
+
| `pnpm wu:claim` | Claim WU, update canonical state, create worktree (or `--cloud`) |
|
|
551
|
+
| `pnpm wu:sandbox` | Run command through hardened WU sandbox backend |
|
|
552
|
+
| `pnpm wu:prep` | Run gates in worktree, prep for wu:done |
|
|
553
|
+
| `pnpm wu:done` | Complete WU (merge, stamp, cleanup) |
|
|
554
|
+
| `pnpm wu:edit` | Edit WU spec fields (sizing flags + non-destructive in-progress edits, WU-2940) |
|
|
555
|
+
| `pnpm wu:block` | Block WU (transitions to blocked, frees lane) |
|
|
556
|
+
| `pnpm wu:unblock` | Unblock WU (transitions to in_progress) |
|
|
557
|
+
| `pnpm wu:release` | Release orphaned WU (in_progress to ready) AND reset lane branch (WU-2941) |
|
|
558
|
+
| `pnpm wu:status` | Show WU status, location, and valid commands |
|
|
559
|
+
| `pnpm wu:brief` | **MANDATORY after wu:claim.** Generate handoff prompt + record evidence |
|
|
560
|
+
| `pnpm wu:delegate` | Generate prompt + record lineage + brief hash attestation |
|
|
561
|
+
| `pnpm wu:validate` | Validate WU spec completeness and schema |
|
|
562
|
+
| `pnpm wu:recover` | Analyze and fix WU state inconsistencies |
|
|
563
|
+
| `pnpm wu:verify` | Verify WU completion (stamp, commit, clean tree) |
|
|
564
|
+
| `pnpm wu:escalate` | Show or resolve WU escalation status |
|
|
565
|
+
| `pnpm wu:delete` | Delete WU spec and cleanup |
|
|
566
|
+
| `pnpm approval:request` | Request control-plane approval for a workflow action |
|
|
567
|
+
| `pnpm approval:review` | Resolve a control-plane approval decision |
|
|
568
|
+
| `pnpm approval:list` | List control-plane approvals with optional filters |
|
|
569
|
+
|
|
570
|
+
#### wu:edit ergonomics (WU-2940)
|
|
571
|
+
|
|
572
|
+
`pnpm wu:edit` accepts the full sizing-estimate surface — `--estimated-files`,
|
|
573
|
+
`--estimated-tool-calls`, `--sizing-strategy`, `--sizing-exception-type`,
|
|
574
|
+
`--sizing-exception-reason` — for mid-flight scope correction without a
|
|
575
|
+
wu:delete + wu:create dance. Each flag is independently editable; partial edits
|
|
576
|
+
merge into the existing `sizing_estimate` sub-object.
|
|
577
|
+
|
|
578
|
+
In-progress WUs accept non-destructive edits (`--description`, `--notes`, and
|
|
579
|
+
the five sizing flags above) **from the main checkout** via the micro-worktree
|
|
580
|
+
path. Other edits — `--lane`, `--code-paths` replace, `--priority`, `--type`,
|
|
581
|
+
`--initiative` — still require the existing `wu:release`/`wu:recover` dance
|
|
582
|
+
because they restructure scope.
|
|
583
|
+
|
|
584
|
+
#### wu:release branch reset (WU-2941)
|
|
585
|
+
|
|
586
|
+
`pnpm wu:release` now resets the **lane branch** alongside the WU YAML so
|
|
587
|
+
subsequent `pnpm wu:status` reports no main↔worktree drift. Default behaviour
|
|
588
|
+
is to delete the lane branch locally and on `origin`. Override with:
|
|
589
|
+
|
|
590
|
+
- `--keep-branch` flag — retain the branch for diagnostic recovery.
|
|
591
|
+
- `software_delivery.wu_release.branch_action` in `workspace.yaml` —
|
|
592
|
+
`'delete'` (default), `'rebase'` (hard-reset local ref to
|
|
593
|
+
`baseline_main_sha`, no remote push), or `'keep'` (no-op for
|
|
594
|
+
air-gapped/offline repos).
|
|
595
|
+
|
|
596
|
+
Cloud `claimed_mode: branch-pr` releases are unaffected; the claimed branch
|
|
597
|
+
is owned by the cloud lifecycle and never touched by `wu:release`.
|
|
598
|
+
|
|
599
|
+
`pnpm wu:status` surfaces residual main↔worktree drift inline as a
|
|
600
|
+
structured remediation hint (matching the `wu:done` preflight error format):
|
|
601
|
+
`WU-X: main shows ready, branch shows in_progress. Run pnpm wu:recover --id
|
|
602
|
+
WU-X --action reset to reconcile.`
|
|
603
|
+
|
|
604
|
+
#### Pre-WU memory artifacts (WU-2940)
|
|
605
|
+
|
|
606
|
+
`pnpm mem:create` accepts pre-WU artifacts: omit `--wu` to capture findings
|
|
607
|
+
produced before any WU exists (Pre-Phase Audits per the wu-sizing-guide §1.5).
|
|
608
|
+
The persisted record stores `wu_id` null/absent and remains discoverable via
|
|
609
|
+
tag-only `mem:context --tags <csv>` queries.
|
|
610
|
+
|
|
611
|
+
```bash
|
|
612
|
+
# Capture an orchestrator finding before claiming the next WU
|
|
613
|
+
pnpm mem:create --type discovery --tags pre-phase-audit \
|
|
614
|
+
--title 'INIT-XXX wave 1 needs review-audit exception in WU-YYY'
|
|
615
|
+
```
|
|
568
616
|
|
|
569
617
|
### WU Maintenance
|
|
570
618
|
|
|
@@ -614,9 +662,12 @@ pnpm wu:prep --id WU-XXX \
|
|
|
614
662
|
```
|
|
615
663
|
|
|
616
664
|
**Allow-list (skippable: true by default):** `migration-verify`,
|
|
617
|
-
`lane-health`, `tdd-diff-evidence`,
|
|
618
|
-
`build`, `integration-test`, `e2e-smoke
|
|
619
|
-
`
|
|
665
|
+
`lane-health`, `tdd-diff-evidence`, the WU-2927 opt-in local-prep gates
|
|
666
|
+
`build`, `integration-test`, `e2e-smoke`, the WU-2943 advisory heuristic
|
|
667
|
+
gates `test-over-deletion`, `monolithic-file-contention`, and the WU-2944
|
|
668
|
+
opt-in `prod-migration-drift` gate (CI-scheduled; auto-skips not-applicable
|
|
669
|
+
when `PROD_DATABASE_URL` is not configured). All other framework gates
|
|
670
|
+
default to `skippable: false` and require a per-repo override at
|
|
620
671
|
`software_delivery.gates.overrides.<gate_id>.skippable=true` to be skipped:
|
|
621
672
|
|
|
622
673
|
```bash
|
|
@@ -714,6 +765,71 @@ with `source: 'agent'`.
|
|
|
714
765
|
Backward-compat: omitting `local_prep` (the default) preserves today's
|
|
715
766
|
behaviour — none of the new gates is applicable, no new commands run.
|
|
716
767
|
|
|
768
|
+
#### Heuristic guard gates (WU-2943)
|
|
769
|
+
|
|
770
|
+
Two advisory gates ride the INIT-068 contract on every `wu:prep`. Both are
|
|
771
|
+
`skippable_default: true` and `prereq_strategy: 'auto-skip'`, surface their
|
|
772
|
+
findings via the `failed` `GateResult` state, and emit the standard six-state
|
|
773
|
+
legend (`✅ / ❌ / ⏭ / ⊘ / 🚫`). Each gate is per-repo configurable via
|
|
774
|
+
`software_delivery.gates.overrides.<gate_id>`.
|
|
775
|
+
|
|
776
|
+
| Gate | Driver | When applicable | When it fails |
|
|
777
|
+
| ---------------------------- | ---------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
778
|
+
| `test-over-deletion` | INIT-105 item 12 | wu:prep diff includes deleted `.test.ts` / `.test.tsx` | Any deleted test's `describe()` / `describe.each()` symbol is not present in the current WU's `code_paths`. Output lists each unrecognised symbol. |
|
|
779
|
+
| `monolithic-file-contention` | INIT-105 item 13 | Always (every `wu:prep`) | A file appears in 2+ active WUs' `code_paths` (statuses: `in_progress`, `ready`) and the current WU is one of the claimants. Output lists the file + claimant WUs + a re-laning hint. |
|
|
780
|
+
|
|
781
|
+
Both gates are advisory (`skippable_default: true`); intentional triggers can
|
|
782
|
+
be skipped with `--skip-gate test-over-deletion` / `--skip-gate
|
|
783
|
+
monolithic-file-contention` (with `--reason` and `--fix-wu` per WU-2925).
|
|
784
|
+
Repos that want either gate to BLOCK can flip the default:
|
|
785
|
+
|
|
786
|
+
```bash
|
|
787
|
+
pnpm config:set software_delivery.gates.overrides.test-over-deletion.skippable=false
|
|
788
|
+
pnpm config:set software_delivery.gates.overrides.monolithic-file-contention.skippable=false
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
Backward-compat: when the heuristic does not fire, both gates auto-skip
|
|
792
|
+
cleanly; existing `wu:prep` flows are unaffected.
|
|
793
|
+
|
|
794
|
+
#### prod-migration-drift gate (WU-2944)
|
|
795
|
+
|
|
796
|
+
Optional CI-scheduled gate (INIT-105 item 14). Compares the canonical
|
|
797
|
+
`migrations/` directory on main against the production database's applied
|
|
798
|
+
migrations and fails when drift exceeds a configurable threshold (default 5).
|
|
799
|
+
Driver: cloud INIT-105 — prod silently accumulated 7+ migrations of drift
|
|
800
|
+
before any human noticed; no automated detection caught it.
|
|
801
|
+
|
|
802
|
+
| Property | Value |
|
|
803
|
+
| --------------------- | ------------------------------------------------------------------------------------------------ |
|
|
804
|
+
| Gate name | `prod-migration-drift` |
|
|
805
|
+
| Allow-list status | `skippable: true` (advisory) |
|
|
806
|
+
| `prereq_strategy` | `auto-skip` |
|
|
807
|
+
| Default applicability | `not-applicable` until repo opts in via override (clean opt-out — most repos won't enable day 1) |
|
|
808
|
+
| Default threshold | `5` (drift > threshold ⇒ `failed`) |
|
|
809
|
+
|
|
810
|
+
Per-repo opt-in (set both keys; without `connection_string_env_var` the gate
|
|
811
|
+
auto-skips not-applicable):
|
|
812
|
+
|
|
813
|
+
```bash
|
|
814
|
+
pnpm config:set software_delivery.gates.overrides.prod-migration-drift.connection_string_env_var=PROD_DATABASE_URL
|
|
815
|
+
pnpm config:set software_delivery.gates.overrides.prod-migration-drift.threshold=5
|
|
816
|
+
# Optional: tighten to BLOCK on drift instead of advisory --skip-gate
|
|
817
|
+
pnpm config:set software_delivery.gates.overrides.prod-migration-drift.skippable=false
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
Local `wu:prep` impact: zero by default. The gate is registered in the
|
|
821
|
+
default registry alongside the WU-2943 heuristic gates, but
|
|
822
|
+
`checkApplicability` returns `not-applicable` for repos that have not set
|
|
823
|
+
`connection_string_env_var`, so it auto-skips cleanly. CI integration is
|
|
824
|
+
scheduled (e.g. daily) — never on every PR — because it requires prod
|
|
825
|
+
credentials and a reachable DB.
|
|
826
|
+
|
|
827
|
+
`@lumenflow/cli` ships without a Postgres driver dependency to keep the CLI
|
|
828
|
+
slim. The gate accepts a probe injection seam (`ctx.__prodDriftProbe`) used
|
|
829
|
+
by the scheduled CI workflow to query the prod DB's applied-migrations list;
|
|
830
|
+
when no probe is supplied (e.g. local `wu:prep`), the gate cleanly auto-skips
|
|
831
|
+
under `prereq_strategy: 'auto-skip'`.
|
|
832
|
+
|
|
717
833
|
### Lane Management
|
|
718
834
|
|
|
719
835
|
| Command | Description |
|
|
@@ -788,29 +904,63 @@ behaviour — none of the new gates is applicable, no new commands run.
|
|
|
788
904
|
| `pnpm agent:log-issue` | Log issue during agent session |
|
|
789
905
|
| `pnpm agent:issues-query` | Query GitHub issues for agent work |
|
|
790
906
|
|
|
791
|
-
**ADR-010 control-plane rule:** planning, handoff, execution, reconciliation, finish, and status are separate concerns. Prompt emission is not launch. Worker return is not WU completion. Reconcile live initiative truth against WU status, worktree / branch state, `wu:prep` / `wu:done` or `wu:cleanup`, stamps, and integrity evidence. `mem:inbox` remains the signal channel, not the whole execution ledger.
|
|
907
|
+
**ADR-010 control-plane rule:** planning, handoff, execution, reconciliation, finish, and status are separate concerns. Prompt emission is not launch. Worker return is not WU completion. Reconcile live initiative truth against WU status, worktree / branch state, `pnpm wu:prep` / `pnpm wu:done` or `pnpm wu:cleanup`, stamps, and integrity evidence. `mem:inbox` remains the signal channel, not the whole execution ledger.
|
|
908
|
+
|
|
909
|
+
#### Plan-time preflight (WU-2942)
|
|
910
|
+
|
|
911
|
+
`pnpm orchestrate:initiative` emits two preflight sections before agent dispatch so plan-time intelligence catches starvation that used to surface at claim time:
|
|
912
|
+
|
|
913
|
+
- **File-overlap preflight** — flags WU pairs (or N-tuples) inside a parallel-claimable wave that share a `code_paths` entry. `wu:claim` rejects overlap by default, so a wave with shared paths is silently serial. Resolution: serialize the WUs, split file ownership, or `--force-overlap` knowingly.
|
|
914
|
+
- **Lane-fit suggestions** — when N≥2 WUs in a wave share a lane whose `lock_policy` holds the lane lock (`all` or `active`), only one runs at a time. The advisor calls the same logic as `pnpm wu:infer-lane` and recommends a re-lane via `pnpm wu:edit --id <WU> --lane '<inferred>'` for the contended WUs.
|
|
915
|
+
|
|
916
|
+
Modes (set via `software_delivery.orchestrate.preflight` in `workspace.yaml`, default `advisory`):
|
|
917
|
+
|
|
918
|
+
- `advisory` — emit warnings and proceed.
|
|
919
|
+
- `strict` — emit warnings and exit non-zero (also enabled per-run with `--strict-preflight`).
|
|
920
|
+
- `off` — skip preflight scans entirely.
|
|
792
921
|
|
|
793
922
|
### Setup & Configuration
|
|
794
923
|
|
|
795
|
-
| Command | Description
|
|
796
|
-
| ------------------------------- |
|
|
797
|
-
| `pnpm setup` | Install deps and build CLI (first time)
|
|
798
|
-
| `pnpm lumenflow` | Initialize LumenFlow in a project
|
|
799
|
-
| `pnpm lumenflow:doctor` | Diagnose LumenFlow configuration
|
|
800
|
-
| `pnpm lumenflow:commands` | List all available CLI commands
|
|
801
|
-
| `pnpm lumenflow:release` | Run release workflow
|
|
802
|
-
| `pnpm distribution:preflight` | Audit consumer repos for npm-access flip readiness
|
|
803
|
-
| `pnpm lumenflow:docs-sync` | Refresh core docs, onboarding docs, and vendor assets
|
|
804
|
-
| `pnpm lumenflow:sync-templates` | Sync templates to project
|
|
805
|
-
| `pnpm lumenflow:upgrade` | Upgrade LumenFlow packages
|
|
806
|
-
| `pnpm lumenflow:integrate` | Generate enforcement hooks for client
|
|
807
|
-
| `pnpm lumenflow:disable` | Reversibly turn enforcement off (hooks become no-ops)
|
|
808
|
-
| `pnpm lumenflow:enable` | Re-enable enforcement after `lumenflow:disable`
|
|
809
|
-
| `pnpm lumenflow:uninstall` | Remove LumenFlow files (dry-run by default)
|
|
810
|
-
| `pnpm config:set` | Safely update workspace.yaml via micro-worktree
|
|
811
|
-
| `pnpm config:get` | Read a value from workspace.yaml
|
|
812
|
-
| `pnpm cloud:connect` | Connect workspace.yaml to cloud control plane
|
|
813
|
-
| `pnpm backlog:prune` | Clean stale backlog entries
|
|
924
|
+
| Command | Description |
|
|
925
|
+
| ------------------------------- | ------------------------------------------------------- |
|
|
926
|
+
| `pnpm setup` | Install deps and build CLI (first time) |
|
|
927
|
+
| `pnpm lumenflow` | Initialize LumenFlow in a project |
|
|
928
|
+
| `pnpm lumenflow:doctor` | Diagnose LumenFlow configuration |
|
|
929
|
+
| `pnpm lumenflow:commands` | List all available CLI commands |
|
|
930
|
+
| `pnpm lumenflow:release` | Run release workflow |
|
|
931
|
+
| `pnpm distribution:preflight` | Audit consumer repos for npm-access flip readiness |
|
|
932
|
+
| `pnpm lumenflow:docs-sync` | Refresh core docs, onboarding docs, and vendor assets |
|
|
933
|
+
| `pnpm lumenflow:sync-templates` | Sync templates to project |
|
|
934
|
+
| `pnpm lumenflow:upgrade` | Upgrade LumenFlow packages |
|
|
935
|
+
| `pnpm lumenflow:integrate` | Generate enforcement hooks for client |
|
|
936
|
+
| `pnpm lumenflow:disable` | Reversibly turn enforcement off (hooks become no-ops) |
|
|
937
|
+
| `pnpm lumenflow:enable` | Re-enable enforcement after `lumenflow:disable` |
|
|
938
|
+
| `pnpm lumenflow:uninstall` | Remove LumenFlow files (dry-run by default) |
|
|
939
|
+
| `pnpm config:set` | Safely update workspace.yaml via micro-worktree |
|
|
940
|
+
| `pnpm config:get` | Read a value from workspace.yaml |
|
|
941
|
+
| `pnpm cloud:connect` | Connect workspace.yaml to cloud control plane |
|
|
942
|
+
| `pnpm backlog:prune` | Clean stale backlog entries |
|
|
943
|
+
| `pnpm db:journal-recover` | Recover drizzle journal collisions (dry-run default) |
|
|
944
|
+
| `pnpm lumenflow:setup-prereqs` | Surface external prereqs (e.g. Supabase CLI) post-setup |
|
|
945
|
+
|
|
946
|
+
#### db:journal-recover (WU-2945)
|
|
947
|
+
|
|
948
|
+
When two drizzle snapshots share the same `prevId` (chain fork) or journal entries share an `idx`,
|
|
949
|
+
`pnpm db:journal-recover` detects the collision and offers a safe-resequence path. Default mode is
|
|
950
|
+
dry-run; pass `--confirm` to apply. Every actual rewrite emits an audit log under
|
|
951
|
+
`.lumenflow/db-recovery/<timestamp>.log`. Idempotent — re-running on a healthy chain is a no-op.
|
|
952
|
+
|
|
953
|
+
```bash
|
|
954
|
+
pnpm db:journal-recover # show plan
|
|
955
|
+
pnpm db:journal-recover --drizzle-dir packages/db/drizzle
|
|
956
|
+
pnpm db:journal-recover --confirm # apply, write audit log
|
|
957
|
+
```
|
|
958
|
+
|
|
959
|
+
#### Supabase CLI prerequisite (WU-2945)
|
|
960
|
+
|
|
961
|
+
`pnpm setup` now runs `lumenflow:setup-prereqs` at the end. When the project uses Supabase
|
|
962
|
+
(via `supabase/config.toml` or `@supabase/*` deps), it surfaces a reminder that the Supabase CLI
|
|
963
|
+
is required for `pnpm db:reset` and similar workflows. Non-blocking informational only.
|
|
814
964
|
|
|
815
965
|
### Metrics & Flow
|
|
816
966
|
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026 Hellmai Ltd
|
|
2
|
-
// SPDX-License-Identifier: LicenseRef-LumenFlow-Proprietary
|
|
3
|
-
|
|
4
|
-
export interface HeartbeatHealth {
|
|
5
|
-
busy?: boolean;
|
|
6
|
-
stalled?: boolean;
|
|
7
|
-
last_progress_at?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface HeartbeatAssignment {
|
|
11
|
-
wu_id: string;
|
|
12
|
-
action: 'claim' | 'continue' | 'abort';
|
|
13
|
-
hint?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface AgentHeartbeatInput {
|
|
17
|
-
workspace_id: string;
|
|
18
|
-
session_id: string;
|
|
19
|
-
agent_id?: string;
|
|
20
|
-
wu_id?: string;
|
|
21
|
-
health?: HeartbeatHealth;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface AgentHeartbeatResult {
|
|
25
|
-
status: 'ok';
|
|
26
|
-
server_time: string;
|
|
27
|
-
next_heartbeat_ms?: number;
|
|
28
|
-
assignment?: HeartbeatAssignment;
|
|
29
|
-
budget_remaining_usd?: number;
|
|
30
|
-
coalesced_signals?: number;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface AgentHeartbeatPort {
|
|
34
|
-
heartbeat(input: AgentHeartbeatInput): Promise<AgentHeartbeatResult>;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface HeartbeatManagerOptions {
|
|
38
|
-
maxAttempts?: number;
|
|
39
|
-
baseBackoffMs?: number;
|
|
40
|
-
maxBackoffMs?: number;
|
|
41
|
-
sleepFn?: (delayMs: number) => Promise<void>;
|
|
42
|
-
logger?: Pick<Console, 'warn'>;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const DEFAULT_MAX_ATTEMPTS = 3;
|
|
46
|
-
const DEFAULT_BASE_BACKOFF_MS = 500;
|
|
47
|
-
const DEFAULT_MAX_BACKOFF_MS = 30_000;
|
|
48
|
-
|
|
49
|
-
function defaultSleep(delayMs: number): Promise<void> {
|
|
50
|
-
return new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Enforces single-flight heartbeat execution and coalesces concurrent signals
|
|
55
|
-
* into one follow-up heartbeat, with retry/backoff on transient failures.
|
|
56
|
-
*/
|
|
57
|
-
export class HeartbeatManager {
|
|
58
|
-
private readonly maxAttempts: number;
|
|
59
|
-
private readonly baseBackoffMs: number;
|
|
60
|
-
private readonly maxBackoffMs: number;
|
|
61
|
-
private readonly sleepFn: (delayMs: number) => Promise<void>;
|
|
62
|
-
private readonly logger?: Pick<Console, 'warn'>;
|
|
63
|
-
|
|
64
|
-
private inFlight: Promise<AgentHeartbeatResult> | null = null;
|
|
65
|
-
private queuedInput: AgentHeartbeatInput | null = null;
|
|
66
|
-
private queuedSignals = 0;
|
|
67
|
-
private consecutiveFailures = 0;
|
|
68
|
-
|
|
69
|
-
public constructor(
|
|
70
|
-
private readonly port: AgentHeartbeatPort,
|
|
71
|
-
options: HeartbeatManagerOptions = {},
|
|
72
|
-
) {
|
|
73
|
-
this.maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
74
|
-
this.baseBackoffMs = options.baseBackoffMs ?? DEFAULT_BASE_BACKOFF_MS;
|
|
75
|
-
this.maxBackoffMs = options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
|
|
76
|
-
this.sleepFn = options.sleepFn ?? defaultSleep;
|
|
77
|
-
this.logger = options.logger;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
public async heartbeat(input: AgentHeartbeatInput): Promise<AgentHeartbeatResult> {
|
|
81
|
-
if (this.inFlight) {
|
|
82
|
-
this.queuedInput = input;
|
|
83
|
-
this.queuedSignals += 1;
|
|
84
|
-
return this.inFlight;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const request = this.drainQueue(input);
|
|
88
|
-
this.inFlight = request;
|
|
89
|
-
try {
|
|
90
|
-
return await request;
|
|
91
|
-
} finally {
|
|
92
|
-
this.inFlight = null;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
public getState(): {
|
|
97
|
-
inFlight: boolean;
|
|
98
|
-
queuedSignals: number;
|
|
99
|
-
consecutiveFailures: number;
|
|
100
|
-
} {
|
|
101
|
-
return {
|
|
102
|
-
inFlight: this.inFlight !== null,
|
|
103
|
-
queuedSignals: this.queuedSignals,
|
|
104
|
-
consecutiveFailures: this.consecutiveFailures,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
private async drainQueue(initialInput: AgentHeartbeatInput): Promise<AgentHeartbeatResult> {
|
|
109
|
-
let currentInput = initialInput;
|
|
110
|
-
let localCoalescedSignals = 0;
|
|
111
|
-
|
|
112
|
-
while (true) {
|
|
113
|
-
const result = await this.sendWithRetry(currentInput);
|
|
114
|
-
const queuedInput = this.queuedInput;
|
|
115
|
-
localCoalescedSignals += this.queuedSignals;
|
|
116
|
-
this.queuedInput = null;
|
|
117
|
-
this.queuedSignals = 0;
|
|
118
|
-
|
|
119
|
-
if (!queuedInput) {
|
|
120
|
-
const mergedCoalesced = (result.coalesced_signals ?? 0) + localCoalescedSignals;
|
|
121
|
-
if (mergedCoalesced > 0) {
|
|
122
|
-
return {
|
|
123
|
-
...result,
|
|
124
|
-
coalesced_signals: mergedCoalesced,
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
return result;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
currentInput = queuedInput;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
private async sendWithRetry(input: AgentHeartbeatInput): Promise<AgentHeartbeatResult> {
|
|
135
|
-
let attempt = 0;
|
|
136
|
-
|
|
137
|
-
while (true) {
|
|
138
|
-
try {
|
|
139
|
-
const result = await this.port.heartbeat(input);
|
|
140
|
-
this.consecutiveFailures = 0;
|
|
141
|
-
return result;
|
|
142
|
-
} catch (error) {
|
|
143
|
-
this.consecutiveFailures += 1;
|
|
144
|
-
attempt += 1;
|
|
145
|
-
|
|
146
|
-
if (attempt >= this.maxAttempts) {
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const delayMs = this.getBackoffDelayMs();
|
|
151
|
-
this.logger?.warn?.(
|
|
152
|
-
`[agent:heartbeat] attempt ${attempt} failed; retrying in ${delayMs}ms`,
|
|
153
|
-
);
|
|
154
|
-
await this.sleepFn(delayMs);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
private getBackoffDelayMs(): number {
|
|
160
|
-
const exponent = Math.max(0, this.consecutiveFailures - 1);
|
|
161
|
-
return Math.min(this.baseBackoffMs * 2 ** exponent, this.maxBackoffMs);
|
|
162
|
-
}
|
|
163
|
-
}
|