create-claude-cabinet 0.46.0 → 0.47.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.
Files changed (139) hide show
  1. package/README.md +2 -6
  2. package/lib/cli.js +348 -91
  3. package/lib/copy.js +108 -6
  4. package/lib/db-setup.js +122 -17
  5. package/lib/metadata.js +51 -2
  6. package/lib/settings-merge.js +52 -10
  7. package/lib/watchtower-setup.js +22 -2
  8. package/package.json +1 -1
  9. package/templates/cabinet/advisories-state-schema.md +1 -1
  10. package/templates/cabinet/checklist-stats-schema.md +15 -1
  11. package/templates/cabinet/memory-lifecycle-contract.md +135 -0
  12. package/templates/cabinet/pib-db-access.md +13 -0
  13. package/templates/cabinet/watchtower-contracts.md +414 -0
  14. package/templates/cabinet/worktree-invocation-contract.md +87 -0
  15. package/templates/engagement/OVERVIEW.md +12 -0
  16. package/templates/engagement/__tests__/engagement.test.mjs +177 -2
  17. package/templates/engagement/__tests__/invoice-doc.test.mjs +195 -0
  18. package/templates/engagement/engagement-preview.mjs +100 -0
  19. package/templates/engagement/engagement-schema.md +240 -0
  20. package/templates/engagement/engagement.mjs +391 -11
  21. package/templates/engagement/pib-db-patches/pib-db-mcp-server.mjs +5 -44
  22. package/templates/engagement/pib-db-patches/pib-db.mjs +5 -2
  23. package/templates/hooks/action-completion-gate.sh +9 -3
  24. package/templates/hooks/memory-index-guard.sh +17 -11
  25. package/templates/hooks/watchtower-session-start.sh +24 -2
  26. package/templates/mcp/pib-db.json +1 -4
  27. package/templates/mux/bin/mux +8 -1
  28. package/templates/mux/config/help.txt +1 -0
  29. package/templates/rules/acknowledge-when-corrected.md +33 -0
  30. package/templates/rules/maintainability.md +11 -0
  31. package/templates/rules/memory-capture.md +26 -4
  32. package/templates/rules/plan-before-bulk-or-irreversible-actions.md +48 -0
  33. package/templates/rules/verify-before-asserting.md +79 -0
  34. package/templates/scripts/__tests__/ahead-check-origin.test.mjs +355 -0
  35. package/templates/scripts/__tests__/batch-disposition.test.mjs +98 -0
  36. package/templates/scripts/__tests__/claude-churn-authored.test.mjs +90 -0
  37. package/templates/scripts/__tests__/cross-ring-reader.test.mjs +505 -0
  38. package/templates/scripts/__tests__/dx-captures-briefing.test.mjs +169 -0
  39. package/templates/scripts/__tests__/hook-runner.test.mjs +247 -0
  40. package/templates/scripts/__tests__/narrative-corpus.test.mjs +247 -0
  41. package/templates/scripts/__tests__/phase-shim.test.mjs +112 -0
  42. package/templates/scripts/__tests__/qa-handoff-merge-state.test.mjs +162 -0
  43. package/templates/scripts/__tests__/resolve-cli.test.mjs +314 -0
  44. package/templates/scripts/__tests__/ring-state-ownership.test.mjs +120 -0
  45. package/templates/scripts/__tests__/ring1-content-detector.test.mjs +168 -0
  46. package/templates/scripts/__tests__/ring1-flagged-actions.test.mjs +135 -0
  47. package/templates/scripts/__tests__/ring1-script-drift.test.mjs +126 -0
  48. package/templates/scripts/__tests__/ring2-queue-reader.test.mjs +80 -0
  49. package/templates/scripts/__tests__/ring2-recall-canary.test.mjs +150 -0
  50. package/templates/scripts/__tests__/ring2-roster-review.test.mjs +311 -0
  51. package/templates/scripts/__tests__/ring3-chunk-merge.test.mjs +122 -0
  52. package/templates/scripts/__tests__/ring3-close-lenses.test.mjs +359 -0
  53. package/templates/scripts/__tests__/ring3-dedup.test.mjs +92 -12
  54. package/templates/scripts/__tests__/ring3-memory-titles.test.mjs +187 -0
  55. package/templates/scripts/__tests__/ring3-novelty-rescue.test.mjs +148 -0
  56. package/templates/scripts/__tests__/ring3-recent-slice.test.mjs +101 -0
  57. package/templates/scripts/__tests__/ring4-reconcile.test.mjs +393 -0
  58. package/templates/scripts/__tests__/shared-thread-reader.test.mjs +187 -0
  59. package/templates/scripts/__tests__/suppression-ledger.test.mjs +148 -0
  60. package/templates/scripts/__tests__/verify-backfill.test.mjs +103 -0
  61. package/templates/scripts/__tests__/verify-coverage.test.mjs +80 -0
  62. package/templates/scripts/__tests__/watchtower-snapshot.test.mjs +261 -0
  63. package/templates/scripts/__tests__/watchtower-sync.test.mjs +311 -0
  64. package/templates/scripts/load-triage-history.js +5 -2
  65. package/templates/scripts/pib-db-mcp-server.mjs +5 -44
  66. package/templates/scripts/pib-db-path.mjs +61 -0
  67. package/templates/scripts/pib-db.mjs +5 -2
  68. package/templates/scripts/validate-memory.mjs +214 -16
  69. package/templates/scripts/watchtower-advisories.mjs +7 -3
  70. package/templates/scripts/watchtower-build-context.mjs +192 -8
  71. package/templates/scripts/watchtower-cross-ring-reader.mjs +700 -0
  72. package/templates/scripts/watchtower-hook-runner.mjs +422 -0
  73. package/templates/scripts/watchtower-lib.mjs +273 -4
  74. package/templates/scripts/watchtower-narrative-corpus.mjs +385 -0
  75. package/templates/scripts/watchtower-phase-shim.mjs +171 -0
  76. package/templates/scripts/watchtower-queue.mjs +341 -3
  77. package/templates/scripts/watchtower-ring1.mjs +405 -45
  78. package/templates/scripts/watchtower-ring2.mjs +710 -68
  79. package/templates/scripts/watchtower-ring3-close.mjs +988 -147
  80. package/templates/scripts/watchtower-ring4-runner.sh +85 -0
  81. package/templates/scripts/watchtower-ring4.mjs +753 -0
  82. package/templates/scripts/watchtower-routines.mjs +1 -1
  83. package/templates/scripts/watchtower-snapshot.mjs +452 -0
  84. package/templates/scripts/watchtower-sync.mjs +393 -0
  85. package/templates/skills/briefing/SKILL.md +281 -41
  86. package/templates/skills/cabinet-process-therapist/SKILL.md +28 -0
  87. package/templates/skills/cabinet-security/SKILL.md +11 -0
  88. package/templates/skills/catch-up/SKILL.md +113 -0
  89. package/templates/skills/cc-publish/SKILL.md +53 -16
  90. package/templates/skills/cc-remember/SKILL.md +45 -0
  91. package/templates/skills/close/SKILL.md +107 -0
  92. package/templates/skills/collab-client/SKILL.md +22 -5
  93. package/templates/skills/collab-consultant/SKILL.md +110 -2
  94. package/templates/skills/debrief/SKILL.md +21 -4
  95. package/templates/skills/debrief-classic/SKILL.md +696 -0
  96. package/templates/skills/debrief-classic/calibration.md +44 -0
  97. package/templates/skills/debrief-classic/phases/audit-pattern-capture.md +78 -0
  98. package/templates/skills/debrief-classic/phases/auto-maintenance.md +48 -0
  99. package/templates/skills/debrief-classic/phases/checklist-feedback.md +123 -0
  100. package/templates/skills/debrief-classic/phases/close-work.md +163 -0
  101. package/templates/skills/debrief-classic/phases/health-checks.md +54 -0
  102. package/templates/skills/debrief-classic/phases/inventory.md +40 -0
  103. package/templates/skills/debrief-classic/phases/loose-ends.md +52 -0
  104. package/templates/skills/debrief-classic/phases/methodology-capture.md +223 -0
  105. package/templates/skills/debrief-classic/phases/qa-handoff-sweep.md +78 -0
  106. package/templates/skills/debrief-classic/phases/record-lessons.md +177 -0
  107. package/templates/skills/debrief-classic/phases/report.md +59 -0
  108. package/templates/skills/debrief-classic/phases/update-state.md +48 -0
  109. package/templates/skills/debrief-classic/phases/upstream-feedback.md +185 -0
  110. package/templates/skills/debrief-classic/phases/verify-coverage.md +101 -0
  111. package/templates/skills/execute/SKILL.md +71 -6
  112. package/templates/skills/execute/phases/commit-and-deploy.md +8 -0
  113. package/templates/skills/execute-group/SKILL.md +23 -26
  114. package/templates/skills/generate-plan-groups/SKILL.md +20 -0
  115. package/templates/skills/inbox/SKILL.md +84 -28
  116. package/templates/skills/memory/SKILL.md +22 -6
  117. package/templates/skills/orient/SKILL.md +71 -5
  118. package/templates/skills/orient-classic/SKILL.md +770 -0
  119. package/templates/skills/orient-classic/phases/auto-maintenance.md +52 -0
  120. package/templates/skills/orient-classic/phases/briefing.md +53 -0
  121. package/templates/skills/orient-classic/phases/cabinet.md +46 -0
  122. package/templates/skills/orient-classic/phases/checklist-status.md +54 -0
  123. package/templates/skills/orient-classic/phases/context.md +88 -0
  124. package/templates/skills/orient-classic/phases/data-sync.md +35 -0
  125. package/templates/skills/orient-classic/phases/deferred-check.md +55 -0
  126. package/templates/skills/orient-classic/phases/dx-captures.md +53 -0
  127. package/templates/skills/orient-classic/phases/health-checks.md +50 -0
  128. package/templates/skills/orient-classic/phases/verify-backfill.md +109 -0
  129. package/templates/skills/orient-classic/phases/work-scan.md +69 -0
  130. package/templates/skills/qa-drain/SKILL.md +38 -0
  131. package/templates/skills/qa-handoff/SKILL.md +287 -46
  132. package/templates/skills/setup-accounts/SKILL.md +38 -16
  133. package/templates/skills/threads/SKILL.md +4 -0
  134. package/templates/skills/validate/phases/validators.md +41 -0
  135. package/templates/skills/watchtower/SKILL.md +160 -8
  136. package/templates/verify-runtime/CONVENTIONS.md +9 -0
  137. package/templates/verify-runtime/README.md +37 -0
  138. package/templates/watchtower/config.json.template +8 -2
  139. package/templates/workflows/execute-group-complete.js +10 -1
@@ -238,9 +238,15 @@ billing:
238
238
  currency: USD
239
239
  period: since-last-sync # engagement | month | since-last-sync
240
240
 
241
+ invoicing: # optional — see §8.1
242
+ mode: consolidated # consolidated | itemized
243
+ scope_label: "Consulting services"
244
+ terms_days: 30
245
+
241
246
  recipients:
242
247
  - id: ed
243
248
  name: "Ed Maginnis"
249
+ org: "Maginnis Howard" # optional — shown in the invoice bill-to
244
250
  email: "ed@example.com"
245
251
  role: principal
246
252
  scopes: [all]
@@ -337,6 +343,186 @@ checklist_summary # [ { type, count } ] when config has sections
337
343
 
338
344
  ---
339
345
 
346
+ ## 5.1. Decision items — the structured options & decision-type contract
347
+
348
+ The single shared contract that the engine synthesis (`renderPacket`),
349
+ the fail-closed validator (`assertPacketInvariants`), the client
350
+ renderer (`/collab-client`), and the consultant inbox
351
+ (`/collab-consultant`) all conform to. P1.1–P1.4 of the engagement
352
+ upstream-fix program depend on this — pin it here, build to it.
353
+
354
+ ### Where a decision is authored (once)
355
+
356
+ A decision is authored exactly once, in `engagement.yaml`, as a `decide`
357
+ item inside a `sections[]` block:
358
+
359
+ ```yaml
360
+ sections:
361
+ - key: go_live
362
+ items:
363
+ - key: arbitration_forum_model
364
+ kind: decide
365
+ tier: recommended # optional priority hint (free text)
366
+ audience: [ed] # optional; default = all principals
367
+ prompt: "Which forum model…" # the question → client_title / title
368
+ help: "Tracking per-company…" # the explanation → client_body / why
369
+ tradeoff: "Per-company is…" # optional; appended to `why`
370
+ options: # omit / empty ⇒ free-text decision
371
+ - "A — forum per company, with an analysis notes field"
372
+ - value: "B — one forum per theory"
373
+ label: "One forum per theory"
374
+ free_text: false # optional; forces a free-text answer
375
+ ```
376
+
377
+ `engagement.yaml` stays the **authoritative authoring source** for
378
+ decisions (Non-Goal: dropping it). The engine derives everything below
379
+ from it.
380
+
381
+ ### The engine internalizes the projection (P1.1)
382
+
383
+ `renderPacket`, given the parsed config, **ensures a backing decision
384
+ per `decide` item and renders it into `needs_you` exactly as it renders
385
+ a `needs:decision` action** — preserving the `ref` / `refmap` /
386
+ `client_feedback` spine. The pure engine synthesizes the backing item
387
+ **in-memory** from the yaml (it imports nothing — no DB, no fs); a
388
+ pib-db row is materialized separately by `ensureDecisionActions` (below).
389
+
390
+ - **Deterministic backing fid.** Each decide item gets a stable fid
391
+ `decisionFid(engagementSlug, sectionKey, itemKey)` → `act:<8 hex>`
392
+ (FNV-1a). Deterministic so the `ref` is stable across renders
393
+ (`new_since_last` stays a reliable diff) and so an inbound answer's
394
+ `target_fid` always resolves to the same decision — even across a
395
+ re-render (the cross-render gate). It **must satisfy the pib-db
396
+ `FID_PATTERN` (`act:<8 lowercase hex>`)** so the answer's `target_fid`
397
+ passes `addEngagementEvent`'s `validateFid` — the production ingest
398
+ path the loop test's in-memory refmap never exercises (so the loop
399
+ test alone would not catch a malformed fid; this is why the scheme is
400
+ fixed at design time, not later). A collision with a real
401
+ pib-db-generated fid is ~1e-6 and is hard-guarded in the synthesis (an
402
+ unrelated live-fid match throws loudly rather than mis-attributing the
403
+ answer).
404
+ - **Same spine as an action.** `ref = stableRef(fid)`,
405
+ `refmap[ref] = fid`. The client answers `context_ref: <ref>`; the
406
+ consultant inbox resolves `ref → fid` and writes `client_feedback`
407
+ with `target_fid = fid`. A yaml section rendered *raw* (no fid) would
408
+ break this — hence synthesis, not raw rendering (loop-test step D).
409
+ - **No row required to render or round-trip.** `target_fid` has no FK,
410
+ so the answer stores even if no pib-db row exists. The row exists so
411
+ the consultant can *apply* the answer against a real action — see
412
+ `ensureDecisionActions`.
413
+
414
+ ### Structural dedup (invariant #3)
415
+
416
+ The engine must **never** emit a decision twice — once natively from the
417
+ yaml and once from a surviving projected action. A backing/projected
418
+ action declares which decide item it covers via an
419
+ `engagement_key: <itemKey>` marker on its own line in `notes`. When
420
+ synthesizing, the engine **skips any decide item whose key appears in
421
+ the `engagement_key` marker of a live, visible `needs:decision`
422
+ action** — that action renders it instead. The marker is the single
423
+ dedup key, shared by the engine synthesis and `ensureDecisionActions`.
424
+ After the Phase-2 cutover (projected actions tag-neutralized), every
425
+ decide item renders natively.
426
+
427
+ ### The packet decision item (the structured shape — P1.2)
428
+
429
+ Every decision `needs_you` item carries the fields below. **Note the
430
+ `kind` value is `'decision'`, not `'needs:decision'`** — `parseActionTags`
431
+ strips the `needs:` prefix, so the rendered item's `kind` is the
432
+ post-colon token (`'decision'` / `'credential'`). The TAG is
433
+ `needs:decision`; the item FIELD is `kind: 'decision'`.
434
+
435
+ | Field | Type | Meaning |
436
+ | ----- | ---- | ------- |
437
+ | `ref` | string | opaque stable ref (`refmap` resolves it to the fid) |
438
+ | `title` | string | the question (`prompt` / `client_title`) |
439
+ | `why` | string | the explanation (`help` / `client_body`, + `tradeoff`) |
440
+ | `kind` | `'decision'` | the needs token (the `needs:` prefix is stripped) |
441
+ | `decision_type` | `'choice'` \| `'free_text'` | how it is answered |
442
+ | `options` | `Array<{ value: string, label?: string }>` | the choices |
443
+
444
+ - **`options` is an array of objects, never a comma-joined string.** The
445
+ `value` is the canonical, **comma-safe** answer text, round-tripped
446
+ verbatim — there is no `split(',')` on a value anywhere. `label` is an
447
+ optional short display string (defaults to `value`). This retires the
448
+ lossy `Options: A, B, C` line: a value that itself contains a comma
449
+ survives intact.
450
+ - **Normalization.** A yaml option given as a bare string `"X"`
451
+ normalizes to `{ value: "X", label: "X" }`. An object option passes
452
+ through; a missing `label` defaults to `value`. Whitespace-only / empty
453
+ values are dropped.
454
+ - **`decision_type: 'free_text'`** — an open-ended written answer. Set
455
+ when the decide item declares `free_text: true` OR has no `options`.
456
+ `options` is `[]`. The client collects free text instead of choices.
457
+ - **`decision_type: 'choice'`** — pick from `options` (≥2 required).
458
+
459
+ ### Fail-closed (P1.2)
460
+
461
+ `assertPacketInvariants` **throws** on any answerable `needs_you` item
462
+ (`kind === 'decision'` carrying a `ref`) with `decision_type === 'choice'`
463
+ and `options.length < 2`. An unanswerable choice decision can never ship —
464
+ the failure is loud at render time, not a confusing empty dialog for the
465
+ client. The gate is whole-packet (consistent with the leak gate): a
466
+ misconfigured decision holds the entire packet until fixed. Free-text
467
+ decisions legitimately carry zero options and are exempt. Display-only
468
+ roll-ups (`feedbackable: false`, no `ref`) are exempt. A real (projected)
469
+ action with exactly 1 option also trips this — fix by adding a second
470
+ option or dropping the `needs:decision` tag (an action author has no
471
+ `free_text` field).
472
+
473
+ ### Two stability caveats
474
+
475
+ - **Decide keys must be unique across sections.** Dedup (and the legacy
476
+ workaround) match a projected action's `engagement_key: <key>` marker —
477
+ which carries no section — against a yaml decide key. If the same key
478
+ appears in two sections and one projected action covers it, both
479
+ sections' synthesis is suppressed and only one renders. Keep decide
480
+ keys unique within an engagement.
481
+ - **A section/slug rename re-keys the ref.** The cross-render ref
482
+ stability holds only while `engagement.slug`, the section key, and the
483
+ item key are all unchanged (they seed `decisionFid`). Renaming any of
484
+ them changes the fid → ref and orphans an in-flight answer keyed to the
485
+ old ref. Don't rename a section or the slug while a decision packet is
486
+ out and unanswered (the refmap-continuity invariant, #5).
487
+
488
+ ### `ensureDecisionActions` — the persistent-row materialization (Phase-2 cutover)
489
+
490
+ **Phase 1 ships the render synthesis above; the persistent-row
491
+ materialization lands at the Phase-2 Maginnis cutover (P2.1), where it
492
+ replaces the project-local `project-engagement-decisions.mjs`.** The
493
+ synthesis alone closes the loop (render + refmap + answer round-trip;
494
+ `target_fid` has no FK, so the answer stores without a row). The
495
+ materialized row is what lets the consultant *apply* an answer against a
496
+ tracked action.
497
+
498
+ When built, it is the DB-side counterpart — living at the adapter/skill
499
+ boundary (NOT in the pure engine), called at sync time before render:
500
+ idempotently materializes one pib-db action per decide item, keyed to
501
+ the **same deterministic fid** and carrying the `engagement_key:
502
+ <itemKey>` marker, `client-visible,needs:decision` tags (+
503
+ `audience:<id>` when declared), and the structured copy. Because the row
504
+ carries the marker, the render's structural dedup skips re-synthesizing
505
+ that key and renders the row instead — so in production every decision
506
+ resolves to a real, ingest-valid fid, and the synthesis is the
507
+ no-row / loop-test fallback.
508
+
509
+ ### Client render (P1.2 → `/collab-client`)
510
+
511
+ A `choice` decision maps each `options[i]` to one AskUserQuestion option
512
+ (`label: opt.label`, description from context); the chosen `value` is
513
+ the answer text submitted as the `client_feedback` message. A
514
+ `free_text` decision collects an open written answer (no option list).
515
+ The client never sees the `decision_type` enum or verdict jargon.
516
+
517
+ ### Answer round-trip (unchanged spine)
518
+
519
+ The answer is a `client_feedback` event with
520
+ `target_fid = refmap[context_ref]` (§6). Because the backing fid is
521
+ deterministic, an answer keyed to a prior packet's ref resolves to the
522
+ same decision across re-renders.
523
+
524
+ ---
525
+
340
526
  ## 6. `item_feedback` envelope
341
527
 
342
528
  The contract for inbound client responses. **Keyed by `ref` only.**
@@ -448,6 +634,60 @@ Default rate **$190/hr**. `renderBilling` sums the `Hours` column;
448
634
 
449
635
  ---
450
636
 
637
+ ## 8.1. Invoicing (`invoicing` block + the `invoices/` output)
638
+
639
+ `/collab-consultant invoice [YYYY-MM] [--itemized]` renders a clean,
640
+ print-friendly invoice **document** (`renderInvoiceDoc`) from a month's
641
+ tracked hours. It is local-only — no API, no pib-db mutation, no email.
642
+
643
+ ### Why a document, not an API
644
+
645
+ The operator's bank (**Relay**) does the actual invoicing. Relay has no
646
+ API but accepts an uploaded PDF/PNG via **Create Invoice → Autofill from
647
+ document**. So the system's only job is to render the document; the
648
+ operator uploads, reviews, and sends in Relay. Validated against Relay's
649
+ autofill (live experiment):
650
+
651
+ - Line items are **Description / Quantity / Unit price / Amount** and
652
+ Relay computes its own totals (Quantity = hours, Unit price = the rate).
653
+ - Relay assigns its own invoice number and pulls the sender (From /
654
+ business name / address / email) from the operator's Relay account.
655
+ **The document therefore carries NO invoice number and NO From / remit
656
+ / bank / ACH block** — they are ignored or overridden.
657
+ - Relay autofills the customer (bill-to name + email) and the line items
658
+ + total correctly.
659
+ - Relay does **not** read a net-30 due date — it defaults the due date to
660
+ today. Terms only survive in Relay's free-text Memo, so they go in a
661
+ memo-friendly footer line and the skill tells the operator to set the
662
+ due date in Relay by hand.
663
+
664
+ ### The `invoicing:` config block (optional)
665
+
666
+ | Field | Default | Meaning |
667
+ | ----- | ------- | ------- |
668
+ | `mode` | `consolidated` | `consolidated` (one line: scope label + month, Quantity = total hours) or `itemized` (one line per timelog row). `--itemized` on the command line overrides. |
669
+ | `scope_label` | `"Consulting services"` | The line description in consolidated mode (rendered as `<scope_label> — <Month YYYY>`). |
670
+ | `terms_days` | `30` | Net-N payment terms — `dueDate = invoiceDate + terms_days`, shown in the memo footer. |
671
+
672
+ `loadEngagement` normalizes these defaults (mirrors how `billing` /
673
+ `transport` defaults are filled), so downstream code can assume the
674
+ shape. **No bank / remit / From fields are needed** — see above.
675
+
676
+ The bill-to block reads `recipient.name`, optional `recipient.org`, and
677
+ `recipient.email` (org rides through `normalizeRecipient`).
678
+
679
+ ### Output convention: `invoices/<YYYY-MM>.html` (+ best-effort `.pdf`)
680
+
681
+ The rendered HTML is written to `invoices/<YYYY-MM>.html` in the working
682
+ dir. The skill then attempts a best-effort PDF conversion using whatever
683
+ tool is already on the machine (weasyprint → headless Chrome →
684
+ wkhtmltopdf), **with no bundled dependency** — if none is available it
685
+ tells the operator to open the HTML and use Cmd-P → Save as PDF. Relay
686
+ needs a PDF or PNG, not HTML. The `invoices/` directory is local runtime
687
+ output (gitignore alongside `engagement-packets/`).
688
+
689
+ ---
690
+
451
691
  ## 9. Scope model: multi-project engagements
452
692
 
453
693
  An engagement operates at the scope of **one `pib.db`** — all