@signaltree/enterprise 13.1.0 → 13.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,364 @@
1
+ ---
2
+ name: signaltree-orchestrating-a-migration
3
+ description: Process playbook for an orchestrator agent driving one or more implementer subagents through a SignalTree adoption — NgRx Signal Store migration, classic NgRx / BehaviorSubject migration, or greenfield. Load when the work spans more than ~5 consumer files, when a single Coder/implementer subagent is likely to exhaust its context window, or when the user explicitly asks for a phased / supervised rollout. Skip for trivial single-file changes.
4
+ ---
5
+
6
+ # Orchestrating a SignalTree migration
7
+
8
+ A SignalTree migration of a real Angular app routinely exceeds the context budget of a single implementer subagent. The work has a natural seam — **build the tree foundation** vs. **migrate every consumer + spec** — and treating it as one task tends to fail in predictable ways:
9
+
10
+ - The implementer builds a clean foundation, runs out of context, and returns a truncated message with no commit and the legacy stores still present.
11
+ - The implementer rushes the consumer sweep to fit, leaves grep-misses, and the verifier fails in late stages.
12
+ - Skill friction is buried in a final wall-of-text report, surfaced too late to fix mid-flight.
13
+
14
+ The orchestrator's job is to **bound each phase to one implementer's context budget**, gate progression on the verifier, and capture skill friction as a first-class artifact. This file documents the playbook.
15
+
16
+ > **Read the matching mechanical-mapping guide first.** For `@ngrx/signals`, [`migration-from-ngrx-signals.md`](./migration-from-ngrx-signals.md); for classic `@ngrx/store` (actions/reducers/selectors/effects/`@ngrx/entity`), [`migration-from-ngrx-store.md`](./migration-from-ngrx-store.md). Those guides tell you what a "good" migration looks like; this file only covers _how to drive subagents through one_. For greenfield adoption or non-NgRx legacy, see Applicability below — the playbook still applies, but Phase 1 and Phase 5 need light adaptation.
17
+
18
+ ## Applicability
19
+
20
+ This playbook is **vendor-neutral** for everything except Phase 1 (survey greps) and Phase 5 (verifier script), which are NgRx-shaped by default. The five-phase loop, the Phase 2 audit, the Phase 3 foundation prompt, and the Phase 4 consumer rewrite rules apply equally to:
21
+
22
+ | Scenario | Phase 1 (Survey) | Phase 2–4 | Phase 5 (Verifier) |
23
+ | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
24
+ | **Migrating from `@ngrx/signals`** (default) | Use the greps below as-is | Apply unchanged | Use `verify-signaltree-migration.sh` as documented |
25
+ | **Migrating from classic `@ngrx/store`** (see [`migration-from-ngrx-store.md`](./migration-from-ngrx-store.md) for the mappings) | Adapt the greps to `createReducer\(` / `createEffect\(` / `createSelector\(` / `inject(Store)`; list reducers/effects as the "LEGACY STORES" rows | Apply unchanged — the audit questions and foundation layout are SignalTree design, not NgRx-specific | Run the verifier with repeatable `--package @ngrx/store --package @ngrx/effects …` so it asserts each NgRx package is gone |
26
+ | **Migrating from `BehaviorSubject` services or `@Injectable` state services** | Adapt the greps to your legacy pattern (e.g. `@Injectable.*State\|new BehaviorSubject\(`); list legacy services as the "LEGACY STORES" rows | Apply unchanged — the audit questions and foundation layout are SignalTree design, not NgRx-specific | Run `build && test && lint` directly, **or** invoke the verifier with `--allow-source-presence --allow-dep-presence` |
27
+ | **Greenfield adoption** (no legacy state lib at all) | Skip Phase 1; the catalog is just the planned domain list from your design notes | Apply unchanged | Run `build && test && lint` directly; skip the verifier script |
28
+
29
+ The Phase 2 audit (collection vs singleton, typed errors, cross-domain lifecycle, persistence, derived-tier ladder) is the most valuable part of this playbook for non-NgRx contexts — it forces the architectural decisions that determine whether a SignalTree adoption succeeds, regardless of where the state was living before.
30
+
31
+ ## When to use this playbook
32
+
33
+ Use it when **any** of these are true:
34
+
35
+ - ≥ 2 legacy stores need migrating in a single PR.
36
+ - ≥ 10 consumer files (components, resolvers, interceptors, guards, specs) import the legacy store(s).
37
+ - The legacy store(s) total > 300 LOC (state + methods + features).
38
+ - The codebase has a typed error model, banner/telemetry/refresh hazards (`withFeature`-style cross-cutting), or persistence — i.e. patterns 1–5 from the migration guide all apply.
39
+ - A previous one-shot subagent dispatch returned truncated output, no commit, or left files un-migrated.
40
+
41
+ Skip it for the [minimum-viable-migration](./migration-from-ngrx-signals.md#minimum-viable-migration-1-small-store) shape — one Coder dispatch handles those fine.
42
+
43
+ ## The five-phase loop
44
+
45
+ ```
46
+ ┌──────────────┐ ┌─────────────┐ ┌──────────────────┐ ┌────────────────┐ ┌───────────────────┐
47
+ │ 1. Survey │ → │ 2. Audit │ → │ 3. Foundation │ → │ 4. Consumers │ → │ 5. Gate + commit │
48
+ │ (read-only) │ │ (orch only) │ │ (Coder #1) │ │ + specs │ │ (orch runs │
49
+ │ Explore │ │ │ │ │ │ (Coder #2) │ │ verifier) │
50
+ └──────────────┘ └─────────────┘ └──────────────────┘ └────────────────┘ └───────────────────┘
51
+ ```
52
+
53
+ Each box maps to one tool call sequence on the orchestrator side. Phases 3 and 4 are the only places implementer subagents are dispatched.
54
+
55
+ ### Phase 1 — Survey (read-only, orchestrator owns)
56
+
57
+ Goal: produce a single artifact — the **migration catalog** — that phases 3 and 4 will consume verbatim.
58
+
59
+ Run these commands yourself (do not delegate). Capture the output verbatim into your scratch notes.
60
+
61
+ > The greps below assume `@ngrx/signals` is the legacy source. For other sources — classic `@ngrx/store`, `BehaviorSubject` services, `@Injectable` state services — adapt the patterns (e.g. `createReducer\(`, `new BehaviorSubject\(`, `@Injectable.*State`) but keep the catalog shape unchanged. For greenfield adoption, skip this phase entirely and use your domain design notes as the catalog input to phases 2–4.
62
+
63
+ ```bash
64
+ # 1. Locate every legacy store file.
65
+ grep -rln 'signalStore(' <app-src> --include='*.ts'
66
+
67
+ # 2. Locate every consumer (any file that injects or imports a legacy store).
68
+ grep -rln 'from.*\.store\|<LegacyStoreNames>' <app-src> --include='*.ts' \
69
+ | grep -v -- '\.store\.ts$\|\.store\.spec\.ts$'
70
+
71
+ # 3. Locate every spec that touches a legacy store.
72
+ grep -rln 'TestBed\|beforeEach\|describe' <app-src> --include='*.spec.ts' \
73
+ | xargs grep -ln '<LegacyStoreNames>' 2>/dev/null
74
+
75
+ # 4. Identify build/test/lint commands (project.json or package.json scripts).
76
+ cat <app-src>/../project.json 2>/dev/null | head -80
77
+ grep -E '"build"|"test"|"lint"|"@nx/' <package.json>
78
+
79
+ # 5. Identify any cross-cutting features (withFeature, withHooks, withProps).
80
+ grep -E 'withFeature|withHooks|withProps|withErrorBanners|withTelemetry|withRefreshHandling' <legacy-stores>
81
+ ```
82
+
83
+ Catalog template (fill in from output above):
84
+
85
+ ```text
86
+ SURVEY — <app-name> @ <commit-sha>
87
+ ==================================
88
+ APP_SRC: <path>
89
+ PACKAGE_JSON: <path>
90
+ BUILD: <command>
91
+ TEST: <command>
92
+ LINT: <command>
93
+ TEST_RUNNER: jest | vitest | karma
94
+
95
+ LEGACY STORES (N):
96
+ 1. <path> — <store-name> — <state-fields-summary> — features: <withFeature list or "none">
97
+ 2. ...
98
+
99
+ CONSUMERS (N): [non-spec files that inject any legacy store]
100
+ - <path> — uses <store-names>
101
+ - ...
102
+
103
+ SPECS (N):
104
+ - <path> — touches <store-names>
105
+ - ...
106
+
107
+ CROSS-CUTTING FEATURES IN USE:
108
+ - withErrorBanners: yes/no
109
+ - withTelemetryBaggage / withReduxDevtools: yes/no
110
+ - withRefreshHandling: yes/no
111
+ - withHooks (onInit/onDestroy): yes/no
112
+ - withProps (toObservable bridges): yes/no
113
+
114
+ PEER DEPS STILL PRESENT IN package.json:
115
+ - @ngrx/signals: yes/no
116
+ - @ngrx/signals/entities: yes/no
117
+ - @angular-architects/ngrx-toolkit (or similar derivatives): yes/no
118
+ ```
119
+
120
+ The catalog is the single source of truth for phases 3 and 4 — paste it into both implementer prompts.
121
+
122
+ ### Phase 2 — Audit (orchestrator only, no subagent)
123
+
124
+ Run the four-question [app-shape audit](./migration-from-ngrx-signals.md#app-shape-audit-run-before-picking-patterns) yourself against the catalog. Decide which patterns from the migration guide apply. Record the answers and the pattern selection in your scratch notes:
125
+
126
+ ```text
127
+ AUDIT
128
+ =====
129
+ Q1 (collection vs singleton): per-domain answer
130
+ Q2 (typed error model present): yes/no — file path if yes
131
+ Q3 (cross-domain lifecycle): yes/no — describe the action(s)
132
+ Q4 (persistence): yes/no — what + where
133
+ Q5 (computed organization): count derived signals per slice from the survey:
134
+ - total derived signals across the tree: N
135
+ - any cross-domain rollups (one computed reading from ≥ 2 slices)? yes/no
136
+ - any duplicated computed (same logic in ≥ 2 consumer files)? yes/no
137
+ → if N > ~15 OR cross-domain rollups OR duplicates: adopt the
138
+ five-tier ladder from patterns.md → "Recommended tier ladder".
139
+ → otherwise: keep computeds inline in state factories.
140
+
141
+ PATTERNS APPLYING:
142
+ - #1 entityMap state shape: <which domains>
143
+ - #2 derived tiers: <none | minimal-inline | full-ladder>
144
+ - #3 cross-domain Ops: yes/no — name(s)
145
+ - #4 persistence: yes/no
146
+ - #5 sync method support: yes/no
147
+
148
+ PATTERNS SKIPPED (and why):
149
+ - ...
150
+ ```
151
+
152
+ This artifact also goes into both implementer prompts — it tells the implementer which patterns to apply, which to skip, and why. It removes the implementer's main source of architectural drift.
153
+
154
+ ### Phase 3 — Foundation (Coder #1)
155
+
156
+ Bounded scope: build only the new `store/` directory and wire `provideAppTree()` in `app.config.ts`. Nothing else.
157
+
158
+ Implementer prompt skeleton:
159
+
160
+ ```text
161
+ ## Task
162
+ Build the SignalTree foundation only. Do NOT touch any consumer files.
163
+ Do NOT delete any legacy stores. Do NOT migrate any specs.
164
+
165
+ ## Working directory
166
+ <absolute path to worktree> (branch <name>)
167
+
168
+ ## Required reading (read in full before editing)
169
+ 1. SKILL.md
170
+ 2. reference/migration-from-ngrx-signals.md
171
+ 3. reference/patterns.md
172
+ 4. reference/testing.md
173
+ 5. reference/core.md (leaf vs branch rules)
174
+
175
+ ## Survey + audit (paste verbatim from orchestrator)
176
+ <paste Phase 1 catalog>
177
+ <paste Phase 2 audit>
178
+
179
+ ## Bounded scope — create these files only
180
+ - store/tree/app-tree.ts — exports createBaseState, createAppTree, APP_TREE, provideAppTree
181
+ - store/tree/app-tree.testing.ts — exports provideAppTreeForTesting
182
+ - store/tree/state/<domain>.state.ts (one per domain)
183
+ - store/tree/derived/tier-*.derived.ts (ONLY if Phase 2 audit Q5 selected `full-ladder`; one file per tier)
184
+ - store/ops/<domain>.ops.ts (one per domain)
185
+ - store/app-store.ts — single AppStore facade
186
+ - store/index.ts — public surface
187
+
188
+ If the audit selected `full-ladder` for derived tiers, follow patterns.md → "Recommended tier ladder for large apps". Do NOT invent your own tier names; use the validated five-tier ladder (entity-resolution → complex-logic → workflow → navigation → ui-aggregates) and only build the tiers your audited signal count justifies.
189
+
190
+ Plus exactly one edit:
191
+ - app.config.ts — add provideAppTree() to providers
192
+
193
+ ## Hard rules
194
+ - No consumer files modified.
195
+ - No legacy stores deleted.
196
+ - No specs touched.
197
+ - @signaltree/core MUST be added to package.json (correct workspace flags).
198
+ - Run `pnpm install` after editing package.json.
199
+ - TypeScript MUST compile (run `tsc --noEmit` or the project's typecheck).
200
+ - No commit yet — orchestrator will inspect before phase 4.
201
+
202
+ ## Final report
203
+ - Files created (paths only).
204
+ - App-shape audit answers (confirm orchestrator's audit or flag disagreement).
205
+ - Skill friction encountered (specific quotes from skill text where possible).
206
+ - Any architectural decisions you made that the orchestrator's audit didn't cover.
207
+ ```
208
+
209
+ After Coder #1 returns, the orchestrator inspects the worktree itself:
210
+
211
+ ```bash
212
+ # Foundation present?
213
+ ls <app-src>/store/tree/ <app-src>/store/ops/
214
+
215
+ # AppStore wires what the audit said it should?
216
+ cat <app-src>/store/app-store.ts
217
+
218
+ # package.json + lockfile updated?
219
+ grep '@signaltree/core' <package.json>
220
+ ```
221
+
222
+ If the foundation is wrong, **patch it yourself** rather than re-dispatching — small fixes are cheaper than another full subagent round.
223
+
224
+ ### Phase 4 — Consumers + specs (Coder #2)
225
+
226
+ Bounded scope: migrate every file in the survey catalog's CONSUMERS and SPECS lists; delete the legacy stores; do not modify the foundation.
227
+
228
+ Implementer prompt skeleton:
229
+
230
+ ```text
231
+ ## Task
232
+ Finish a SignalTree migration. The foundation is already in place. Migrate
233
+ every consumer and spec listed below, delete the legacy stores, run the
234
+ verifier, commit only when green.
235
+
236
+ ## Working directory
237
+ <absolute path to worktree> (branch <name>)
238
+
239
+ ## Foundation already in place
240
+ - store/tree/app-tree.ts (createBaseState + createAppTree + APP_TREE)
241
+ - store/tree/app-tree.testing.ts (provideAppTreeForTesting)
242
+ - store/app-store.ts (AppStore facade with: <list orchestration methods>)
243
+ - store/ops/{<domain>}.ops.ts
244
+ - @signaltree/core already in package.json
245
+ - provideAppTree() already wired in app.config.ts
246
+
247
+ ## Survey + audit (paste verbatim from orchestrator)
248
+ <paste Phase 1 catalog>
249
+ <paste Phase 2 audit>
250
+
251
+ ## Required reading
252
+ - reference/migration-from-ngrx-signals.md (consumer rewrite section)
253
+ - reference/testing.md (especially the Nullable<Object> leaf gotcha)
254
+ - reference/patterns.md (consumer rules)
255
+
256
+ ## Bounded scope
257
+ For each file in CONSUMERS:
258
+ - Replace inject(<LegacyStore>) with inject(AppStore).
259
+ - Replace store.field() with appStore.$.<domain>.<field>().
260
+ - Replace store.method() with appStore.ops.<domain>.<method>() (or appStore.<orchestrator>() if cross-domain).
261
+
262
+ For each file in SPECS:
263
+ - Add provideAppTreeForTesting() to providers.
264
+ - For Nullable<Object> leaves, seed via post-injection .set() — NOT the overrides callback.
265
+ - Mock Ops via { provide: <DomainOps>, useValue: { <method>: jest.fn() } } where appropriate.
266
+
267
+ Delete every file in LEGACY STORES.
268
+
269
+ ## Verifier (must exit 0)
270
+ <paste verbatim verifier command from Phase 5 below>
271
+
272
+ ## Hard rules
273
+ - Do NOT modify any file in store/ unless adding a missing Ops method that
274
+ the audit overlooked. If you do, call it out in your report.
275
+ - Do NOT weaken --allow-* flags on the verifier.
276
+ - Do NOT push.
277
+ - Pre-existing lint warnings are OK; new lint errors are not.
278
+ - If a pre-existing spec was already broken at the base commit, surface it
279
+ but do not let it block the commit; minimal-rebaseline is acceptable
280
+ if the orchestrator pre-approves it. If it surprises you, ASK first.
281
+
282
+ ## Commit
283
+ git add -A && git commit --no-verify -m "<msg>"
284
+
285
+ ## Final report
286
+ - Files modified (with rough line counts).
287
+ - Files deleted (confirm each legacy path).
288
+ - Verifier exit code + last 30 lines of output.
289
+ - Build / test / lint counts (errors and warnings separately).
290
+ - Commit SHA.
291
+ - Skill friction log — every place the skill was ambiguous, missing, or
292
+ actively wrong; quote skill text where possible. THIS IS THE MOST
293
+ VALUABLE SECTION FOR THE USER.
294
+ - Architectural self-check verdict (5-item checklist).
295
+ ```
296
+
297
+ ### Phase 5 — Gate + commit (orchestrator owns)
298
+
299
+ The orchestrator runs the verifier itself **once more** after Coder #2 returns, regardless of what Coder #2 reported. Trust but verify.
300
+
301
+ > For non-NgRx scenarios (other legacy state libs, or greenfield adoption), the `verify-signaltree-migration.sh` script's `@ngrx/signals` assertions don't apply. Either run `build && test && lint` directly as the gate, or invoke the verifier with `--allow-source-presence --allow-dep-presence` so it skips the NgRx checks but still runs the full build/test/lint sequence.
302
+
303
+ ```bash
304
+ cd <worktree>
305
+ PATH="/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:$HOME/.nvm/versions/node/v22.17.0/bin" \
306
+ NX_DAEMON=false CI=true COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
307
+ <path-to-signaltree>/scripts/verify-signaltree-migration.sh \
308
+ --src <app-src>/store \
309
+ --build "<build-cmd>" \
310
+ --test "<test-cmd>" \
311
+ --lint "<lint-cmd>" \
312
+ --package-json <package-json> \
313
+ --allow-source-presence --allow-dep-presence
314
+ ```
315
+
316
+ If exit code is non-zero, dispatch a third Coder with **just** the verifier output as the failure context — do not re-paste the full survey.
317
+
318
+ If exit code is 0, surface to the user:
319
+
320
+ 1. Verifier exit code + commit SHA.
321
+ 2. Skill friction items extracted from Coder #1 + Coder #2 reports, deduplicated.
322
+ 3. Architectural self-check verdict.
323
+ 4. Outstanding decisions for the user (push? cleanup worktree? open follow-up issue for friction items?).
324
+
325
+ ## Hand-off rules between phases
326
+
327
+ These rules eliminate the most common orchestration failures observed across runs:
328
+
329
+ | Rule | Why |
330
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
331
+ | Each implementer prompt MUST include the full Phase 1 catalog and Phase 2 audit. | Implementers re-deriving these facts wastes context and produces drift. |
332
+ | The orchestrator NEVER edits files itself during phases 3–4 unless a fix is < 10 LOC. | Mixing orchestrator edits with implementer edits creates merge confusion in the report. |
333
+ | The verifier is run by the orchestrator, not the implementer, for the final gate. | Implementer reports cannot be trusted as the gate — they paraphrase output. |
334
+ | Skill friction is collected as a separate report section, never folded into the diffstat narrative. | Friction items get lost in long reports; a dedicated section is the only reliable harvest. |
335
+ | If Coder #2 reports that a pre-existing spec was rewritten without prior orchestrator approval, treat that as a friction item against this playbook (not a code defect). | Silent rebaselines defeat the audit trail. |
336
+
337
+ ## Failure modes and recoveries
338
+
339
+ | Symptom | Cause | Recovery |
340
+ | ------------------------------------------------------------------ | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
341
+ | Coder #1 returns no/truncated output | Context exhausted on a too-broad scope | Inspect worktree state with `ls` + `git status`; if foundation is partially built, patch it yourself; if not, re-dispatch with a stricter scope (only `app-tree.ts` + `app-tree.testing.ts` first). |
342
+ | Coder #2 commits but verifier fails on second run | Implementer mis-paraphrased the verifier result | Re-dispatch with verifier failure log as the only context; do not re-include the survey. |
343
+ | Implementer adds Ops methods that orchestrator's audit didn't list | Audit missed a required method | Accept the addition; update the audit notes; pass to next phase. |
344
+ | Pre-existing tests broken at base commit | Branch not clean before the migration | Confirm with `git stash && <test-cmd>` against the base commit; if confirmed pre-existing, mark in friction log; do NOT block commit on it. |
345
+ | Verifier `--allow-dep-presence` masks an unremoved package | Sibling apps still reference the legacy package | Open a follow-up tracking issue; do NOT remove the dep until all siblings migrate. |
346
+
347
+ ## What this playbook is NOT
348
+
349
+ - **Not a replacement for the migration guide.** It tells you _how to drive_ a migration; the migration guide tells you _what a migration is_.
350
+ - **Not a code-generation tool.** Each implementer subagent still does the work; the orchestrator only bounds, gates, and harvests.
351
+ - **Not appropriate for trivial migrations.** A one-store, < 5-signal app should use the [minimum viable](./migration-from-ngrx-signals.md#minimum-viable-migration-1-small-store) recipe in a single dispatch.
352
+
353
+ ## Checklist for the orchestrator
354
+
355
+ Before declaring a phased migration done:
356
+
357
+ 1. ✅ Phase 1 survey artifact captured verbatim.
358
+ 2. ✅ Phase 2 audit explicitly maps each legacy store to a pattern selection (with skips justified).
359
+ 3. ✅ Phase 3 implementer prompt included the catalog + audit and bounded scope to the foundation.
360
+ 4. ✅ Foundation inspected by the orchestrator before phase 4 dispatched.
361
+ 5. ✅ Phase 4 implementer prompt included the catalog + audit + foundation summary + verifier command.
362
+ 6. ✅ Verifier re-run by the orchestrator after the commit (independent of Coder #2's report).
363
+ 7. ✅ Skill friction items deduplicated across both implementer reports and surfaced separately to the user.
364
+ 8. ✅ Outstanding decisions (push, cleanup, follow-up issues) presented to the user; nothing pushed without explicit approval.