@xhulz/nina 0.82.0 → 0.83.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 (135) hide show
  1. package/package.json +1 -1
  2. package/releases/0.83.0/core/GAPS.md +125 -0
  3. package/releases/0.83.0/core/answered.json +134 -0
  4. package/releases/0.83.0/core/defaults/tree/.claude/agents/architect.md +1 -0
  5. package/releases/0.83.0/core/defaults/tree/.claude/agents/dba.md +3 -0
  6. package/releases/0.83.0/core/defaults/tree/.claude/agents/devops.md +1 -0
  7. package/releases/0.83.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
  8. package/releases/0.83.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
  9. package/releases/0.83.0/core/defaults/tree/.claude/agents/qa.md +7 -0
  10. package/releases/0.83.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
  11. package/releases/0.83.0/core/defaults/tree/.claude/agents/secops.md +3 -0
  12. package/releases/0.83.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
  13. package/releases/0.83.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
  14. package/releases/0.83.0/core/tiers.json +5 -0
  15. package/releases/0.83.0/core/tree/.claude/agents/architect.md +140 -0
  16. package/releases/0.83.0/core/tree/.claude/agents/dba.md +123 -0
  17. package/releases/0.83.0/core/tree/.claude/agents/design-reviewer.md +82 -0
  18. package/releases/0.83.0/core/tree/.claude/agents/devops.md +122 -0
  19. package/releases/0.83.0/core/tree/.claude/agents/implementer.md +208 -0
  20. package/releases/0.83.0/core/tree/.claude/agents/integration-tester.md +174 -0
  21. package/releases/0.83.0/core/tree/.claude/agents/planner.md +132 -0
  22. package/releases/0.83.0/core/tree/.claude/agents/qa.md +154 -0
  23. package/releases/0.83.0/core/tree/.claude/agents/reviewer.md +191 -0
  24. package/releases/0.83.0/core/tree/.claude/agents/secops.md +124 -0
  25. package/releases/0.83.0/core/tree/.claude/agents/solidity-auditor.md +130 -0
  26. package/releases/0.83.0/core/tree/.claude/agents/solidity-dev.md +127 -0
  27. package/releases/0.83.0/core/tree/.claude/agents-overview.md +65 -0
  28. package/releases/0.83.0/core/tree/.claude/frontend.md +10 -0
  29. package/releases/0.83.0/core/tree/.claude/graph.md +79 -0
  30. package/releases/0.83.0/core/tree/.claude/patterns.md +256 -0
  31. package/releases/0.83.0/core/tree/.claude/pills/README.md +150 -0
  32. package/releases/0.83.0/core/tree/.claude/pipeline.md +101 -0
  33. package/releases/0.83.0/core/tree/.claude/retrieval.md +103 -0
  34. package/releases/0.83.0/core/tree/.claude/router.md +224 -0
  35. package/releases/0.83.0/core/tree/.claude/templates/integration.md +48 -0
  36. package/releases/0.83.0/core/tree/CLAUDE.md +167 -0
  37. package/releases/0.83.0/core/tree/scripts/cost-watch.mjs +27 -0
  38. package/releases/0.83.0/core/tree/scripts/edit-guard.mjs +24 -0
  39. package/releases/0.83.0/core/tree/scripts/harness-check.mjs +84 -0
  40. package/releases/0.83.0/core/tree/scripts/loop-gate.mjs +19 -0
  41. package/releases/0.83.0/core/vocabulary.json +18 -0
  42. package/releases/0.83.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
  43. package/releases/0.83.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
  44. package/releases/0.83.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
  45. package/releases/0.83.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
  46. package/releases/0.83.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
  47. package/releases/0.83.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
  48. package/releases/0.83.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
  49. package/releases/0.83.0/surfaces/blockchain/tree/.claude/router.md +6 -0
  50. package/releases/0.83.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
  51. package/releases/0.83.0/surfaces/d1/tree/.claude/agents/dba.md +15 -0
  52. package/releases/0.83.0/surfaces/d1/tree/.claude/agents/devops.md +2 -0
  53. package/releases/0.83.0/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
  54. package/releases/0.83.0/surfaces/d1/tree/.claude/patterns.md +8 -0
  55. package/releases/0.83.0/surfaces/d1/tree/CLAUDE.md +2 -0
  56. package/releases/0.83.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
  57. package/releases/0.83.0/surfaces/db/tree/.claude/agents/dba.md +54 -0
  58. package/releases/0.83.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
  59. package/releases/0.83.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
  60. package/releases/0.83.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
  61. package/releases/0.83.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
  62. package/releases/0.83.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
  63. package/releases/0.83.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
  64. package/releases/0.83.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
  65. package/releases/0.83.0/surfaces/db/tree/.claude/graph.md +8 -0
  66. package/releases/0.83.0/surfaces/db/tree/.claude/patterns.md +22 -0
  67. package/releases/0.83.0/surfaces/db/tree/.claude/pipeline.md +13 -0
  68. package/releases/0.83.0/surfaces/db/tree/.claude/retrieval.md +5 -0
  69. package/releases/0.83.0/surfaces/db/tree/.claude/router.md +4 -0
  70. package/releases/0.83.0/surfaces/db/tree/CLAUDE.md +17 -0
  71. package/releases/0.83.0/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
  72. package/releases/0.83.0/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
  73. package/releases/0.83.0/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
  74. package/releases/0.83.0/surfaces/drizzle/tree/.claude/patterns.md +7 -0
  75. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
  76. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
  77. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
  78. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
  79. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
  80. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
  81. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
  82. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
  83. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
  84. package/releases/0.83.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
  85. package/releases/0.83.0/surfaces/edge-cf/tree/CLAUDE.md +29 -0
  86. package/releases/0.83.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
  87. package/releases/0.83.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
  88. package/releases/0.83.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
  89. package/releases/0.83.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
  90. package/releases/0.83.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
  91. package/releases/0.83.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
  92. package/releases/0.83.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
  93. package/releases/0.83.0/surfaces/frontend/tree/.claude/router.md +14 -0
  94. package/releases/0.83.0/surfaces/frontend/tree/CLAUDE.md +5 -0
  95. package/releases/0.83.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
  96. package/releases/0.83.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
  97. package/releases/0.83.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
  98. package/releases/0.83.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
  99. package/releases/0.83.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
  100. package/releases/0.83.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
  101. package/releases/0.83.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
  102. package/releases/0.83.0/surfaces/integrations/tree/.claude/graph.md +10 -0
  103. package/releases/0.83.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
  104. package/releases/0.83.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
  105. package/releases/0.83.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
  106. package/releases/0.83.0/surfaces/integrations/tree/.claude/router.md +6 -0
  107. package/releases/0.83.0/surfaces/integrations/tree/CLAUDE.md +17 -0
  108. package/releases/0.83.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
  109. package/releases/0.83.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
  110. package/releases/0.83.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
  111. package/releases/0.83.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
  112. package/releases/0.83.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
  113. package/releases/0.83.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
  114. package/releases/0.83.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
  115. package/releases/0.83.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
  116. package/releases/0.83.0/surfaces/money/tree/.claude/graph.md +2 -0
  117. package/releases/0.83.0/surfaces/money/tree/.claude/patterns.md +49 -0
  118. package/releases/0.83.0/surfaces/money/tree/.claude/pipeline.md +2 -0
  119. package/releases/0.83.0/surfaces/money/tree/.claude/retrieval.md +2 -0
  120. package/releases/0.83.0/surfaces/money/tree/CLAUDE.md +11 -0
  121. package/releases/0.83.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
  122. package/releases/0.83.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
  123. package/releases/0.83.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
  124. package/releases/0.83.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
  125. package/releases/0.83.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
  126. package/releases/0.83.0/surfaces/pii/tree/CLAUDE.md +5 -0
  127. package/releases/0.83.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
  128. package/releases/0.83.0/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
  129. package/releases/0.83.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
  130. package/releases/0.83.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
  131. package/releases/0.83.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
  132. package/releases/0.83.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
  133. package/releases/0.83.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
  134. package/releases/0.83.0/surfaces/prisma/tree/CLAUDE.md +5 -0
  135. package/src/commands/eval.mjs +9 -3
@@ -0,0 +1,18 @@
1
+ {
2
+ "ARCHITECT_EFFORT": "xhigh",
3
+ "ARCHITECT_MODEL": "claude-opus-5-5",
4
+ "BUILD_CMD": "pnpm build",
5
+ "DEEP_EFFORT": "high",
6
+ "DEEP_MODEL": "claude-opus-5-5",
7
+ "IMMUTABLE_EFFORT": "high",
8
+ "IMMUTABLE_MODEL": "claude-opus-5-5",
9
+ "LINT_CMD": "pnpm lint",
10
+ "OUTPUT_CLIP": "8000",
11
+ "RUN_READ_WARN": "40",
12
+ "STEP_FILES": "15",
13
+ "STEP_LINES": "400",
14
+ "TEST_CMD": "pnpm test",
15
+ "TYPECHECK_CMD": "pnpm typecheck",
16
+ "WORK_EFFORT": "xhigh",
17
+ "WORK_MODEL": "claude-sonnet-5-5"
18
+ }
@@ -0,0 +1,5 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+ | a contract, a proxy, or a contracts library component | **`develop-secure-contracts`** · **`upgrade-solidity-contracts`** when storage moves |
3
+
4
+ <!-- nina:slot blockchain.2 -->
5
+ - **Contract surface (MANDATORY when the spec reaches `{{CONTRACTS_DIR}}`).** Name which contracts are touched and whether each is deployed; for a deployed one, say whether this is an upgrade and what preserves the storage layout. State the access-control model in roles, not in adjectives: who may call each state-changing function, and how that role is granted and revoked. List the adversarial tests the implementation owes — re-entry, the unauthorized caller, the boundary amount, the second call that must fail. A spec that reaches a contract and leaves any of these to the implementer is rejected.
@@ -0,0 +1,5 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+ - **`upgrade-solidity-contracts`** — before deploying a contract or executing a proxy upgrade, to check the storage layout against what is live.
3
+
4
+ <!-- nina:slot blockchain.2 -->
5
+ - **A contract deploy needs `solidity-auditor` `APPROVED` for this exact diff**, and its rollback named before it runs — which for a non-upgradeable contract is a redeploy plus a migration of state, not a revert. Say so *before* deploying. A deploy to a network carrying real value needs an explicit go from {{OWNER}} for that change, the same as production.
@@ -0,0 +1,5 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+ - **The solidity-auditor gate ran and returned `APPROVED`** for any diff touching `{{CONTRACTS_DIR}}`, a deploy script, or a contracts library version. Its absence is a blocking finding on its own, whatever the diff looks like to you.
3
+
4
+ <!-- nina:slot blockchain.2 -->
5
+ - A contract change written by the implementer rather than **solidity-dev** is rejected on routing alone. The two roles carry different rules about what a defect costs, and the cheaper set is the wrong one here.
@@ -0,0 +1,18 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+ | **`develop-secure-contracts`** | any library component in the diff — to check the usage against the library's own guidance, not against memory |
3
+
4
+ <!-- nina:slot blockchain.2 -->
5
+ | **`upgrade-solidity-contracts`** | a proxy, an initializer, or a storage layout change |
6
+
7
+ <!-- nina:slot blockchain.3 -->
8
+ | **`security-audit`** | the off-chain half — deploy scripts, key handling, CI, RPC endpoints (guidance mode) |
9
+
10
+ <!-- nina:slot blockchain.4 -->
11
+ - The deployed addresses and role holders in play, where the change targets a live system.
12
+
13
+ <!-- nina:slot blockchain.5 -->
14
+ - **An event for every state change**, and that what it emits matches what was written. Off-chain
15
+ reconstruction is the only history there is, and a wrong event is worse than a missing one.
16
+
17
+ <!-- nina:slot blockchain.6 -->
18
+ - Approve a change to a live contract without stating the upgrade path and naming who can execute it.
@@ -0,0 +1,16 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+ | **`setup-solidity-contracts`** | a new contract project, a dependency install, or import/remapping configuration |
3
+
4
+ <!-- nina:slot blockchain.2 -->
5
+ | **`develop-secure-contracts`** | any library component — token standards, access control, pausing, reentrancy protection |
6
+
7
+ <!-- nina:slot blockchain.3 -->
8
+ | **`upgrade-solidity-contracts`** | a proxy, an initializer, or anything that moves storage |
9
+
10
+ <!-- nina:slot blockchain.4 -->
11
+ - The contract's deployed state, where one exists. A change to a live contract is an upgrade with a
12
+ storage layout to preserve, not an edit.
13
+
14
+ <!-- nina:slot blockchain.5 -->
15
+ - Widen a function's visibility, or add an address to a role, to make a test pass. The test is
16
+ describing the access control; fix the test or reject the spec.
@@ -0,0 +1,6 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+ - **Contract guardrail** → deployed code is immutable and permanently callable by anyone, so a defect is not a patch away and "nothing calls this" is not a property of it. Reentrancy, a state-changing function with no access control, a storage layout broken by an upgrade, and an audited component used against its own guidance are caught here.
3
+
4
+ <!-- nina:slot blockchain.2 -->
5
+ | **solidity-dev** | Write contract sources and their adversarial tests to spec; never deploys | `.claude/agents/solidity-dev.md` |
6
+ | **solidity-auditor** | Mandatory gate on any contract diff; blocks reviewer and devops | `.claude/agents/solidity-auditor.md` |
@@ -0,0 +1,11 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+ - `solidity-dev` — writes contract code, which cannot be changed once it is live
3
+ - `solidity-auditor` — gate: audits contract code as an attacker before anything deploys
4
+
5
+ <!-- nina:slot blockchain.2 -->
6
+ - `architect` → `solidity-dev` on `SPEC-READY` — the spec changes contract code
7
+ - `solidity-dev` → `solidity-auditor` on `DIFF-READY`
8
+ - `solidity-dev` → `architect` on `BLOCKED` — the change cannot be made safely as specified · max 2
9
+ - `solidity-auditor` → `reviewer` on `APPROVED`
10
+ - `solidity-auditor` → `solidity-dev` on `REJECTED` — a flaw in the contract code · max 2
11
+ - `solidity-auditor` → `architect` on `REJECTED` — a flaw in the design · max 2
@@ -0,0 +1,6 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+
3
+ ### Solidity-auditor is a guardrail for contract changes
4
+ Invoke **solidity-auditor** on any diff that touches `{{CONTRACTS_DIR}}`, a deploy script, or the version of a contracts library — regardless of where you are in the pipeline. No contract change merges without its approval, and none deploys without it. Reviewer verifies it ran; devops verifies it approved.
5
+
6
+ Contract sources are written by **solidity-dev**, not the implementer. Route the work there when the spec's file list reaches `{{CONTRACTS_DIR}}`, and keep the implementer on the off-chain side of the same feature.
@@ -0,0 +1,12 @@
1
+ <!-- nina:slot blockchain.1 -->
2
+ 16. **Every contract change goes through the solidity-auditor gate, and deployed code is never patched in place.** A diff touching a contract source, a deploy script, or the version of a contracts library does not reach the reviewer without `VERDICT: APPROVED` from **solidity-auditor**, and does not reach any network without it. Contract sources are written by **solidity-dev**, not by the implementer — the implementer's rules assume a defect is a patch away, and here it is a redeploy or a proxy upgrade at best. Private keys, mnemonics and funded accounts never enter the repository in any form, test fixtures included.
3
+
4
+ <!-- nina:slot blockchain.2 -->
5
+ | **ANY step touching a contract, a deploy script, or a contracts library version** | **architect → solidity-dev → solidity-auditor → reviewer → qa** — the auditor is mandatory and blocks the reviewer |
6
+
7
+ <!-- nina:slot blockchain.3 -->
8
+ - **solidity-dev** → write contract sources and their adversarial tests strictly to spec; never deploys, never widens access control to make a test pass
9
+ - **solidity-auditor** → **mandatory gate** on any contract diff; `APPROVED` required before reviewer and before any deploy
10
+
11
+ <!-- nina:slot blockchain.4 -->
12
+ - **contract code**: a contract source, a deploy script, or the version of a contracts library
@@ -0,0 +1,15 @@
1
+ <!-- nina:slot d1.1 -->
2
+ | `cloudflare:cloudflare` | D1's limits, its binding's API, `wrangler d1` migrations |
3
+
4
+ <!-- nina:slot d1.2 -->
5
+ - **On D1, migration safety is about table redefinitions, not locks.** SQLite cannot alter a column, so many changes are drafted as a redefinition: a new table, a copy, `DROP TABLE` of the old one, a rename. Under the local emulator `PRAGMA foreign_keys=OFF` had no effect, so that `DROP TABLE` fired every `CASCADE` and `SET NULL` pointing at the table, exited 0 and left `foreign_key_check` clean, and `PRAGMA defer_foreign_keys=on` did not stop it. Until production D1 shows otherwise, hold every migration to:
6
+ - no redefinition of a table that holds data;
7
+ - foreign keys `RESTRICT` or `NO ACTION`, so a redefinition that would destroy rows fails instead. A `CASCADE`, `SET NULL` or `SET DEFAULT` the architecture keeps is named there with its reason, and every migration that redefines a table it reaches is tested on rows it would cascade to;
8
+ - `ADD COLUMN` nullable, or NOT NULL with a constant default — with no default, or a non-constant one such as `unixepoch()` or `CURRENT_TIMESTAMP`, it applied to an empty table and failed on one with rows under the emulator — and an added `REFERENCES` column nullable with no default, which SQLite requires while foreign keys are on;
9
+ - a redefinition's `INSERT … SELECT` naming only columns the old table has: the emulator read an unknown double-quoted name as a string literal and filled every row with it;
10
+ - the migration applied, in a test, to the previous schema holding rows, and a drift test comparing the applied schema (`PRAGMA table_info`, `foreign_key_list`, `index_list`) with the one the code declares.
11
+
12
+ - **On D1, the SQL you read is the text D1 runs, not the file.** Per wrangler 4.148's source and `--local`: `d1 migrations apply` appends `INSERT INTO d1_migrations (name) values ('<file>');` to the text, so a last statement with no `;` merges with it and the deploy fails while the tests, which bind that insert apart, pass; locally, text holding `BEGIN TRANSACTION` loses its first `BEGIN TRANSACTION;` and first `COMMIT;` wherever they stand, comments and strings included; `--remote` hands the text whole to D1's server, whose splitter nobody outside Cloudflare can read; and SQLite reads `$name(…)`, `:name(…)`, `@name(…)` and `#name(…)` as one token that swallows quotes, `--` and `;`. Refuse a migration holding `BEGIN TRANSACTION` or `COMMIT;` anywhere, `[$@:#]name(` outside a string or comment, or a last statement without its `;`. A script that gates migrations is checked differentially against wrangler's own trim and split and SQLite's tokenizer, never a model of one stage.
13
+
14
+ <!-- nina:slot d1.3 -->
15
+ - **On D1, every query holds to `.claude/patterns.md` § *D1*:** an atomic change is one batch, a conditional write carries its guard in SQL, and no statement binds more than 100 parameters. A list lookup "batched" past that limit is an N+1 fix that fails once the list grows.
@@ -0,0 +1,2 @@
1
+ <!-- nina:slot d1.1 -->
2
+ - **D1 migrations reach the preview database before production**, as the files the database gate read, and one that redefines a table holding data does not go out at all — the dba's D1 rules say why.
@@ -0,0 +1,2 @@
1
+ <!-- nina:slot d1.1 -->
2
+ | `cloudflare:cloudflare` | a D1 query, batch or migration |
@@ -0,0 +1,8 @@
1
+ <!-- nina:slot d1.1 -->
2
+
3
+ ### D1
4
+
5
+ - **No interactive transaction.** A transaction call sends `begin`, which the local emulator refused, and the type checker accepts the call. The atomic unit is one D1 batch: a statement failing a UNIQUE or NOT NULL constraint rolled the whole batch back under the emulator. Production D1 has not been observed for either; until it is, design as if both hold. Whether a client's batch call is one D1 batch, and which items it can hold, is cited from the integration doc.
6
+ - **A batch rolls back on an error, not on "0 rows changed".** A write that must not happen when an earlier one changed nothing carries its guard in SQL inside the same batch — a statement that fails when the condition does not hold. A `changes() = 0` guard read only the statement right before it, under the emulator.
7
+ - **At most 100 bound parameters per statement** (the emulator ran 100 and refused 101). A lookup by a list of ids, with its tenant filter, and a multi-row insert, at rows × columns, are chunked to stay within it.
8
+ - **Each row written counted once per index it touched**, a text primary key's own index included, in the rows written the emulator reported; how production D1 bills them against a rows-written quota is not yet observed.
@@ -0,0 +1,2 @@
1
+ <!-- nina:slot d1.1 -->
2
+ | Write or audit a D1 query, batch, migration or binding (architect, implementer, the database gate) | `cloudflare:cloudflare` | D1's limits and its binding's API drift with the platform; `.claude/patterns.md` § *D1* holds what this harness requires on top |
@@ -0,0 +1,5 @@
1
+ <!-- nina:slot db.2 -->
2
+ - **Tenant-scope impact** — state where `{{TENANT_KEY}}` is enforced. Every new query in app code filters by it, or reaches it through the model's foreign keys; only the auth library's own tables are exempt.
3
+
4
+ <!-- nina:slot db.3 -->
5
+ - **Database flag** — if the schema or a new query is touched, mark **"DBA REQUIRED"** prominently at the top of the spec, and name each new read's cache policy, or **`NO_CACHE`** for a read that feeds a write whose correctness depends on it being fresh — a stale row contaminates every decision made from it.
@@ -0,0 +1,54 @@
1
+ <!-- nina:slot db.3 -->
2
+ - Any change to the schema.
3
+ - Any new query, or change to one, anywhere in application code.
4
+ - Any migration.
5
+
6
+ <!-- nina:slot db.4 -->
7
+ - The schema diff, and the migration SQL it generates.
8
+ - The application code that uses the new or modified queries.
9
+
10
+ <!-- nina:slot db.5 -->
11
+ **Read `.claude/code-map.md`** when the change touches new query patterns — it lists which services consume which models, so you can spot N+1 risk and consumer-side cache implications without re-grepping. (Before there is code, fall back to `.claude/architecture.md` § *Database* for the planned schema and its cache policies.)
12
+
13
+ <!-- nina:slot db.6 -->
14
+ - **The schema validates, and you read the migration's SQL** — offline, from files, with the project's own schema tooling. A check that seems to need a live database is one you report as impossible, not one you run.
15
+ - **An empty diff from a schema change is a failure, not "nothing changed".** A diff tool short of what it needs — a datasource, a config — has printed nothing and exited 0, and so has its `--exit-code`. Before you trust an empty result, make the same command print a change you know is there.
16
+
17
+ <!-- nina:slot db.8 -->
18
+ - **Migration safety on large tables:**
19
+ - No `ALTER TABLE ... ADD COLUMN NOT NULL` without a safe default (causes lock + rewrite).
20
+ - No operations that hold long locks without an explicit batched strategy.
21
+ - Non-breaking for rolling deploy — old application code and new schema must coexist during the deploy window.
22
+
23
+ <!-- nina:slot db.9 -->
24
+ - **Index coverage.** Every new query pattern (`WHERE`, `ORDER BY`, `JOIN`, `aggregate`) must be backed by an index declared in the schema. Reject queries that would table-scan. The most-used compound index is `(<tenant>, <other>)` or, for models keyed by a parent entity, `(<parentId>, <other>)`; verify the leading column matches the query.
25
+
26
+ <!-- nina:slot db.10 -->
27
+ - **Tenant scope.** Every query in app code filters by `{{TENANT_KEY}}`, or by the foreign-key chain that resolves back to it. The auth library's own tables are the only exemption. Reject any app query missing the scope.
28
+
29
+ <!-- nina:slot db.11 -->
30
+ - **Cache discipline.** A cached read names its policy explicitly — **an implicit cache is a bug: reject it** — checked against the cache policies in `.claude/architecture.md` § *Database*. A read that feeds a write whose correctness depends on it being fresh is never cached.
31
+
32
+ <!-- nina:slot db.12 -->
33
+ - **N+1 patterns.** If the code fetches a list then queries per item, reject with "fetch the related rows with the list, or batch."
34
+
35
+ <!-- nina:slot db.13 -->
36
+ - **Secrets.** Whatever credential reaches the database — a connection string, an API token — comes from `{{SECRETS_LOCAL}}` locally and `{{SECRETS_PROD}}` in production — never a committed `.env`, never a literal in code. A database reached through a platform binding has no connection string to check.
37
+
38
+ <!-- nina:slot db.14 -->
39
+ - **Run anything that can write to a real database.** You are a read-only gate: against a live database you run read-only queries and nothing else. If a check seems to require writing, it does not — report the limitation to the orchestrator instead.
40
+
41
+ <!-- nina:slot db.15 -->
42
+ - Approve without validating the schema and reading the migration's SQL, offline, as *You MUST check* says.
43
+
44
+ <!-- nina:slot db.16 -->
45
+ - Wave through "small" schema changes. Small changes cause the worst production incidents.
46
+
47
+ <!-- nina:slot db.17 -->
48
+ - Approve a query in app code missing its `{{TENANT_KEY}}` scope, or the foreign key that owns it.
49
+
50
+ <!-- nina:slot db.18 -->
51
+ **Final report format:** ≤300 words if approved. Sections: Schema validation result, Migration SQL preview (verbatim if non-trivial), Index analysis, Tenant-scope check, Cache verdict, Privacy check, Final verdict. If rejected, list each issue with required action — no length cap.
52
+
53
+ <!-- nina:slot db.19 -->
54
+ - **The tracked schema is the reviewed one, not a generator's output.** A diff that rewrites it whole, or drops a delta its header lists, is a generator writing where it must not (`.claude/patterns.md`): reject it.
@@ -0,0 +1,5 @@
1
+ <!-- nina:slot db.2 -->
2
+ - **Migrations, in order, against the right database.** Confirm the target is the database you intend, and that the migration is backward-compatible with the code already deployed, because the two are live together during the rollout.
3
+
4
+ <!-- nina:slot db.5 -->
5
+ - **Migrations:** applied / none, with the database they hit.
@@ -0,0 +1,2 @@
1
+ <!-- nina:slot db.2 -->
2
+ - If you change the schema or write a new query, flag it explicitly in the diff summary: it triggers the **dba** gate.
@@ -0,0 +1,10 @@
1
+ <!-- nina:slot db.2 -->
2
+ - A new query on a cached read path — verify the cache's behavior live (dba covers the schema; you cover how the cache behaves at runtime)
3
+
4
+ <!-- nina:slot db.3 -->
5
+ If a query behaves differently against a real database than the dba's static analysis suggested, escalate to **dba** — do not fix it yourself.
6
+
7
+ <!-- nina:slot db.4 -->
8
+ - **The auth library's backing store is a real database** — the development database, reached as the
9
+ implementer reaches it locally: a connection from `{{SECRETS_LOCAL}}`, or the local emulator's binding. A suite that is green against an
10
+ in-memory stand-in has not exercised the library, which is the whole point of this stage.
@@ -0,0 +1,2 @@
1
+ <!-- nina:slot db.1 -->
2
+ - **Database flag** — if any subtask may touch the schema or create a new query, mark **"DBA REQUIRED"** on that subtask.
@@ -0,0 +1,22 @@
1
+ <!-- nina:slot db.2 -->
2
+ - **If the schema, a migration or a query was touched anywhere in the diff: name `dba` on your Gates line.** Its approval is what a database change needs; yours does not stand in for it.
3
+
4
+ <!-- nina:slot db.3 -->
5
+ - Check for **tenant scoping** in every new query in app code: it filters by `{{TENANT_KEY}}`, or reaches it through the model's foreign keys. No "global" queries except the auth library's own tables. Missing scope = `REJECTED`.
6
+
7
+ <!-- nina:slot db.4 -->
8
+ - Check for N+1 queries when the DB layer was touched.
9
+
10
+ <!-- nina:slot db.5 -->
11
+ - **tenant-and-privacy** — `{{TENANT_KEY}}` in every app query (the auth library's own tables are the only exemption);
12
+ no PII or secrets in logs; no cross-tenant read
13
+ or write reachable through a route, an MCP tool, a webhook, or an RPC between services.
14
+
15
+ <!-- nina:slot db.6 -->
16
+ - The schema touched (a migration in play)
17
+
18
+ <!-- nina:slot db.7 -->
19
+ - Leave `dba` off your Gates line on a database change "because it seems fine."
20
+
21
+ <!-- nina:slot db.8 -->
22
+ - Schema or query touched and `dba` not dispatched → name it on your Gates line; the orchestrator sends it.
@@ -0,0 +1,2 @@
1
+ <!-- nina:slot db.1 -->
2
+ - **AuthZ / tenant isolation (Hard Rule #7)** — EVERY query in app code scopes by `{{TENANT_KEY}}` (or its foreign key). Hunt for any query, route, MCP tool, or queue, webhook or background path where another tenant's data could be read or mutated (IDOR). The auth library's own tables are the only allowed unscoped reads — verify nothing else is.
@@ -0,0 +1,5 @@
1
+ <!-- nina:slot db.1 -->
2
+ - **DBA guardrail** → the database is the surface where a bad change causes hard-to-reverse damage. Schema mistakes, missing indexes, cache on reads that feed a correctness-critical write, missing tenant scope — all caught here.
3
+
4
+ <!-- nina:slot db.2 -->
5
+ | **dba** | Mandatory gate on schema changes, migrations and new queries | `.claude/agents/dba.md` |
@@ -0,0 +1,8 @@
1
+ <!-- nina:slot db.1 -->
2
+ - `dba` — gate: runs when the schema, a migration or a query is touched
3
+
4
+ <!-- nina:slot db.2 -->
5
+ - `implementer` → `dba` on `DIFF-READY` — the diff touches the schema, a migration or a query
6
+ - `dba` → `qa` on `APPROVED` — once the reviewer, and every other gate the diff went to, approved too
7
+ - `dba` → `implementer` on `REJECTED` — a query or schema change in the diff is unsafe · max 2
8
+ - `dba` → `architect` on `REJECTED` — the spec's migration or data design is unsafe · max 2
@@ -0,0 +1,22 @@
1
+ <!-- nina:slot db.2 -->
2
+ - Routes must NOT import query functions (`list*`, `find*`, `get*`, `upsert*`, `delete*`) from `{{DB_PKG_NAME}}` — only its client and its error classes.
3
+
4
+ <!-- nina:slot db.4 -->
5
+ - **Every service query filters by `{{TENANT_KEY}}` (tenant scope).** Missing scope = automatic `REJECTED`.
6
+
7
+ <!-- nina:slot db.5 -->
8
+
9
+ ---
10
+
11
+ ## Database conventions (enforced by the dba subagent)
12
+
13
+ - **A cached read names its policy, and a read that feeds a write whose correctness depends on it being fresh is NEVER cached.** A stale row contaminates the decision made from it. Hard reject in dba review.
14
+ - **Every query in app code filters by `{{TENANT_KEY}}`** (or reaches it through the model's foreign keys). Tenant isolation is in the data layer. The auth library's own tables are the only exemption.
15
+ - Migrations reviewed by **dba** for: non-blocking on large tables, index coverage for new query patterns, backward compatibility during rolling deploy.
16
+ - N+1 queries are a bug.
17
+
18
+ <!-- nina:slot db.6 -->
19
+ - A real database, never a mock of its client.
20
+
21
+ <!-- nina:slot db.7 -->
22
+ - **A library's schema generator never writes the tracked schema.** One rewrites the file whole, so it writes to scratch.<!-- nina:why --> An auth library's generator dropped a hand-added table and foreign key.<!-- /nina:why --> The tracked file is the reviewed one and lists its deltas from the generator's output; a check regenerates into scratch and compares the two, less those deltas.
@@ -0,0 +1,13 @@
1
+ <!-- nina:slot db.1 -->
2
+
3
+ ### DBA (mandatory for the database)
4
+
5
+ - **Trigger:** any schema change, any new query, any migration.
6
+ - **Input:** the schema diff and its migration SQL + the application code using the queries.
7
+ - **Output:** `APPROVED`, or `REJECTED` with specific issues.
8
+ - **Tools:** Read, Grep, Glob, Bash (schema validation, an offline migration diff, query-plan checks).
9
+ - **Checks:** schema validates; migration safe on large tables; index coverage; an explicit policy on every cached read; **no cache on a read that feeds a correctness-critical write**; **tenant scope in every query**; no N+1; no raw PII without encryption; the connection secret comes from the environment, never from code.
10
+ - **Position:** beside the reviewer, when a diff touches the schema, a migration or a query; `qa` waits for its `APPROVED`.
11
+
12
+ <!-- nina:slot db.2 -->
13
+ - **If the schema or a query was touched → dba approved.**
@@ -0,0 +1,5 @@
1
+ <!-- nina:slot db.1 -->
2
+ | Schema change | `.claude/architecture.md` § *Database*, the schema | implementer → reviewer + **dba** (mandatory) → qa |
3
+
4
+ <!-- nina:slot db.2 -->
5
+ | New query in app code | `.claude/patterns.md` § *Database conventions* | implementer → reviewer + **dba** (mandatory) → qa |
@@ -0,0 +1,4 @@
1
+ <!-- nina:slot db.1 -->
2
+
3
+ ### DBA is a guardrail, not a stage
4
+ Invoke **dba** any time the schema, a migration or a query is touched — regardless of where you are in the pipeline. No such change reaches qa without dba approval; the reviewer names it on its Gates line.
@@ -0,0 +1,17 @@
1
+ <!-- nina:slot db.3 -->
2
+ | **ANY schema change, migration or new query** | **+ dba beside the reviewer** |
3
+
4
+ <!-- nina:slot db.4 -->
5
+ - **dba** → mandatory gate on schema changes, migrations, and new queries
6
+
7
+ <!-- nina:slot db.5 -->
8
+ 2. **Every schema change, migration and new query goes through the dba subagent.** No exceptions. It runs beside the reviewer, which names it on its Gates line, and `qa` does not go out without its `APPROVED`.
9
+
10
+ <!-- nina:slot db.6 -->
11
+ 6. **A cached read names its cache policy, and a read that feeds a write whose correctness depends on it being fresh is never cached.** An implicit cache is a bug, and a stale row contaminates every decision made from it. A write invalidates what it made stale.
12
+
13
+ <!-- nina:slot db.7 -->
14
+ 7. **Tenant isolation is enforced in the data layer.** Every query in app code filters by `{{TENANT_KEY}}`, or reaches it through the model's foreign keys. No "global" queries except the auth library's own tables. Reviewer rejects any query missing the scope.
15
+
16
+ <!-- nina:slot db.8 -->
17
+ - **the database**: the schema, a migration, or a query
@@ -0,0 +1,9 @@
1
+ <!-- nina:slot drizzle.1 -->
2
+ No skill covers Drizzle. What `drizzle-orm` and `drizzle-kit` do is cited from their installed source, by
3
+ `file:line`, like any installed library — and what they do on this project's engine, from its integration doc.
4
+
5
+ <!-- nina:slot drizzle.2 -->
6
+ - **With Drizzle, offline and failing closed.** Draft the migration with `drizzle-kit generate`, which needs no driver and no URL, in a copy of the tree in your scratch directory — it writes the SQL, a snapshot and a journal, and the tracked migrations are not yours to write — and read the SQL, not the schema delta. On SQLite kit drafts a table redefinition for a nullability, type, default or primary-key change, a foreign key added to an existing column or with a changed action, and a CHECK: look for one in every draft. drizzle-kit fails open: it has exited 0 with no file when a rename prompt could not render without a terminal, on a schema syntax error and with a missing journal, and exited 0 with a `DROP TABLE` for every table when the schema exported none. The check passes only on exit 0, empty stderr, and either exactly one new `.sql` holding the change you expected, or no new file and the exact line "No schema changes, nothing to migrate". A rename comes out as `RENAME COLUMN` or as `ADD` plus `DROP COLUMN` depending on that prompt's answer: read which you got. An `ADD COLUMN … REFERENCES` draft has dropped the declared `ON DELETE` while kit's snapshot kept it, so a later "no changes" passes over a database that differs from the schema — only a test against the applied schema sees it.
7
+
8
+ <!-- nina:slot drizzle.3 -->
9
+ - Run a drizzle-kit command that writes to a database — `push`, `migrate` — or give a drizzle config the credentials of a real one. `generate` answers everything this gate asks.
@@ -0,0 +1,5 @@
1
+ <!-- nina:slot drizzle.1 -->
2
+ - **Drizzle migrations go out through the one runner the architecture names**, as the SQL files the database gate read, and nothing else changes a shared database's schema.
3
+
4
+ <!-- nina:slot drizzle.2 -->
5
+ - Run `drizzle-kit push` against a shared database. It applies the schema without a migration file, so no gate read what it did.
@@ -0,0 +1,2 @@
1
+ <!-- nina:slot drizzle.1 -->
2
+ - **With Drizzle, `db.transaction` and `db.batch` do what this project's driver does with them**, not what their types promise: `tsc` accepts calls a driver refuses at run time. Rely on either only as the integration doc's premises, cited from the driver's installed source, say it behaves.
@@ -0,0 +1,7 @@
1
+ <!-- nina:slot drizzle.1 -->
2
+
3
+ ### Drizzle
4
+
5
+ - Tables are declared in one schema module per storage backend, and only there.
6
+ - A database error does not leave the data layer as Drizzle threw it: a failed single query's error carries the SQL and every bound value, in its message and as properties, so logging or serializing it publishes them. `logger: true` logs every parameter too.
7
+ - Tests run a real Drizzle client against the real engine or its local emulator; the client is never mocked.
@@ -0,0 +1,14 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ | `cloudflare:workers-best-practices` | `{{API_DIR}}/**` — routes, services, middleware, queue handlers |
3
+
4
+ <!-- nina:slot edge-cf.2 -->
5
+ | `cloudflare:durable-objects` | `{{API_DIR}}/src/do/**` or any DO call site |
6
+
7
+ <!-- nina:slot edge-cf.3 -->
8
+ | `cloudflare:cloudflare` | Queues, R2 or KV |
9
+
10
+ <!-- nina:slot edge-cf.4 -->
11
+ | `cloudflare:wrangler` | its config or any wrangler command |
12
+
13
+ <!-- nina:slot edge-cf.5 -->
14
+ - **Cloudflare skill flag** — if the spec touches `{{API_DIR}}/**` (routes, services, queue handlers), the per-account Durable Object, Queues, R2/KV, or `wrangler` config, name which `cloudflare:*` plugin skill the implementer must consult (`cloudflare:workers-best-practices`, `cloudflare:durable-objects`, `cloudflare:cloudflare`, `cloudflare:wrangler`), or state why none applies. Retrieval beats recall — the reviewer rejects a spec that touches these surfaces without naming the skill.
@@ -0,0 +1,2 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ - **Edge runtime compatibility.** A database client that runs at the edge uses its edge build, and `nodejs_compat` is in the wrangler config's `compatibility_flags`.
@@ -0,0 +1,29 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ - **`cloudflare:wrangler`** — before running ANY `wrangler` command or reading the wrangler config.
3
+ CLI flags and config fields churn between minor versions; pre-trained knowledge is stale.
4
+
5
+ <!-- nina:slot edge-cf.2 -->
6
+ - **`cloudflare:cloudflare`** — when the deploy touches R2, KV, Queues or Durable Object bindings.
7
+
8
+ <!-- nina:slot edge-cf.3 -->
9
+ - **Every target the change reaches, or none.** A change to the API surface deploys the Worker's staging or preview, and — where the frontend deploys apart from it, as a Pages project or a Worker of its own — the frontend's too. Deploying a frontend alone against an old API is the failure that renders new fields as "—". Where one Worker serves the API and the frontend as static assets, the two are one deploy. State which targets this change requires and why.
10
+
11
+ <!-- nina:slot edge-cf.4 -->
12
+ - **Secret and variable parity.** Everything the new code reads via `env.*` exists in the target environment (`wrangler secret list`). A missing secret fails at request time, not at deploy time.
13
+
14
+ <!-- nina:slot edge-cf.5 -->
15
+ - **A variable the frontend bundle reads is in the environment of its build command.** The wrangler config's `vars` reach a Worker at runtime and never a bundler, which inlines what it reads at build time. A missing one ships a blank page with no error.
16
+
17
+ ## A frontend on Pages: which branch, and why it matters
18
+
19
+ Only where the frontend deploys as a Pages project of its own; a Worker that serves it as static assets has no
20
+ branch to choose. A **direct-upload** Pages project whose production branch is `main` goes to production or
21
+ to preview by `wrangler pages deploy --branch` alone:
22
+
23
+ - **Staging FE** → `--branch staging`. A preview deployment on its own URL. Production is untouched,
24
+ and this is the FE half of the staging pair with the Worker's staging.
25
+ - **Production FE** → `--branch main`. Only with an explicit go from {{OWNER}}, per § *Production*.
26
+
27
+ Deploying staging with `--branch=main` is a production deploy wearing a staging label — the
28
+ permission classifier is right to stop it. Use the staging branch and the block disappears, because
29
+ the block was correct.
@@ -0,0 +1,14 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ | `cloudflare:workers-best-practices` | anything under `{{API_DIR}}/**` |
3
+
4
+ <!-- nina:slot edge-cf.2 -->
5
+ | `cloudflare:durable-objects` | anything under `{{API_DIR}}/src/do/**` or a DO call site |
6
+
7
+ <!-- nina:slot edge-cf.3 -->
8
+ | `cloudflare:cloudflare` | a queue consumer, or R2 / KV access |
9
+
10
+ <!-- nina:slot edge-cf.4 -->
11
+ | `cloudflare:wrangler` | a change to the wrangler config |
12
+
13
+ <!-- nina:slot edge-cf.5 -->
14
+ - Respect Workers conventions: secrets in `{{SECRETS_LOCAL}}` for local dev (never commit), `nodejs_compat` in the wrangler config's `compatibility_flags`.
@@ -0,0 +1,11 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ | `cloudflare:durable-objects` | DO lifecycle, alarms, RPC, storage — the API surface drifts fast |
3
+
4
+ <!-- nina:slot edge-cf.2 -->
5
+ | `cloudflare:cloudflare` | Queues, R2 or KV bindings |
6
+
7
+ <!-- nina:slot edge-cf.3 -->
8
+ | `cloudflare:wrangler` | anything you run through the wrangler CLI |
9
+
10
+ <!-- nina:slot edge-cf.4 -->
11
+ - Any new Cloudflare binding read/write: R2, KV, Queues, Durable Objects — drive the binding via Miniflare and observe real I/O. Miniflare fetches `workers.cloudflare.com/cf.json` as it starts unless `CLOUDFLARE_CF_FETCH_ENABLED=false`: set it where a run promises no network beyond a named host
@@ -0,0 +1,3 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ Here `$STRAY` is `vitest|workerd`: a Worker test boots a second runtime process alongside vitest,
3
+ and it is the one that holds ~2 GB and survives a killed test run.
@@ -0,0 +1,8 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ | `cloudflare:workers-best-practices` | `{{API_DIR}}/**` |
3
+
4
+ <!-- nina:slot edge-cf.2 -->
5
+ | `cloudflare:durable-objects` | `{{API_DIR}}/src/do/**` or a DO call site |
6
+
7
+ <!-- nina:slot edge-cf.3 -->
8
+ - `{{API_DIR}}/src/do/`, a queue consumer, or a webhook receiver touched (serialization + idempotency surface)
@@ -0,0 +1,8 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ - **Secrets & config exposure** — no secrets in committed files, logs, error messages, or generated artifacts (`worker-configuration.d.ts` must contain only types, never values). `{{SECRETS_LOCAL}}`/`.env` gitignored. The split between `wrangler secret` and the wrangler config's `vars` is correct. No secret echoed in a response or thrown error.
3
+
4
+ <!-- nina:slot edge-cf.2 -->
5
+ - **Dependency & binding posture** — obviously risky dependency usage; Cloudflare binding scoping (R2 bucket names, Queue, DO) — nothing over-privileged or world-exposed; `nodejs_compat` and compatibility flags sane.
6
+
7
+ <!-- nina:slot edge-cf.3 -->
8
+ - Prefer retrieval over recall for Cloudflare/{{AUTH_LIB}} specifics: consult the `cloudflare:*` skills and the installed `node_modules` source / `.claude/integrations/*.md` rather than assuming.
@@ -0,0 +1,17 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+
3
+ ---
4
+
5
+ ## Secrets
6
+
7
+ - **Wrangler secrets** for Workers (`{{SECRETS_PROD}} X`). Never `.env` committed.
8
+ - **Local dev:** `{{SECRETS_LOCAL}}` (gitignored).
9
+
10
+ <!-- nina:slot edge-cf.2 -->
11
+ - `nodejs_compat` in the wrangler config's `compatibility_flags` is required for a database client that runs at the edge.
12
+
13
+ <!-- nina:slot edge-cf.3 -->
14
+ - **Miniflare** for Worker integration tests.
15
+
16
+ <!-- nina:slot edge-cf.4 -->
17
+ - **Miniflare** for Worker tests — the real Cloudflare runtime, no mocks.
@@ -0,0 +1,8 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+ | New Durable Object behavior | `.claude/architecture.md` § *Durable Objects*, existing `{{API_DIR}}/src/do/` | architect → implementer → reviewer + the integration gate, where there is one → qa |
3
+
4
+ <!-- nina:slot edge-cf.2 -->
5
+ | New Queue handler | `.claude/architecture.md` § *Processing pipeline*, `{{API_DIR}}/src/queues/` | architect → implementer → reviewer + the integration gate, where there is one → qa |
6
+
7
+ <!-- nina:slot edge-cf.3 -->
8
+ | Wrangler / deploy / config | `CLAUDE.md` § *Common commands*, the wrangler config (`wrangler.jsonc` or `wrangler.toml`), `.claude/patterns.md` § *Secrets* | implementer → reviewer → qa → devops |
@@ -0,0 +1,29 @@
1
+ <!-- nina:slot edge-cf.1 -->
2
+
3
+ ### Cloudflare plugin skills — USE THEM
4
+
5
+ The `cloudflare@cloudflare` plugin is installed at user scope and exposes skills that retrieve the **current** Cloudflare docs at invocation time. Pre-trained knowledge of Workers / Wrangler / DO / Queues / Cron APIs is stale — prefer the skill over recalling from memory.
6
+
7
+ <!-- nina:slot edge-cf.2 -->
8
+ | Write or review code under `{{API_DIR}}/**` (routes, services, middleware, webhook receivers, queue consumers) | `cloudflare:workers-best-practices` | catches floating promises, global-state misuse, missing `waitUntil`, streaming pitfalls |
9
+
10
+ <!-- nina:slot edge-cf.3 -->
11
+ | Touch `{{API_DIR}}/src/do/**` or any Durable Object call site | `cloudflare:durable-objects` | covers RPC, alarms, WebSocket, SQLite storage, lifecycle — DO API surface drifts fast |
12
+
13
+ <!-- nina:slot edge-cf.4 -->
14
+ | Touch `{{API_DIR}}/src/queues/**`, R2/KV usage | `cloudflare:cloudflare` | Queues, R2, KV decision tree |
15
+
16
+ <!-- nina:slot edge-cf.5 -->
17
+ | Author or modify `wrangler.toml` / `wrangler.jsonc` / run any `wrangler` CLI command | `cloudflare:wrangler` | CLI flags + config fields churn between minor versions |
18
+
19
+ <!-- nina:slot edge-cf.6 -->
20
+ | Run the **devops** deploy stage | `cloudflare:wrangler` (+ `cloudflare:cloudflare` for R2/KV/Queues/DO bindings) | deploy flags and binding config churn between versions |
21
+
22
+ <!-- nina:slot edge-cf.7 -->
23
+
24
+ The plugin's other skills — `cloudflare:agents-sdk`, `cloudflare:sandbox-sdk`, `cloudflare:cloudflare-email-service` — apply only where {{PROJECT}} adopts what they cover: an agent runtime, untrusted code execution, sending mail.
25
+
26
+ **Wrangler calls out on its own.** Wrangler 4 checks npm for a newer version whenever it prints its banner, a warning or an error, honouring no opt-out, and sends telemetry unless told not to. Every run of it, or of a process that loads it (`getPlatformProxy`), sets `WRANGLER_HIDE_BANNER=true npm_registry=http://127.0.0.1:9 CLOUDFLARE_CF_FETCH_ENABLED=false WRANGLER_SEND_METRICS=false` — `npm_registry`, since wrangler reads it through `rc("npm")`, which strips the `npm_` prefix, so `npm_config_registry` sets nothing — and the wrangler config says `send_metrics: false`. The project's own scripts that start wrangler set them, so no run depends on a stage remembering them and no task runner drops them. A run that prints "update available" reached the network: its report says so.<!-- nina:why --> Learned three times in the third project: a dba's "local only" migration, a reviewer's typecheck and an implementer's turbo run each printed "update available", and the registry variable the lesson first named was the one wrangler does not read.<!-- /nina:why -->
27
+
28
+ <!-- nina:slot edge-cf.8 -->
29
+ 10. **Secrets in `{{SECRETS_LOCAL}}` for local dev, `{{SECRETS_PROD}}` for production.** Never `.env` committed. `nodejs_compat` is required in the `compatibility_flags` of the wrangler config (`wrangler.jsonc` or `wrangler.toml`) for any database client that runs at the edge.
@@ -0,0 +1,20 @@
1
+ <!-- nina:slot frontend.1 -->
2
+ | `cloudflare:web-perf` | a page-load performance question in `{{APP_DIR}}` |
3
+
4
+ <!-- nina:slot frontend.2 -->
5
+
6
+ ## Visual acceptance — required in any spec touching `{{APP_DIR}}/**`
7
+
8
+ A frontend spec that describes only structure produces a diff that only structure can verify, and
9
+ structure is exactly what a test renderer checks while blind to the result. So state, as a short
10
+ checklist, what must be TRUE ON THE SCREEN at **1440** and at **375**:
11
+
12
+ - what is visible, and what must not be
13
+ - what sits beside what, and what wraps or stacks at 375
14
+ - the empty, loading and error states, if the change can produce them
15
+ - anything that must not overflow, clip or overlap
16
+
17
+ Each line must be checkable from a screenshot by someone who did not write the code — the **reviewer**
18
+ checks the render against this list, and rejects on a mismatch. "Follows the design system" is not a
19
+ criterion. A spec that touches `{{APP_DIR}}/**` without this section is incomplete, and the reviewer
20
+ rejects it back to you.