@xhulz/nina 0.29.0 → 0.31.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 (240) hide show
  1. package/README.md +3 -2
  2. package/package.json +1 -1
  3. package/releases/0.30.0/core/GAPS.md +125 -0
  4. package/releases/0.30.0/core/answered.json +29 -0
  5. package/releases/0.30.0/core/defaults/tree/.claude/agents/architect.md +1 -0
  6. package/releases/0.30.0/core/defaults/tree/.claude/agents/dba.md +3 -0
  7. package/releases/0.30.0/core/defaults/tree/.claude/agents/devops.md +1 -0
  8. package/releases/0.30.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
  9. package/releases/0.30.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
  10. package/releases/0.30.0/core/defaults/tree/.claude/agents/qa.md +2 -0
  11. package/releases/0.30.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
  12. package/releases/0.30.0/core/defaults/tree/.claude/agents/secops.md +3 -0
  13. package/releases/0.30.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
  14. package/releases/0.30.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
  15. package/releases/0.30.0/core/tree/.claude/agents/architect.md +126 -0
  16. package/releases/0.30.0/core/tree/.claude/agents/dba.md +107 -0
  17. package/releases/0.30.0/core/tree/.claude/agents/devops.md +113 -0
  18. package/releases/0.30.0/core/tree/.claude/agents/implementer.md +155 -0
  19. package/releases/0.30.0/core/tree/.claude/agents/integration-tester.md +168 -0
  20. package/releases/0.30.0/core/tree/.claude/agents/planner.md +132 -0
  21. package/releases/0.30.0/core/tree/.claude/agents/qa.md +148 -0
  22. package/releases/0.30.0/core/tree/.claude/agents/reviewer.md +183 -0
  23. package/releases/0.30.0/core/tree/.claude/agents/secops.md +121 -0
  24. package/releases/0.30.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
  25. package/releases/0.30.0/core/tree/.claude/agents/solidity-dev.md +123 -0
  26. package/releases/0.30.0/core/tree/.claude/agents-overview.md +64 -0
  27. package/releases/0.30.0/core/tree/.claude/graph.md +75 -0
  28. package/releases/0.30.0/core/tree/.claude/patterns.md +212 -0
  29. package/releases/0.30.0/core/tree/.claude/pills/README.md +145 -0
  30. package/releases/0.30.0/core/tree/.claude/pipeline.md +101 -0
  31. package/releases/0.30.0/core/tree/.claude/retrieval.md +104 -0
  32. package/releases/0.30.0/core/tree/.claude/router.md +195 -0
  33. package/releases/0.30.0/core/tree/.claude/templates/integration.md +45 -0
  34. package/releases/0.30.0/core/tree/CLAUDE.md +160 -0
  35. package/releases/0.30.0/core/tree/scripts/edit-guard.mjs +16 -0
  36. package/releases/0.30.0/core/tree/scripts/harness-check.mjs +71 -0
  37. package/releases/0.30.0/core/tree/scripts/loop-gate.mjs +19 -0
  38. package/releases/0.30.0/core/vocabulary.json +12 -0
  39. package/releases/0.30.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
  40. package/releases/0.30.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
  41. package/releases/0.30.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
  42. package/releases/0.30.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
  43. package/releases/0.30.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
  44. package/releases/0.30.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
  45. package/releases/0.30.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
  46. package/releases/0.30.0/surfaces/blockchain/tree/.claude/router.md +6 -0
  47. package/releases/0.30.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
  48. package/releases/0.30.0/surfaces/db/tree/.claude/agents/architect.md +8 -0
  49. package/releases/0.30.0/surfaces/db/tree/.claude/agents/dba.md +84 -0
  50. package/releases/0.30.0/surfaces/db/tree/.claude/agents/devops.md +14 -0
  51. package/releases/0.30.0/surfaces/db/tree/.claude/agents/implementer.md +5 -0
  52. package/releases/0.30.0/surfaces/db/tree/.claude/agents/integration-tester.md +13 -0
  53. package/releases/0.30.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
  54. package/releases/0.30.0/surfaces/db/tree/.claude/agents/reviewer.md +25 -0
  55. package/releases/0.30.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
  56. package/releases/0.30.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
  57. package/releases/0.30.0/surfaces/db/tree/.claude/graph.md +8 -0
  58. package/releases/0.30.0/surfaces/db/tree/.claude/patterns.md +29 -0
  59. package/releases/0.30.0/surfaces/db/tree/.claude/pipeline.md +13 -0
  60. package/releases/0.30.0/surfaces/db/tree/.claude/retrieval.md +5 -0
  61. package/releases/0.30.0/surfaces/db/tree/.claude/router.md +4 -0
  62. package/releases/0.30.0/surfaces/db/tree/CLAUDE.md +23 -0
  63. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
  64. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
  65. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/agents/devops.md +31 -0
  66. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
  67. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
  68. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
  69. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
  70. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
  71. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
  72. package/releases/0.30.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
  73. package/releases/0.30.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
  74. package/releases/0.30.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
  75. package/releases/0.30.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
  76. package/releases/0.30.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
  77. package/releases/0.30.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
  78. package/releases/0.30.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
  79. package/releases/0.30.0/surfaces/frontend/tree/.claude/patterns.md +15 -0
  80. package/releases/0.30.0/surfaces/frontend/tree/.claude/retrieval.md +5 -0
  81. package/releases/0.30.0/surfaces/frontend/tree/.claude/router.md +14 -0
  82. package/releases/0.30.0/surfaces/frontend/tree/CLAUDE.md +5 -0
  83. package/releases/0.30.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
  84. package/releases/0.30.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
  85. package/releases/0.30.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
  86. package/releases/0.30.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
  87. package/releases/0.30.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
  88. package/releases/0.30.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
  89. package/releases/0.30.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
  90. package/releases/0.30.0/surfaces/integrations/tree/.claude/graph.md +10 -0
  91. package/releases/0.30.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
  92. package/releases/0.30.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
  93. package/releases/0.30.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
  94. package/releases/0.30.0/surfaces/integrations/tree/.claude/router.md +6 -0
  95. package/releases/0.30.0/surfaces/integrations/tree/CLAUDE.md +17 -0
  96. package/releases/0.30.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
  97. package/releases/0.30.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
  98. package/releases/0.30.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
  99. package/releases/0.30.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
  100. package/releases/0.30.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
  101. package/releases/0.30.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
  102. package/releases/0.30.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
  103. package/releases/0.30.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
  104. package/releases/0.30.0/surfaces/money/tree/.claude/graph.md +2 -0
  105. package/releases/0.30.0/surfaces/money/tree/.claude/patterns.md +49 -0
  106. package/releases/0.30.0/surfaces/money/tree/.claude/pipeline.md +2 -0
  107. package/releases/0.30.0/surfaces/money/tree/.claude/retrieval.md +2 -0
  108. package/releases/0.30.0/surfaces/money/tree/CLAUDE.md +11 -0
  109. package/releases/0.30.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
  110. package/releases/0.30.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
  111. package/releases/0.30.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
  112. package/releases/0.30.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
  113. package/releases/0.30.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
  114. package/releases/0.30.0/surfaces/pii/tree/CLAUDE.md +5 -0
  115. package/releases/0.31.0/core/GAPS.md +125 -0
  116. package/releases/0.31.0/core/answered.json +29 -0
  117. package/releases/0.31.0/core/defaults/tree/.claude/agents/architect.md +1 -0
  118. package/releases/0.31.0/core/defaults/tree/.claude/agents/dba.md +3 -0
  119. package/releases/0.31.0/core/defaults/tree/.claude/agents/devops.md +1 -0
  120. package/releases/0.31.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
  121. package/releases/0.31.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
  122. package/releases/0.31.0/core/defaults/tree/.claude/agents/qa.md +2 -0
  123. package/releases/0.31.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
  124. package/releases/0.31.0/core/defaults/tree/.claude/agents/secops.md +3 -0
  125. package/releases/0.31.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
  126. package/releases/0.31.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
  127. package/releases/0.31.0/core/tree/.claude/agents/architect.md +126 -0
  128. package/releases/0.31.0/core/tree/.claude/agents/dba.md +110 -0
  129. package/releases/0.31.0/core/tree/.claude/agents/devops.md +114 -0
  130. package/releases/0.31.0/core/tree/.claude/agents/implementer.md +155 -0
  131. package/releases/0.31.0/core/tree/.claude/agents/integration-tester.md +168 -0
  132. package/releases/0.31.0/core/tree/.claude/agents/planner.md +132 -0
  133. package/releases/0.31.0/core/tree/.claude/agents/qa.md +148 -0
  134. package/releases/0.31.0/core/tree/.claude/agents/reviewer.md +183 -0
  135. package/releases/0.31.0/core/tree/.claude/agents/secops.md +121 -0
  136. package/releases/0.31.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
  137. package/releases/0.31.0/core/tree/.claude/agents/solidity-dev.md +123 -0
  138. package/releases/0.31.0/core/tree/.claude/agents-overview.md +64 -0
  139. package/releases/0.31.0/core/tree/.claude/frontend.md +10 -0
  140. package/releases/0.31.0/core/tree/.claude/graph.md +75 -0
  141. package/releases/0.31.0/core/tree/.claude/patterns.md +213 -0
  142. package/releases/0.31.0/core/tree/.claude/pills/README.md +145 -0
  143. package/releases/0.31.0/core/tree/.claude/pipeline.md +101 -0
  144. package/releases/0.31.0/core/tree/.claude/retrieval.md +103 -0
  145. package/releases/0.31.0/core/tree/.claude/router.md +195 -0
  146. package/releases/0.31.0/core/tree/.claude/templates/integration.md +45 -0
  147. package/releases/0.31.0/core/tree/CLAUDE.md +160 -0
  148. package/releases/0.31.0/core/tree/scripts/edit-guard.mjs +16 -0
  149. package/releases/0.31.0/core/tree/scripts/harness-check.mjs +71 -0
  150. package/releases/0.31.0/core/tree/scripts/loop-gate.mjs +19 -0
  151. package/releases/0.31.0/core/vocabulary.json +12 -0
  152. package/releases/0.31.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
  153. package/releases/0.31.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
  154. package/releases/0.31.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
  155. package/releases/0.31.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
  156. package/releases/0.31.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
  157. package/releases/0.31.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
  158. package/releases/0.31.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
  159. package/releases/0.31.0/surfaces/blockchain/tree/.claude/router.md +6 -0
  160. package/releases/0.31.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
  161. package/releases/0.31.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
  162. package/releases/0.31.0/surfaces/db/tree/.claude/agents/dba.md +50 -0
  163. package/releases/0.31.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
  164. package/releases/0.31.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
  165. package/releases/0.31.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
  166. package/releases/0.31.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
  167. package/releases/0.31.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
  168. package/releases/0.31.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
  169. package/releases/0.31.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
  170. package/releases/0.31.0/surfaces/db/tree/.claude/graph.md +8 -0
  171. package/releases/0.31.0/surfaces/db/tree/.claude/patterns.md +19 -0
  172. package/releases/0.31.0/surfaces/db/tree/.claude/pipeline.md +13 -0
  173. package/releases/0.31.0/surfaces/db/tree/.claude/retrieval.md +5 -0
  174. package/releases/0.31.0/surfaces/db/tree/.claude/router.md +4 -0
  175. package/releases/0.31.0/surfaces/db/tree/CLAUDE.md +17 -0
  176. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
  177. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
  178. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/agents/devops.md +32 -0
  179. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
  180. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
  181. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
  182. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
  183. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
  184. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
  185. package/releases/0.31.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
  186. package/releases/0.31.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
  187. package/releases/0.31.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
  188. package/releases/0.31.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
  189. package/releases/0.31.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
  190. package/releases/0.31.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
  191. package/releases/0.31.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
  192. package/releases/0.31.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
  193. package/releases/0.31.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
  194. package/releases/0.31.0/surfaces/frontend/tree/.claude/router.md +14 -0
  195. package/releases/0.31.0/surfaces/frontend/tree/CLAUDE.md +5 -0
  196. package/releases/0.31.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
  197. package/releases/0.31.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
  198. package/releases/0.31.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
  199. package/releases/0.31.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
  200. package/releases/0.31.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
  201. package/releases/0.31.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
  202. package/releases/0.31.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
  203. package/releases/0.31.0/surfaces/integrations/tree/.claude/graph.md +10 -0
  204. package/releases/0.31.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
  205. package/releases/0.31.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
  206. package/releases/0.31.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
  207. package/releases/0.31.0/surfaces/integrations/tree/.claude/router.md +6 -0
  208. package/releases/0.31.0/surfaces/integrations/tree/CLAUDE.md +17 -0
  209. package/releases/0.31.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
  210. package/releases/0.31.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
  211. package/releases/0.31.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
  212. package/releases/0.31.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
  213. package/releases/0.31.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
  214. package/releases/0.31.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
  215. package/releases/0.31.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
  216. package/releases/0.31.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
  217. package/releases/0.31.0/surfaces/money/tree/.claude/graph.md +2 -0
  218. package/releases/0.31.0/surfaces/money/tree/.claude/patterns.md +49 -0
  219. package/releases/0.31.0/surfaces/money/tree/.claude/pipeline.md +2 -0
  220. package/releases/0.31.0/surfaces/money/tree/.claude/retrieval.md +2 -0
  221. package/releases/0.31.0/surfaces/money/tree/CLAUDE.md +11 -0
  222. package/releases/0.31.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
  223. package/releases/0.31.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
  224. package/releases/0.31.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
  225. package/releases/0.31.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
  226. package/releases/0.31.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
  227. package/releases/0.31.0/surfaces/pii/tree/CLAUDE.md +5 -0
  228. package/releases/0.31.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
  229. package/releases/0.31.0/surfaces/prisma/tree/.claude/agents/dba.md +39 -0
  230. package/releases/0.31.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
  231. package/releases/0.31.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
  232. package/releases/0.31.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
  233. package/releases/0.31.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
  234. package/releases/0.31.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
  235. package/releases/0.31.0/surfaces/prisma/tree/CLAUDE.md +5 -0
  236. package/src/commands/check.mjs +2 -0
  237. package/src/commands/init.mjs +11 -12
  238. package/src/commands/pipeline.mjs +8 -3
  239. package/src/commands/upgrade.mjs +15 -2
  240. package/src/surfaces.mjs +33 -0
@@ -52,7 +52,7 @@ export function stageWords(text) {
52
52
  * - The line: from the first stage no forward edge reaches, the one forward edge each stage takes with no
53
53
  * condition, until a stage has none.
54
54
  * - The gates: a stage off the line that a line stage sends work to on a condition, and that hands it on
55
- * to the next stage of the line.
55
+ * to a later stage of the line — the next one, or one past the stages it runs beside.
56
56
  * - The ends: where the line's last stage sends work on a condition, followed forward to a terminal.
57
57
  * - The loop-backs: every edge on a verdict that sends work back, to a stage or to the owner, grouped by
58
58
  * the stage that sends it.
@@ -70,10 +70,14 @@ export function shapeOf(graph) {
70
70
  if (next.length !== 1) break;
71
71
  line.push(next[0].to);
72
72
  }
73
+ // A gate leaves the line on a condition and comes back to it further on: to the next stage, when it runs
74
+ // before that stage, or past it, when it runs beside the stages it skips — the way the database and
75
+ // integration gates run beside the reviewer, and `qa` waits for them all.
73
76
  const gates = [];
74
77
  line.forEach((stage, i) => {
75
78
  for (const e of forward.filter((e) => e.from === stage && e.when && !line.includes(e.to) && !TERMINALS.has(e.to))) {
76
- if (i + 1 < line.length && forward.some((f) => f.from === e.to && f.to === line[i + 1])) gates.push({ from: stage, gate: e.to, to: line[i + 1], when: e.when });
79
+ const back = line.findIndex((s, j) => j > i && forward.some((f) => f.from === e.to && f.to === s));
80
+ if (back !== -1) gates.push({ from: stage, gate: e.to, to: line[back], beside: line.slice(i + 1, back), when: e.when });
77
81
  }
78
82
  });
79
83
  const last = line.at(-1);
@@ -248,7 +252,8 @@ export async function pipeline(argv) {
248
252
  const chain = (g) => `${g.from}${arrow}${g.gate}${arrow}${g.to}`;
249
253
  const col = Math.max(...shape.gates.map((g) => chain(g).length)) + 4;
250
254
  for (const g of shape.gates) {
251
- console.log(` ${name(g.from)}${arrow}${name(g.gate)}${arrow}${name(g.to)}${' '.repeat(col - chain(g).length)}${dim(fit(g.when, width - col - 6))}`);
255
+ const when = g.beside.length > 0 ? `beside the ${g.beside.join(', ')} · ${g.when}` : g.when;
256
+ console.log(` ${name(g.from)}${arrow}${name(g.gate)}${arrow}${name(g.to)}${' '.repeat(col - chain(g).length)}${dim(fit(when, width - col - 6))}`);
252
257
  }
253
258
  }
254
259
  }
@@ -15,7 +15,8 @@ import { spawnSync } from 'node:child_process';
15
15
  import { HARNESS, legacyHint } from '../paths.mjs';
16
16
  import { existsSync, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
17
17
  import { dirname, join, resolve } from 'node:path';
18
- import { composeProject, composedPaths, defaultedSlots, layerRootFor } from './compose.mjs';
18
+ import { composeProject, composedPaths, defaultedSlots, layerRootFor, walk } from './compose.mjs';
19
+ import { NEEDS, detected } from '../surfaces.mjs';
19
20
  import { filledSlots, projectSlots, referencedVocabulary } from './check.mjs';
20
21
  import { EXPECT_ENV } from '../expected.mjs';
21
22
  import { closeAnswered } from './learn.mjs';
@@ -213,6 +214,13 @@ export async function upgrade(argv, ctx) {
213
214
  .map((e) => e.name);
214
215
  const gone = surfaces.filter((s) => !available.includes(s));
215
216
  const kept = surfaces.filter((s) => available.includes(s));
217
+ // A surface the target release adds that this project's own files show it has. When a stack is split out
218
+ // of a concern — `prisma` out of `db` — its rules go with it, and a project that does not declare it loses
219
+ // them in silence: the rules that were in its specs yesterday are not there after the move.
220
+ const offeredBefore = (await readdir(join(from.dir, 'surfaces'), { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
221
+ const offered = detected(await walk(target)).filter(
222
+ (d) => available.includes(d.surface) && !offeredBefore.includes(d.surface) && !surfaces.includes(d.surface) && (!NEEDS[d.surface] || kept.includes(NEEDS[d.surface])),
223
+ );
216
224
 
217
225
  const [vocabBefore, vocabAfter] = [
218
226
  await referencedVocabulary(from.dir, surfaces, target),
@@ -236,6 +244,11 @@ export async function upgrade(argv, ctx) {
236
244
 
237
245
  console.log(` ${profile.core} → ${to}\n`);
238
246
 
247
+ if (offered.length > 0) {
248
+ console.log(` ✗ ${offered.length} surface(s) ${to} adds that this project's files show it has — undeclared, their rules leave its specs:`);
249
+ for (const d of offered) console.log(` ${d.surface} — ${d.why}`);
250
+ console.log(` add each to "surfaces" in ${HARNESS}/profile.json, or pass --force to move without them.\n`);
251
+ }
239
252
  if (gone.length > 0) {
240
253
  console.log(` ✗ ${gone.length} declared surface(s) do not exist in ${to}: ${gone.join(', ')}`);
241
254
  console.log(` a rename cannot be guessed — pick the replacement yourself, and move the`);
@@ -309,7 +322,7 @@ export async function upgrade(argv, ctx) {
309
322
  console.log('');
310
323
  }
311
324
 
312
- const blocking = gone.length + stranded.length + unwired.length + occupied.length + walledOff.length;
325
+ const blocking = gone.length + offered.length + stranded.length + unwired.length + occupied.length + walledOff.length;
313
326
  if (!apply) {
314
327
  console.log(
315
328
  blocking > 0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * What the compiler knows about surfaces beyond their layers: which ones a repository's files reveal, and
3
+ * which ones only make sense on top of another.
4
+ *
5
+ * A surface is a question about what the project is — does it own persistent data, does it render a screen
6
+ * a person looks at — and its layer states what is true of every project that answers yes. A stack is a
7
+ * surface too, of another kind: `prisma` is how a project reaches the database it owns, and means nothing
8
+ * without one. The database surface used to be both at once, and a project that owned data but had not
9
+ * chosen its client was told its client was Prisma, its reads went through Accelerate and its tenant was
10
+ * `userId`.
11
+ *
12
+ * `init`, `check` and `upgrade` all read this, so a surface's evidence and its prerequisite are stated once.
13
+ */
14
+
15
+ /** Surfaces a repository reveals by its files. The rest are claims about the domain. */
16
+ export const DETECTABLE = [
17
+ { surface: 'db', why: 'a Prisma schema', test: (f) => f.some((p) => p.endsWith('schema.prisma')) },
18
+ { surface: 'prisma', why: 'a Prisma schema', test: (f) => f.some((p) => p.endsWith('schema.prisma')) },
19
+ { surface: 'edge-cf', why: 'a wrangler config', test: (f) => f.some((p) => /(^|\/)wrangler\.(toml|jsonc?)$/.test(p)) },
20
+ { surface: 'frontend', why: 'a Vite config', test: (f) => f.some((p) => /(^|\/)vite\.config\.[cm]?[jt]s$/.test(p)) },
21
+ { surface: 'blockchain', why: 'a Foundry or Hardhat config', test: (f) => f.some((p) => /(^|\/)(foundry\.toml|hardhat\.config\.[cm]?[jt]s)$/.test(p)) },
22
+ ];
23
+
24
+ /** A stack surface, and the concern it is a stack of: declared without it, its rules have nowhere to land. */
25
+ export const NEEDS = { prisma: 'db' };
26
+
27
+ /**
28
+ * The surfaces a project's files reveal, with the evidence for each.
29
+ *
30
+ * @param {string[]} tree - The project's files, relative to it.
31
+ * @returns {{surface: string, why: string}[]}
32
+ */
33
+ export const detected = (tree) => DETECTABLE.filter((d) => d.test(tree)).map(({ surface, why }) => ({ surface, why }));