codetrellis 0.0.0-stage → 0.3.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 (448) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +27 -2
  3. package/bin/codetrellis.mjs +4 -0
  4. package/package.json +41 -4
  5. package/reader/material-reader.mjs +130346 -0
  6. package/resources/tree-sitter/README.md +150 -0
  7. package/resources/tree-sitter/tree-sitter-c-sharp.wasm +0 -0
  8. package/resources/tree-sitter/tree-sitter-go.wasm +0 -0
  9. package/resources/tree-sitter/tree-sitter-java.wasm +0 -0
  10. package/resources/tree-sitter/tree-sitter-javascript.wasm +0 -0
  11. package/resources/tree-sitter/tree-sitter-kotlin.wasm +0 -0
  12. package/resources/tree-sitter/tree-sitter-php.wasm +0 -0
  13. package/resources/tree-sitter/tree-sitter-python.wasm +0 -0
  14. package/resources/tree-sitter/tree-sitter-ruby.wasm +0 -0
  15. package/resources/tree-sitter/tree-sitter-rust.wasm +0 -0
  16. package/resources/tree-sitter/tree-sitter-swift.wasm +0 -0
  17. package/resources/tree-sitter/tree-sitter-tsx.wasm +0 -0
  18. package/resources/tree-sitter/tree-sitter-typescript.wasm +0 -0
  19. package/resources/tree-sitter/tree-sitter.wasm +0 -0
  20. package/src/backend/agent/claude-code-watcher.js +270 -0
  21. package/src/backend/index.js +8 -0
  22. package/src/backend/lib/sha256-file.js +39 -0
  23. package/src/backend/lib/zip-entries.js +98 -0
  24. package/src/backend/lifecycle.js +102 -0
  25. package/src/backend/mcp/binding-headers.js +54 -0
  26. package/src/backend/mcp/client-identity.js +44 -0
  27. package/src/backend/mcp/connector/command.js +110 -0
  28. package/src/backend/mcp/connector/core.js +278 -0
  29. package/src/backend/mcp/connector/files.js +121 -0
  30. package/src/backend/mcp/connector/hook.js +284 -0
  31. package/src/backend/mcp/connector/main.js +126 -0
  32. package/src/backend/mcp/connector/sse-upstream.js +152 -0
  33. package/src/backend/mcp/helpers.js +43 -0
  34. package/src/backend/mcp/prompt-builders.js +104 -0
  35. package/src/backend/mcp/resources.js +197 -0
  36. package/src/backend/mcp/server.js +813 -0
  37. package/src/backend/mcp/skill-guide.js +1528 -0
  38. package/src/backend/mcp/tools/architecture-tools.js +273 -0
  39. package/src/backend/mcp/tools/audio-tools.js +117 -0
  40. package/src/backend/mcp/tools/awareness-tools.js +623 -0
  41. package/src/backend/mcp/tools/budget-tools.js +185 -0
  42. package/src/backend/mcp/tools/channel-tools.js +205 -0
  43. package/src/backend/mcp/tools/contribution-tools.js +181 -0
  44. package/src/backend/mcp/tools/drift-tools.js +252 -0
  45. package/src/backend/mcp/tools/git-tools.js +316 -0
  46. package/src/backend/mcp/tools/governance-tools.js +175 -0
  47. package/src/backend/mcp/tools/graph-tools.js +181 -0
  48. package/src/backend/mcp/tools/intake-tools.js +244 -0
  49. package/src/backend/mcp/tools/mobile-tools.js +118 -0
  50. package/src/backend/mcp/tools/peer-tools.js +330 -0
  51. package/src/backend/mcp/tools/plan-item-tools.js +1601 -0
  52. package/src/backend/mcp/tools/plan-tools.js +680 -0
  53. package/src/backend/mcp/tools/presence-tools.js +185 -0
  54. package/src/backend/mcp/tools/project-config-tools.js +150 -0
  55. package/src/backend/mcp/tools/review-tools.js +172 -0
  56. package/src/backend/mcp/tools/session-tools.js +554 -0
  57. package/src/backend/mcp/tools/system-docs-tools.js +168 -0
  58. package/src/backend/mcp/tools/terminal-tools.js +186 -0
  59. package/src/backend/mcp/tools/test-tools.js +117 -0
  60. package/src/backend/mcp/tools/ui-tools.js +356 -0
  61. package/src/backend/mcp/types.js +15 -0
  62. package/src/backend/middleware/local-auth.js +116 -0
  63. package/src/backend/server.js +5951 -0
  64. package/src/backend/services/agent-event-log.js +350 -0
  65. package/src/backend/services/architecture-rule.js +584 -0
  66. package/src/backend/services/architecture-rules.js +275 -0
  67. package/src/backend/services/artefact-content-service.js +181 -0
  68. package/src/backend/services/artefact-service.js +305 -0
  69. package/src/backend/services/artefact-watcher.js +167 -0
  70. package/src/backend/services/ast-parser.js +327 -0
  71. package/src/backend/services/audio-buffer-service.js +152 -0
  72. package/src/backend/services/awareness-notices.js +139 -0
  73. package/src/backend/services/awareness-replies.js +194 -0
  74. package/src/backend/services/awareness-service.js +344 -0
  75. package/src/backend/services/awareness-signals.js +267 -0
  76. package/src/backend/services/baseline-store.js +83 -0
  77. package/src/backend/services/branch-workstreams.js +341 -0
  78. package/src/backend/services/breakpoint-service.js +584 -0
  79. package/src/backend/services/brief-service.js +299 -0
  80. package/src/backend/services/budget-service.js +528 -0
  81. package/src/backend/services/callsites/base.js +15 -0
  82. package/src/backend/services/callsites/csharp.js +148 -0
  83. package/src/backend/services/callsites/go.js +163 -0
  84. package/src/backend/services/callsites/index.js +53 -0
  85. package/src/backend/services/callsites/kotlin.js +123 -0
  86. package/src/backend/services/callsites/process-env.js +125 -0
  87. package/src/backend/services/callsites/python.js +91 -0
  88. package/src/backend/services/callsites/ruby.js +164 -0
  89. package/src/backend/services/callsites/shared.js +198 -0
  90. package/src/backend/services/callsites/swift.js +115 -0
  91. package/src/backend/services/callsites/typescript.js +87 -0
  92. package/src/backend/services/capability-token.js +108 -0
  93. package/src/backend/services/change-check.js +156 -0
  94. package/src/backend/services/channel-dispatcher-service.js +235 -0
  95. package/src/backend/services/channel-event-file-service.js +125 -0
  96. package/src/backend/services/channel-event-service.js +297 -0
  97. package/src/backend/services/check-runs.js +177 -0
  98. package/src/backend/services/checkout-identity.js +73 -0
  99. package/src/backend/services/claude-code-parallel.js +221 -0
  100. package/src/backend/services/claude-desktop-config.js +186 -0
  101. package/src/backend/services/cli-install.js +249 -0
  102. package/src/backend/services/clock.js +57 -0
  103. package/src/backend/services/cloud-files.js +191 -0
  104. package/src/backend/services/coalesce.js +50 -0
  105. package/src/backend/services/code-breakpoints.js +291 -0
  106. package/src/backend/services/comment-service.js +168 -0
  107. package/src/backend/services/commit-attribution.js +134 -0
  108. package/src/backend/services/commit-edges.js +99 -0
  109. package/src/backend/services/confined-fs.js +241 -0
  110. package/src/backend/services/conformity-gate.js +132 -0
  111. package/src/backend/services/contribution-service.js +409 -0
  112. package/src/backend/services/coverage-service.js +173 -0
  113. package/src/backend/services/criteria-service.js +721 -0
  114. package/src/backend/services/criterion-checks.js +387 -0
  115. package/src/backend/services/criterion-loop-service.js +411 -0
  116. package/src/backend/services/cross-system-service.js +231 -0
  117. package/src/backend/services/database.js +916 -0
  118. package/src/backend/services/db-schema.js +1358 -0
  119. package/src/backend/services/deviation-service.js +344 -0
  120. package/src/backend/services/diff-engine.js +168 -0
  121. package/src/backend/services/evidence.js +363 -0
  122. package/src/backend/services/external-intake-service.js +269 -0
  123. package/src/backend/services/external-pointer-service.js +195 -0
  124. package/src/backend/services/external-refs-service.js +214 -0
  125. package/src/backend/services/file-history.js +158 -0
  126. package/src/backend/services/file-watcher.js +193 -0
  127. package/src/backend/services/folder-requests.js +118 -0
  128. package/src/backend/services/freeze-service.js +189 -0
  129. package/src/backend/services/gemini-cli-hook.js +172 -0
  130. package/src/backend/services/git-activity-service.js +325 -0
  131. package/src/backend/services/git-blobs.js +70 -0
  132. package/src/backend/services/git-branches.js +357 -0
  133. package/src/backend/services/git-checkout.js +153 -0
  134. package/src/backend/services/git-commit-service.js +91 -0
  135. package/src/backend/services/git-env.js +121 -0
  136. package/src/backend/services/git-identity.js +84 -0
  137. package/src/backend/services/git-refs.js +386 -0
  138. package/src/backend/services/git-safety.js +58 -0
  139. package/src/backend/services/grant-guard.js +67 -0
  140. package/src/backend/services/html-view-policy.js +135 -0
  141. package/src/backend/services/human-decision.js +55 -0
  142. package/src/backend/services/importers.js +159 -0
  143. package/src/backend/services/intent-service.js +105 -0
  144. package/src/backend/services/ipc-dispatcher.js +164 -0
  145. package/src/backend/services/item-git-state.js +208 -0
  146. package/src/backend/services/line-changes.js +232 -0
  147. package/src/backend/services/line-history.js +174 -0
  148. package/src/backend/services/local-api-changes.js +40 -0
  149. package/src/backend/services/logger.js +217 -0
  150. package/src/backend/services/material-footprints.js +203 -0
  151. package/src/backend/services/material-place.js +82 -0
  152. package/src/backend/services/material-reader/docx-markdown.js +198 -0
  153. package/src/backend/services/material-reader/fixtures.test-helper.js +169 -0
  154. package/src/backend/services/material-reader/quote.js +44 -0
  155. package/src/backend/services/material-reader/reader-host.js +202 -0
  156. package/src/backend/services/material-signals.js +141 -0
  157. package/src/backend/services/mcp-capabilities.js +390 -0
  158. package/src/backend/services/mdns-service.js +304 -0
  159. package/src/backend/services/mobile-api-server.js +281 -0
  160. package/src/backend/services/mobile-approvals.js +306 -0
  161. package/src/backend/services/mobile-awareness.js +180 -0
  162. package/src/backend/services/mobile-breakpoints.js +115 -0
  163. package/src/backend/services/mobile-budget.js +98 -0
  164. package/src/backend/services/mobile-freeze.js +106 -0
  165. package/src/backend/services/mobile-proposals.js +100 -0
  166. package/src/backend/services/mobile-rpc-service.js +1289 -0
  167. package/src/backend/services/mobile-workstreams.js +160 -0
  168. package/src/backend/services/monorepo-detector.js +131 -0
  169. package/src/backend/services/other-work.js +45 -0
  170. package/src/backend/services/pack-seal.js +129 -0
  171. package/src/backend/services/paired-device-service.js +192 -0
  172. package/src/backend/services/pairing-server.js +323 -0
  173. package/src/backend/services/pairing-service.js +200 -0
  174. package/src/backend/services/pantry-resolution-service.js +166 -0
  175. package/src/backend/services/parsers/base.js +124 -0
  176. package/src/backend/services/parsers/csharp.js +224 -0
  177. package/src/backend/services/parsers/go.js +180 -0
  178. package/src/backend/services/parsers/index.js +101 -0
  179. package/src/backend/services/parsers/java.js +103 -0
  180. package/src/backend/services/parsers/kotlin.js +252 -0
  181. package/src/backend/services/parsers/php.js +113 -0
  182. package/src/backend/services/parsers/python.js +189 -0
  183. package/src/backend/services/parsers/ruby.js +212 -0
  184. package/src/backend/services/parsers/rust.js +97 -0
  185. package/src/backend/services/parsers/swift.js +221 -0
  186. package/src/backend/services/parsers/typescript.js +235 -0
  187. package/src/backend/services/pattern-scan.js +65 -0
  188. package/src/backend/services/patterns.js +281 -0
  189. package/src/backend/services/peer-audit-service.js +123 -0
  190. package/src/backend/services/peer-auth.js +153 -0
  191. package/src/backend/services/peer-capabilities.js +209 -0
  192. package/src/backend/services/peer-connection-service.js +450 -0
  193. package/src/backend/services/peer-grants.js +33 -0
  194. package/src/backend/services/persistence.js +116 -0
  195. package/src/backend/services/personal-sync-service.js +232 -0
  196. package/src/backend/services/pipeline-approvals.js +72 -0
  197. package/src/backend/services/pipeline.js +232 -0
  198. package/src/backend/services/plan-arrivals.js +68 -0
  199. package/src/backend/services/plan-changes-service.js +273 -0
  200. package/src/backend/services/plan-conflict-service.js +288 -0
  201. package/src/backend/services/plan-dependencies.js +91 -0
  202. package/src/backend/services/plan-doc-guard.js +90 -0
  203. package/src/backend/services/plan-documents-service.js +275 -0
  204. package/src/backend/services/plan-event-service.js +154 -0
  205. package/src/backend/services/plan-file-refs.js +106 -0
  206. package/src/backend/services/plan-file-service.js +1564 -0
  207. package/src/backend/services/plan-history-service.js +156 -0
  208. package/src/backend/services/plan-import-service.js +261 -0
  209. package/src/backend/services/plan-item-service.js +1223 -0
  210. package/src/backend/services/plan-migrate-service.js +395 -0
  211. package/src/backend/services/plan-overlay-service.js +173 -0
  212. package/src/backend/services/plan-phases-service.js +182 -0
  213. package/src/backend/services/plan-progress-service.js +134 -0
  214. package/src/backend/services/plan-review-service.js +262 -0
  215. package/src/backend/services/plan-service.js +682 -0
  216. package/src/backend/services/plan-status.js +113 -0
  217. package/src/backend/services/plan-template-publish-service.js +217 -0
  218. package/src/backend/services/plan-templates-service.js +242 -0
  219. package/src/backend/services/plan-templates.js +1164 -0
  220. package/src/backend/services/planned-overlap-actions.js +200 -0
  221. package/src/backend/services/plans-home.js +224 -0
  222. package/src/backend/services/play-forward.js +256 -0
  223. package/src/backend/services/playback-service.js +117 -0
  224. package/src/backend/services/power-service.js +167 -0
  225. package/src/backend/services/power-signals.js +81 -0
  226. package/src/backend/services/pr-draft-service.js +142 -0
  227. package/src/backend/services/presence-service.js +122 -0
  228. package/src/backend/services/pricing.js +60 -0
  229. package/src/backend/services/project-config-service.js +474 -0
  230. package/src/backend/services/project-scanner.js +184 -0
  231. package/src/backend/services/projection-service.js +69 -0
  232. package/src/backend/services/push-notification-service.js +288 -0
  233. package/src/backend/services/recent-projects-service.js +204 -0
  234. package/src/backend/services/record-chain.js +162 -0
  235. package/src/backend/services/recurrence-rule.js +63 -0
  236. package/src/backend/services/recurring-agent.js +89 -0
  237. package/src/backend/services/recurring-scheduler.js +77 -0
  238. package/src/backend/services/recurring-service.js +276 -0
  239. package/src/backend/services/reference-service.js +169 -0
  240. package/src/backend/services/release-public-key.js +30 -0
  241. package/src/backend/services/release-signature.js +64 -0
  242. package/src/backend/services/remote-audio-service.js +224 -0
  243. package/src/backend/services/remote-interaction-service.js +275 -0
  244. package/src/backend/services/remote-terminal-service.js +324 -0
  245. package/src/backend/services/rendition/child/main.js +76 -0
  246. package/src/backend/services/rendition/engine-host.js +249 -0
  247. package/src/backend/services/rendition/engine-lock.js +39 -0
  248. package/src/backend/services/rendition/engine-lock.json +14 -0
  249. package/src/backend/services/rendition/engine-manifest.js +97 -0
  250. package/src/backend/services/rendition/network-proof.js +73 -0
  251. package/src/backend/services/rendition/rendition-service.js +175 -0
  252. package/src/backend/services/replay-frames.js +387 -0
  253. package/src/backend/services/replay-state.js +201 -0
  254. package/src/backend/services/resolvers/base.js +108 -0
  255. package/src/backend/services/resolvers/csharp.js +109 -0
  256. package/src/backend/services/resolvers/go.js +105 -0
  257. package/src/backend/services/resolvers/index.js +60 -0
  258. package/src/backend/services/resolvers/java.js +63 -0
  259. package/src/backend/services/resolvers/kotlin.js +109 -0
  260. package/src/backend/services/resolvers/php.js +89 -0
  261. package/src/backend/services/resolvers/python.js +154 -0
  262. package/src/backend/services/resolvers/ruby.js +103 -0
  263. package/src/backend/services/resolvers/rust.js +77 -0
  264. package/src/backend/services/resolvers/swift.js +98 -0
  265. package/src/backend/services/resolvers/typescript.js +71 -0
  266. package/src/backend/services/retention.js +54 -0
  267. package/src/backend/services/review-architecture.js +236 -0
  268. package/src/backend/services/review-attest.js +68 -0
  269. package/src/backend/services/review-bundle.js +226 -0
  270. package/src/backend/services/review-graduation.js +93 -0
  271. package/src/backend/services/review-host/bitbucket.js +79 -0
  272. package/src/backend/services/review-host/detect.js +80 -0
  273. package/src/backend/services/review-host/github.js +97 -0
  274. package/src/backend/services/review-host/gitlab.js +77 -0
  275. package/src/backend/services/review-host/host-state.js +103 -0
  276. package/src/backend/services/review-host/http.js +58 -0
  277. package/src/backend/services/review-host/switch.js +120 -0
  278. package/src/backend/services/review-marks.js +72 -0
  279. package/src/backend/services/review-notes.js +169 -0
  280. package/src/backend/services/review-other-work.js +90 -0
  281. package/src/backend/services/review-queue-service.js +147 -0
  282. package/src/backend/services/review-risk.js +127 -0
  283. package/src/backend/services/review-task.js +121 -0
  284. package/src/backend/services/rule-approvals.js +275 -0
  285. package/src/backend/services/rule-baseline.js +134 -0
  286. package/src/backend/services/rule-changes.js +162 -0
  287. package/src/backend/services/rule-preview.js +47 -0
  288. package/src/backend/services/rule-proposals.js +104 -0
  289. package/src/backend/services/rule-scope.js +76 -0
  290. package/src/backend/services/rulebook.js +286 -0
  291. package/src/backend/services/rules-at.js +56 -0
  292. package/src/backend/services/rules-overview.js +88 -0
  293. package/src/backend/services/schema-reconciler.js +250 -0
  294. package/src/backend/services/secret-store.js +119 -0
  295. package/src/backend/services/section-workstreams.js +95 -0
  296. package/src/backend/services/self-write-tracker.js +75 -0
  297. package/src/backend/services/sensor-bridge-service.js +285 -0
  298. package/src/backend/services/session-service.js +192 -0
  299. package/src/backend/services/settings-service.js +324 -0
  300. package/src/backend/services/signal-breakpoints.js +172 -0
  301. package/src/backend/services/signed-approval-record.js +86 -0
  302. package/src/backend/services/signed-approvals.js +244 -0
  303. package/src/backend/services/signoff-pack.js +328 -0
  304. package/src/backend/services/signoff-rows.js +114 -0
  305. package/src/backend/services/skill-arrival-service.js +138 -0
  306. package/src/backend/services/skill-model.js +193 -0
  307. package/src/backend/services/skill-use-service.js +140 -0
  308. package/src/backend/services/skills-service.js +150 -0
  309. package/src/backend/services/snapshot-compare-service.js +397 -0
  310. package/src/backend/services/source-control.js +189 -0
  311. package/src/backend/services/spec-links-service.js +123 -0
  312. package/src/backend/services/spec-proposal-withdraw.js +50 -0
  313. package/src/backend/services/spec-proposals-service.js +470 -0
  314. package/src/backend/services/sql/embedded.js +95 -0
  315. package/src/backend/services/sql/index.js +63 -0
  316. package/src/backend/services/sql/refs.js +357 -0
  317. package/src/backend/services/sql/schema.js +312 -0
  318. package/src/backend/services/sql/tokenizer.js +195 -0
  319. package/src/backend/services/stack-overlaps.js +117 -0
  320. package/src/backend/services/stack-service.js +225 -0
  321. package/src/backend/services/state-sync-service.js +384 -0
  322. package/src/backend/services/stuck-sensor-service.js +200 -0
  323. package/src/backend/services/system-discovery.js +481 -0
  324. package/src/backend/services/system-docs-service.js +701 -0
  325. package/src/backend/services/task-attachments-service.js +340 -0
  326. package/src/backend/services/task-grounding.js +60 -0
  327. package/src/backend/services/task-records/check-run-record.js +146 -0
  328. package/src/backend/services/task-records/check-runs.js +115 -0
  329. package/src/backend/services/task-records/heads.js +88 -0
  330. package/src/backend/services/task-records/material-reads.js +225 -0
  331. package/src/backend/services/task-records/read-record.js +100 -0
  332. package/src/backend/services/task-records/record.js +173 -0
  333. package/src/backend/services/task-records/run-record.js +136 -0
  334. package/src/backend/services/task-records/shared-state.js +548 -0
  335. package/src/backend/services/task-records/signing.js +140 -0
  336. package/src/backend/services/task-records/split-signals.js +52 -0
  337. package/src/backend/services/task-records/test-runs.js +164 -0
  338. package/src/backend/services/task-records/trust.js +243 -0
  339. package/src/backend/services/task-rules.js +81 -0
  340. package/src/backend/services/task-workstreams.js +90 -0
  341. package/src/backend/services/terminal-history-service.js +266 -0
  342. package/src/backend/services/terminal-service.js +267 -0
  343. package/src/backend/services/test-clock.js +53 -0
  344. package/src/backend/services/tests/grounding.js +266 -0
  345. package/src/backend/services/tests/junit.js +104 -0
  346. package/src/backend/services/tests/teammate-runs.js +134 -0
  347. package/src/backend/services/tests/test-results.js +234 -0
  348. package/src/backend/services/tree-watcher.js +204 -0
  349. package/src/backend/services/trellis-service.js +204 -0
  350. package/src/backend/services/trusted-roots.js +186 -0
  351. package/src/backend/services/update-download-service.js +342 -0
  352. package/src/backend/services/update-service.js +266 -0
  353. package/src/backend/services/watch-ignore.js +76 -0
  354. package/src/backend/services/webhook-egress.js +206 -0
  355. package/src/backend/services/webrtc-service.js +413 -0
  356. package/src/backend/services/work-changes.js +59 -0
  357. package/src/backend/services/workstream-binding.js +82 -0
  358. package/src/backend/services/workstream-commits.js +116 -0
  359. package/src/backend/services/workstream-imports.js +177 -0
  360. package/src/backend/services/workstream-service.js +335 -0
  361. package/src/backend/services/workstream-symbols.js +223 -0
  362. package/src/backend/services/workstream-watch-service.js +391 -0
  363. package/src/backend/services/worktree-service.js +235 -0
  364. package/src/cli/agent.js +100 -0
  365. package/src/cli/args.js +209 -0
  366. package/src/cli/conformity.js +106 -0
  367. package/src/cli/desktop.js +91 -0
  368. package/src/cli/main.js +411 -0
  369. package/src/cli/pipeline.js +109 -0
  370. package/src/cli/plan-verbs.js +259 -0
  371. package/src/cli/review-adapters.js +220 -0
  372. package/src/cli/review-output.js +93 -0
  373. package/src/cli/review-post.js +89 -0
  374. package/src/cli/review-sink.js +183 -0
  375. package/src/cli/review-skill.js +44 -0
  376. package/src/cli/review-verify.js +104 -0
  377. package/src/cli/review.js +386 -0
  378. package/src/cli/sarif.js +148 -0
  379. package/src/cli/verbs.js +360 -0
  380. package/src/shared/build-info.js +39 -0
  381. package/src/shared/lib/agent-review.js +199 -0
  382. package/src/shared/lib/agent-turns.js +140 -0
  383. package/src/shared/lib/awareness-digest.js +120 -0
  384. package/src/shared/lib/branch-name.js +45 -0
  385. package/src/shared/lib/breakpoint-words.js +118 -0
  386. package/src/shared/lib/budget-words.js +56 -0
  387. package/src/shared/lib/burst.js +69 -0
  388. package/src/shared/lib/call-entry.js +105 -0
  389. package/src/shared/lib/check-compare.js +42 -0
  390. package/src/shared/lib/check-words.js +216 -0
  391. package/src/shared/lib/csv.js +62 -0
  392. package/src/shared/lib/folder-entry.js +87 -0
  393. package/src/shared/lib/freeze-words.js +60 -0
  394. package/src/shared/lib/fuzzy.js +84 -0
  395. package/src/shared/lib/git-state-words.js +80 -0
  396. package/src/shared/lib/grep-entry.js +86 -0
  397. package/src/shared/lib/grounding-line.js +61 -0
  398. package/src/shared/lib/import-line.js +71 -0
  399. package/src/shared/lib/item-status.js +249 -0
  400. package/src/shared/lib/line-changes.js +53 -0
  401. package/src/shared/lib/locator.js +71 -0
  402. package/src/shared/lib/matcher.js +120 -0
  403. package/src/shared/lib/merge-order.js +65 -0
  404. package/src/shared/lib/open-findings.js +68 -0
  405. package/src/shared/lib/other-work.js +108 -0
  406. package/src/shared/lib/package-entry.js +142 -0
  407. package/src/shared/lib/plan-vocab.js +40 -0
  408. package/src/shared/lib/pptx-xml.js +86 -0
  409. package/src/shared/lib/proposal-words.js +61 -0
  410. package/src/shared/lib/recurrence.js +183 -0
  411. package/src/shared/lib/references.js +72 -0
  412. package/src/shared/lib/rule-pattern.js +56 -0
  413. package/src/shared/lib/sdp-fingerprint.js +115 -0
  414. package/src/shared/lib/sdp-minimal.js +123 -0
  415. package/src/shared/lib/secret-paths.js +34 -0
  416. package/src/shared/lib/signal-words.js +172 -0
  417. package/src/shared/lib/signoff.js +56 -0
  418. package/src/shared/lib/skills-note.js +60 -0
  419. package/src/shared/lib/spec-sections.js +78 -0
  420. package/src/shared/lib/symbol-entry.js +60 -0
  421. package/src/shared/lib/tool-phrasing.js +338 -0
  422. package/src/shared/lib/turn-gap.js +27 -0
  423. package/src/shared/lib/workstream-words.js +38 -0
  424. package/src/shared/lib/xlsx-xml.js +144 -0
  425. package/src/shared/lib/zip-reader.js +99 -0
  426. package/src/shared/types/agent.js +27 -0
  427. package/src/shared/types/architecture-rules.js +30 -0
  428. package/src/shared/types/ast.js +15 -0
  429. package/src/shared/types/breakpoint.js +33 -0
  430. package/src/shared/types/channel.js +41 -0
  431. package/src/shared/types/criteria.js +15 -0
  432. package/src/shared/types/graph.js +15 -0
  433. package/src/shared/types/index.js +53 -0
  434. package/src/shared/types/peer.js +36 -0
  435. package/src/shared/types/pipeline.js +15 -0
  436. package/src/shared/types/plan.js +15 -0
  437. package/src/shared/types/play-forward.js +15 -0
  438. package/src/shared/types/power.js +15 -0
  439. package/src/shared/types/presence.js +15 -0
  440. package/src/shared/types/project-config.js +35 -0
  441. package/src/shared/types/project.js +15 -0
  442. package/src/shared/types/record.js +15 -0
  443. package/src/shared/types/recurring.js +15 -0
  444. package/src/shared/types/review.js +15 -0
  445. package/src/shared/types/settings.js +114 -0
  446. package/src/shared/types/stack.js +15 -0
  447. package/src/shared/types/system-doc.js +15 -0
  448. package/src/shared/types/system.js +15 -0
@@ -0,0 +1,275 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var rule_approvals_exports = {};
29
+ __export(rule_approvals_exports, {
30
+ APPROVALS_DIR: () => APPROVALS_DIR,
31
+ RULE_CHANGE_NAMESPACE: () => RULE_CHANGE_NAMESPACE,
32
+ approvalFor: () => approvalFor,
33
+ approvalYaml: () => approvalYaml,
34
+ approvalsHere: () => approvalsHere,
35
+ deviceBytes: () => deviceBytes,
36
+ keysAt: () => keysAt,
37
+ parseApproval: () => parseApproval,
38
+ ruleTerms: () => ruleTerms,
39
+ signRuleChange: () => signRuleChange,
40
+ statementBytes: () => statementBytes
41
+ });
42
+ module.exports = __toCommonJS(rule_approvals_exports);
43
+ var import_node_fs = __toESM(require("node:fs"));
44
+ var import_node_os = __toESM(require("node:os"));
45
+ var import_node_path = __toESM(require("node:path"));
46
+ var import_node_crypto = require("node:crypto");
47
+ var import_node_child_process = require("node:child_process");
48
+ var import_yaml = require("yaml");
49
+ var import_architecture_rules = require("../../shared/types/architecture-rules");
50
+ var import_confined_fs = require("./confined-fs");
51
+ var import_signed_approvals = require("./signed-approvals");
52
+ var import_signing = require("./task-records/signing");
53
+ var import_trust = require("./task-records/trust");
54
+ const RULE_CHANGE_NAMESPACE = "codetrellis-rule-change";
55
+ const APPROVALS_DIR = ".codetrellis/rules/approvals";
56
+ const KIND = "codetrellis-rule-change";
57
+ const MAX_APPROVALS = 200;
58
+ const MAX_BYTES = 16 * 1024;
59
+ const COMMIT = /^[0-9a-f]{40}$/;
60
+ function ruleTerms(r) {
61
+ if (!r) return null;
62
+ const t = termsOf(r);
63
+ return r.tags?.length ? { ...t, tags: [...r.tags].sort() } : t;
64
+ }
65
+ function termsOf(r) {
66
+ const terms = { from: r.from, mayNotImport: r.mayNotImport, except: [...r.except].sort(), strength: r.strength };
67
+ if (r.kind === "folder") return { ...terms, kind: "folder", files: [...r.files ?? []].sort(), kinds: [...r.kinds ?? []].sort(), ...r.exports ? { exports: r.exports } : {} };
68
+ if (r.kind === "agent") return { ...terms, kind: "agent", in: [...r.in ?? []].sort() };
69
+ if (r.kind === "grep") return { ...terms, kind: "grep", in: [...r.in ?? []].sort(), ...r.must ? { must: true } : {}, ...r.ignoreCase ? { ignoreCase: true } : {}, ...r.match ? { match: r.match } : {}, ...r.threshold !== void 0 ? { threshold: r.threshold } : {} };
70
+ return r.kind === "package" || r.kind === "symbol" || r.kind === "calls" ? { ...terms, kind: r.kind, only: [...r.only ?? []].sort(), ...r.match ? { match: r.match } : {}, ...r.threshold !== void 0 ? { threshold: r.threshold } : {} } : terms;
71
+ }
72
+ const statementBytes = (s) => (0, import_signing.canonicalJson)(s);
73
+ const deviceBytes = (bytes) => `${RULE_CHANGE_NAMESPACE}
74
+ ${bytes}`;
75
+ function approvalYaml(s, signature) {
76
+ return "# CodeTrellis: a person approved this change to an architecture rule, in the app.\n# CI accepts the change only if this verifies against keys on the base branch.\n" + (0, import_yaml.stringify)({ kind: KIND, version: 1, statement: statementBytes(s), signature }, { lineWidth: 0 });
77
+ }
78
+ const isTerms = (v) => {
79
+ if (!v || typeof v !== "object") return false;
80
+ const t = v;
81
+ return typeof t.from === "string" && typeof t.mayNotImport === "string" && Array.isArray(t.except) && t.except.every((e) => typeof e === "string") && import_architecture_rules.RULE_STRENGTHS.includes(t.strength);
82
+ };
83
+ function parseApproval(text) {
84
+ if (Buffer.byteLength(text, "utf8") > MAX_BYTES) return { error: "larger than an approval can be" };
85
+ let raw;
86
+ try {
87
+ raw = (0, import_yaml.parse)(text, { maxAliasCount: 0 });
88
+ } catch {
89
+ return { error: "not YAML" };
90
+ }
91
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { error: "not an approval" };
92
+ const r = raw;
93
+ if (r.kind !== KIND || r.version !== 1 || typeof r.statement !== "string") return { error: "not a rule-change approval this version reads" };
94
+ const signature = (0, import_signing.parseSignature)(r.signature);
95
+ if (!signature) return { error: "it has no signature this version reads" };
96
+ let s;
97
+ try {
98
+ s = JSON.parse(r.statement);
99
+ } catch {
100
+ return { error: "its statement is not JSON" };
101
+ }
102
+ if (s.kind !== KIND || s.version !== 1 || typeof s.rule !== "string" || typeof s.signer !== "string" || typeof s.at !== "string" || !(s.before === null || isTerms(s.before)) || !(s.after === null || isTerms(s.after)) || !(s.base === null || typeof s.base === "string" && COMMIT.test(s.base))) {
103
+ return { error: "its statement is not a rule change" };
104
+ }
105
+ const statement = s;
106
+ if (statementBytes(statement) !== r.statement) return { error: "its statement is not in canonical form" };
107
+ return { statement, bytes: r.statement, signature };
108
+ }
109
+ function git(cwd, args) {
110
+ try {
111
+ return (0, import_node_child_process.execFileSync)("git", ["-C", cwd, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 15e3, maxBuffer: 4 * 1024 * 1024 });
112
+ } catch {
113
+ return null;
114
+ }
115
+ }
116
+ function signRuleChange(projectRoot, change, device, now = Date.now()) {
117
+ const head = git(projectRoot, ["rev-parse", "--verify", "--quiet", "HEAD^{commit}"])?.trim() ?? null;
118
+ const base = head && COMMIT.test(head) ? head : null;
119
+ const at = new Date(now).toISOString();
120
+ const draft = (signer) => ({
121
+ kind: KIND,
122
+ version: 1,
123
+ rule: change.rule,
124
+ before: ruleTerms(change.before),
125
+ after: ruleTerms(change.after),
126
+ base,
127
+ signer,
128
+ at
129
+ });
130
+ let statement = null;
131
+ let signature = null;
132
+ const setup = process.env.CODETRELLIS_GIT_SIGN_RECORDS === "0" ? null : (0, import_signed_approvals.signingSetup)(projectRoot);
133
+ if (setup?.canSign) {
134
+ statement = draft(setup.signer);
135
+ try {
136
+ const value = (0, import_node_child_process.execFileSync)("ssh-keygen", ["-Y", "sign", "-f", setup.keyFile, "-n", RULE_CHANGE_NAMESPACE], {
137
+ input: statementBytes(statement),
138
+ encoding: "utf-8",
139
+ stdio: ["pipe", "pipe", "pipe"],
140
+ timeout: 15e3
141
+ });
142
+ signature = { how: "git", signer: setup.signer, value: value.trim() };
143
+ } catch (err) {
144
+ console.warn("[Rules] git could not sign the approval; the device key signs it:", err.message.split("\n")[0]);
145
+ statement = null;
146
+ }
147
+ }
148
+ if (!statement || !signature) {
149
+ const key = (0, import_trust.deviceKey)();
150
+ (0, import_trust.introduceDeviceKey)(projectRoot, device.writer, device.name, key);
151
+ statement = draft(key.fingerprint);
152
+ signature = (0, import_signing.signWithDevice)(key, deviceBytes(statementBytes(statement)));
153
+ }
154
+ const bytes = statementBytes(statement);
155
+ const rel = `${APPROVALS_DIR}/${change.rule}-${(0, import_node_crypto.createHash)("sha256").update(bytes).digest("hex").slice(0, 12)}.yaml`;
156
+ (0, import_confined_fs.writeFileWithin)(projectRoot, rel, approvalYaml(statement, signature), "rule approval");
157
+ return { file: rel, how: signature.how, as: statement.signer };
158
+ }
159
+ function canonicalFolderOf(file) {
160
+ try {
161
+ return import_node_path.default.join(import_node_fs.default.realpathSync(import_node_path.default.dirname(file)), import_node_path.default.basename(file));
162
+ } catch {
163
+ return file;
164
+ }
165
+ }
166
+ function keysAt(projectRoot, commit) {
167
+ const devices = /* @__PURE__ */ new Map();
168
+ const listing = git(projectRoot, ["ls-tree", "--name-only", commit, `./${import_trust.KEYS_DIR}/`]);
169
+ for (const line of (listing ?? "").split("\n").map((l) => l.trim()).filter(Boolean).slice(0, 500)) {
170
+ const name = import_node_path.default.basename(line);
171
+ const m = /^([a-f0-9]{8,32})\.yaml$/.exec(name);
172
+ if (!m) continue;
173
+ const text = git(projectRoot, ["show", `${commit}:./${import_trust.KEYS_DIR}/${name}`]);
174
+ if (!text) continue;
175
+ const parsed = (0, import_signing.parseKeyIntroduction)(text, m[1]);
176
+ if ("key" in parsed) devices.set(parsed.key.fingerprint, parsed.key.publicKey);
177
+ }
178
+ let allowedSigners = null;
179
+ let tmp = null;
180
+ const configured = (0, import_signed_approvals.signingSetup)(projectRoot).allowedSigners;
181
+ if (configured) {
182
+ const top = git(projectRoot, ["rev-parse", "--show-toplevel"])?.trim();
183
+ const inRepo = top ? import_node_path.default.relative(import_node_fs.default.realpathSync(top), canonicalFolderOf(import_node_path.default.resolve(configured))) : null;
184
+ if (inRepo !== null && !inRepo.startsWith("..") && !import_node_path.default.isAbsolute(inRepo)) {
185
+ const text = git(top, ["show", `${commit}:${inRepo.split(import_node_path.default.sep).join("/")}`]);
186
+ if (text !== null) {
187
+ tmp = import_node_fs.default.mkdtempSync(import_node_path.default.join(import_node_os.default.tmpdir(), "codetrellis-signers-"));
188
+ allowedSigners = import_node_path.default.join(tmp, "allowed_signers");
189
+ import_node_fs.default.writeFileSync(allowedSigners, text, { mode: 384 });
190
+ }
191
+ } else if (import_node_fs.default.existsSync(configured)) {
192
+ allowedSigners = configured;
193
+ }
194
+ }
195
+ return { devices, allowedSigners, done: () => {
196
+ if (tmp) import_node_fs.default.rmSync(tmp, { recursive: true, force: true });
197
+ } };
198
+ }
199
+ function approvalsHere(projectRoot) {
200
+ const dir = import_node_path.default.join(projectRoot, APPROVALS_DIR);
201
+ let names;
202
+ try {
203
+ names = import_node_fs.default.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".yaml")).map((e) => e.name).sort().slice(0, MAX_APPROVALS);
204
+ } catch {
205
+ return [];
206
+ }
207
+ const out = [];
208
+ for (const name of names) {
209
+ const file = `${APPROVALS_DIR}/${name}`;
210
+ let text;
211
+ try {
212
+ text = (0, import_confined_fs.readTextWithin)(projectRoot, file, "rule approval");
213
+ } catch {
214
+ continue;
215
+ }
216
+ const p = parseApproval(text);
217
+ if ("statement" in p) out.push({ ...p, file });
218
+ }
219
+ return out;
220
+ }
221
+ function approvalFor(projectRoot, change, approvals, keys, mergeBase) {
222
+ const before = (0, import_signing.canonicalJson)(ruleTerms(change.before));
223
+ const after = (0, import_signing.canonicalJson)(ruleTerms(change.after));
224
+ const claims = approvals.filter((a) => a.statement.rule === change.rule && (0, import_signing.canonicalJson)(a.statement.before) === before && (0, import_signing.canonicalJson)(a.statement.after) === after);
225
+ if (claims.length === 0) return null;
226
+ let why = "";
227
+ for (const a of claims) {
228
+ const s = a.statement;
229
+ if (!s.base) {
230
+ why = `${a.file} was not made in a git checkout`;
231
+ continue;
232
+ }
233
+ if (git(projectRoot, ["merge-base", "--is-ancestor", mergeBase, s.base]) === null) {
234
+ why = `${a.file} was made at ${s.base.slice(0, 7)}, before this change's base (or that commit is not in this clone), so it approves an earlier change`;
235
+ continue;
236
+ }
237
+ if (a.signature.how === "device") {
238
+ const pub = keys.devices.get(a.signature.key);
239
+ if (!pub) {
240
+ why = `${a.file} is signed with a device key the base branch does not list under ${import_trust.KEYS_DIR}/`;
241
+ continue;
242
+ }
243
+ if (a.signature.key !== s.signer || !(0, import_signing.verifyWithDevice)(pub, deviceBytes(a.bytes), a.signature.value)) {
244
+ why = `${a.file}'s signature does not verify`;
245
+ continue;
246
+ }
247
+ return { ok: true, by: s.signer, how: "device", file: a.file };
248
+ }
249
+ if (a.signature.signer !== s.signer) {
250
+ why = `${a.file} names one signer in its statement and another on its signature`;
251
+ continue;
252
+ }
253
+ const v = (0, import_signed_approvals.verifyRecord)(a.bytes, a.signature.value, s.signer, keys.allowedSigners, RULE_CHANGE_NAMESPACE);
254
+ if (!v.ok) {
255
+ why = `${a.file}: ${v.reason}`;
256
+ continue;
257
+ }
258
+ return { ok: true, by: s.signer, how: "git", file: a.file };
259
+ }
260
+ return { ok: false, why };
261
+ }
262
+ // Annotate the CommonJS export names for ESM import in node:
263
+ 0 && (module.exports = {
264
+ APPROVALS_DIR,
265
+ RULE_CHANGE_NAMESPACE,
266
+ approvalFor,
267
+ approvalYaml,
268
+ approvalsHere,
269
+ deviceBytes,
270
+ keysAt,
271
+ parseApproval,
272
+ ruleTerms,
273
+ signRuleChange,
274
+ statementBytes
275
+ });
@@ -0,0 +1,134 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var rule_baseline_exports = {};
29
+ __export(rule_baseline_exports, {
30
+ BASELINE_FILE: () => BASELINE_FILE,
31
+ baselineAt: () => baselineAt,
32
+ baselineOf: () => baselineOf,
33
+ baselineYaml: () => baselineYaml,
34
+ parseBaseline: () => parseBaseline,
35
+ ratchet: () => ratchet,
36
+ readBaseline: () => readBaseline
37
+ });
38
+ module.exports = __toCommonJS(rule_baseline_exports);
39
+ var import_node_fs = __toESM(require("node:fs"));
40
+ var import_node_path = __toESM(require("node:path"));
41
+ var import_node_child_process = require("node:child_process");
42
+ var import_yaml = require("yaml");
43
+ var import_architecture_rule = require("./architecture-rule");
44
+ var import_confined_fs = require("./confined-fs");
45
+ const BASELINE_FILE = ".codetrellis/rules/baseline.yaml";
46
+ const MAX_ENTRIES = 2e4;
47
+ const entry = (e) => `${e.from} > ${e.to}`;
48
+ function parseBaseline(text) {
49
+ const out = /* @__PURE__ */ new Map();
50
+ let raw;
51
+ try {
52
+ raw = (0, import_yaml.parse)(text, { maxAliasCount: 0 });
53
+ } catch {
54
+ return out;
55
+ }
56
+ const rules = raw && typeof raw === "object" ? raw.rules : null;
57
+ if (!rules || typeof rules !== "object" || Array.isArray(rules)) return out;
58
+ let n = 0;
59
+ for (const [id, list] of Object.entries(rules)) {
60
+ if (!Array.isArray(list)) continue;
61
+ const set = /* @__PURE__ */ new Set();
62
+ for (const x of list) {
63
+ if (typeof x !== "string" || !x.includes(" > ") || ++n > MAX_ENTRIES) continue;
64
+ set.add(x.trim());
65
+ }
66
+ out.set(id, set);
67
+ }
68
+ return out;
69
+ }
70
+ function baselineYaml(b) {
71
+ const rules = {};
72
+ for (const id of [...b.keys()].sort()) rules[id] = [...b.get(id)].sort();
73
+ return "# CodeTrellis: imports that already broke each rule when it was baselined.\n# The check fails on any breach not listed here, and this file may only shrink.\n# Written by `codetrellis rules baseline`; fix a breach, then run it again.\n" + (0, import_yaml.stringify)({ rules }, { lineWidth: 0 });
74
+ }
75
+ function baselineOf(rules, edges) {
76
+ const out = /* @__PURE__ */ new Map();
77
+ for (const r of rules) {
78
+ if (r.strength === "guide") continue;
79
+ out.set(r.id, new Set((0, import_architecture_rule.checkEdges)([r], edges).map(entry)));
80
+ }
81
+ return out;
82
+ }
83
+ function readBaseline(projectRoot) {
84
+ if (!import_node_fs.default.existsSync(import_node_path.default.join(projectRoot, BASELINE_FILE))) return null;
85
+ try {
86
+ return parseBaseline((0, import_confined_fs.readTextWithin)(projectRoot, BASELINE_FILE, "rule baseline"));
87
+ } catch {
88
+ return null;
89
+ }
90
+ }
91
+ function baselineAt(projectRoot, commit) {
92
+ try {
93
+ const text = (0, import_node_child_process.execFileSync)("git", ["-C", projectRoot, "show", `${commit}:./${BASELINE_FILE}`], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: 16 * 1024 * 1024 });
94
+ return parseBaseline(text);
95
+ } catch {
96
+ return null;
97
+ }
98
+ }
99
+ function ratchet(base, head, rules, edges) {
100
+ const out = [];
101
+ for (const [id, entries] of head ?? /* @__PURE__ */ new Map()) {
102
+ const was = base?.get(id);
103
+ if (!was) continue;
104
+ const added = [...entries].filter((e) => !was.has(e));
105
+ if (added.length) {
106
+ out.push({ rule: id, kind: "grew", words: `\u2717 This change adds ${added.length} ${added.length === 1 ? "entry" : "entries"} to the baseline of ${id} (${added.slice(0, 3).join(", ")}${added.length > 3 ? ", \u2026" : ""}); a baseline may only shrink.` });
107
+ }
108
+ }
109
+ if (!base) return out;
110
+ for (const r of rules) {
111
+ const listed = base.get(r.id);
112
+ if (!listed || r.strength === "guide") continue;
113
+ const breaches = (0, import_architecture_rule.checkEdges)([r], edges);
114
+ for (const b of breaches) {
115
+ if (listed.has(entry(b))) continue;
116
+ out.push({ rule: r.id, kind: "breach", from: b.from, to: b.to, words: `\u2717 ${b.from} imports ${b.to}, which the rule \u201C${(0, import_architecture_rule.ruleStatement)({ ...r, except: [] })}\u201D forbids, and its baseline does not list it` });
117
+ }
118
+ const left = breaches.filter((b) => listed.has(entry(b))).length;
119
+ if (left < listed.size) {
120
+ out.push({ rule: r.id, kind: "fell", words: `\u2193 ${r.id}: ${left} ${left === 1 ? "breach" : "breaches"} left, down from ${listed.size} in the baseline. Run \`codetrellis rules baseline\` to lock in the lower count.` });
121
+ }
122
+ }
123
+ return out;
124
+ }
125
+ // Annotate the CommonJS export names for ESM import in node:
126
+ 0 && (module.exports = {
127
+ BASELINE_FILE,
128
+ baselineAt,
129
+ baselineOf,
130
+ baselineYaml,
131
+ parseBaseline,
132
+ ratchet,
133
+ readBaseline
134
+ });
@@ -0,0 +1,162 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key2 of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key2) && key2 !== except)
13
+ __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var rule_changes_exports = {};
19
+ __export(rule_changes_exports, {
20
+ NEEDS: () => NEEDS,
21
+ changeWords: () => changeWords,
22
+ diffRules: () => diffRules
23
+ });
24
+ module.exports = __toCommonJS(rule_changes_exports);
25
+ var import_architecture_rule = require("./architecture-rule");
26
+ const key = (e) => e.to.startsWith("folder:") ? `${e.from}>folder` : `${e.from}>${e.to}`;
27
+ const breaches = (rule, edges) => (0, import_architecture_rule.checkEdges)([rule], edges).map((b) => ({ from: b.from, to: b.to }));
28
+ const minus = (a, b) => {
29
+ const drop = new Set(b.map(key));
30
+ return a.filter((e) => !drop.has(key(e)));
31
+ };
32
+ const imports = (n, r) => {
33
+ const noun = r?.kind === "grep" ? r.must ? "file" : "line" : "import";
34
+ return `${n} ${noun}${n === 1 ? "" : "s"}`;
35
+ };
36
+ const sameSet = (a, b) => a.length === b.length && [...a].sort().every((x, i) => x === [...b].sort()[i]);
37
+ function textEffect(base, head) {
38
+ const pathsSame = (base.kind ?? "imports") === (head.kind ?? "imports") && base.from === head.from && base.mayNotImport === head.mayNotImport && (base.match ?? null) === (head.match ?? null);
39
+ const threshold = (base.threshold ?? null) === (head.threshold ?? null) ? "same" : (head.threshold ?? 1) < (base.threshold ?? 1) ? "tightens" : "loosens";
40
+ const baseOnly = base.only ?? [];
41
+ const headOnly = head.only ?? [];
42
+ const onlySame = sameSet(baseOnly, headOnly);
43
+ const onlyShrank = headOnly.every((o) => baseOnly.includes(o));
44
+ const allowed = (b = [], h = []) => sameSet(b, h) ? "same" : b.length === 0 && h.length > 0 || h.length > 0 && h.every((x) => b.includes(x)) ? "tightens" : "loosens";
45
+ const folder = [
46
+ allowed(base.files, head.files),
47
+ allowed(base.kinds, head.kinds),
48
+ base.exports === head.exports ? "same" : head.exports === "one" ? "tightens" : "loosens"
49
+ ];
50
+ const grepSame = sameSet(base.in ?? [], head.in ?? []) && !!base.must === !!head.must && !!base.ignoreCase === !!head.ignoreCase;
51
+ const baseTags = base.tags ?? [];
52
+ const headTags = head.tags ?? [];
53
+ const tags = sameSet(baseTags, headTags) ? "same" : baseTags.every((t) => headTags.includes(t)) ? "tightens" : "loosens";
54
+ const folderSame = folder.every((f) => f === "same") && grepSame && threshold === "same" && tags === "same";
55
+ const folderTighter = folder.every((f) => f !== "loosens") && grepSame && threshold !== "loosens" && tags !== "loosens";
56
+ if (pathsSame && onlySame && sameSet(base.except, head.except) && folderSame) return "same";
57
+ if (pathsSame && onlyShrank && head.except.every((e) => base.except.includes(e)) && folderTighter) return "tightens";
58
+ return "loosens";
59
+ }
60
+ const RANK = { guide: 0, warn: 1, block: 2 };
61
+ function strengthEffect(base, head) {
62
+ const d = RANK[head.strength] - RANK[base.strength];
63
+ return d === 0 ? "same" : d > 0 ? "tightens" : "loosens";
64
+ }
65
+ const stated = (r) => `\u201C${(0, import_architecture_rule.ruleStatement)(r)}\u201D`;
66
+ function diffRules(base, head, edges) {
67
+ const out = [];
68
+ const before = new Map(base.map((r) => [r.id, r]));
69
+ const after = new Map(head.map((r) => [r.id, r]));
70
+ for (const [id, b] of before) {
71
+ const h = after.get(id);
72
+ if (!h) {
73
+ const allowed2 = breaches(b, edges);
74
+ out.push({
75
+ rule: id,
76
+ change: "removed",
77
+ effect: "loosens",
78
+ allowed: allowed2,
79
+ forbidden: [],
80
+ before: b,
81
+ after: null,
82
+ words: `\u2717 This change removes the rule \u201C${(0, import_architecture_rule.ruleStatement)({ ...b, except: [] })}\u201D (${id})${allowed2.length ? `: ${imports(allowed2.length, b)} it forbade become allowed` : ""}. Loosening a rule needs a person's approval in the app.`
83
+ });
84
+ continue;
85
+ }
86
+ const text = textEffect(b, h);
87
+ const strength = strengthEffect(b, h);
88
+ if (text === "same" && strength === "same") {
89
+ if (b.because !== h.because) {
90
+ out.push({ rule: id, change: "changed", effect: "reworded", allowed: [], forbidden: [], before: b, after: h, words: `\xB7 This change rewords why the rule ${id} exists.` });
91
+ }
92
+ continue;
93
+ }
94
+ const was = breaches(b, edges);
95
+ const now = breaches(h, edges);
96
+ if (text === "same") {
97
+ const n = was.length;
98
+ out.push(strength === "loosens" ? {
99
+ rule: id,
100
+ change: "changed",
101
+ effect: "loosens",
102
+ allowed: b.strength === "block" ? was : [],
103
+ forbidden: [],
104
+ before: b,
105
+ after: h,
106
+ words: `\u2717 This change lowers the rule ${id} from ${b.strength} to ${h.strength}${n && b.strength === "block" ? `: ${imports(n, b)} that break it would no longer fail CI` : ""}. Loosening a rule needs a person's approval in the app.`
107
+ } : {
108
+ rule: id,
109
+ change: "changed",
110
+ effect: "tightens",
111
+ allowed: [],
112
+ forbidden: h.strength === "block" ? now : [],
113
+ before: b,
114
+ after: h,
115
+ words: `\u26A0 This change raises the rule ${id} from ${b.strength} to ${h.strength}${now.length && h.strength === "block" ? `: ${imports(now.length, h)} already in the code would fail CI` : ""}.`
116
+ });
117
+ continue;
118
+ }
119
+ const allowed = minus(was, now);
120
+ const forbidden = minus(now, was);
121
+ const effect = text === "loosens" || strength === "loosens" || allowed.length > 0 ? "loosens" : "tightens";
122
+ const at = (r) => b.strength === h.strength ? "" : ` at ${r.strength}`;
123
+ const what = `${stated(b)}${at(b)} to ${stated(h)}${at(h)}`;
124
+ out.push({
125
+ rule: id,
126
+ change: "changed",
127
+ effect,
128
+ allowed,
129
+ forbidden,
130
+ before: b,
131
+ after: h,
132
+ words: effect === "loosens" ? `\u2717 This change loosens the rule ${id}, from ${what}${allowed.length ? `: ${imports(allowed.length, b)} it forbade become allowed` : ""}. Loosening a rule needs a person's approval in the app.` : `\u26A0 This change tightens the rule ${id}, from ${what}${forbidden.length ? `: ${imports(forbidden.length, h)} already in the code would break it` : ""}.`
133
+ });
134
+ }
135
+ for (const [id, h] of after) {
136
+ if (before.has(id)) continue;
137
+ const forbidden = breaches(h, edges);
138
+ out.push({
139
+ rule: id,
140
+ change: "added",
141
+ effect: "tightens",
142
+ allowed: [],
143
+ forbidden,
144
+ before: null,
145
+ after: h,
146
+ words: `\u26A0 This change adds the rule \u201C${(0, import_architecture_rule.ruleStatement)({ ...h, except: [] })}\u201D (${id}) at ${h.strength}${forbidden.length ? `: ${imports(forbidden.length, h)} already in the code would break it` : ""}. It is checked once it is on the base branch.`
147
+ });
148
+ }
149
+ return out;
150
+ }
151
+ const NEEDS = " Loosening a rule needs a person's approval in the app.";
152
+ function changeWords(c) {
153
+ if (c.effect !== "loosens" || !c.approval) return c.words;
154
+ if (c.approval.ok) return `\u2713 ${c.words.replace(/^✗ /, "").replace(NEEDS, "")} ${c.approval.by} approved it in the app, signed (${c.approval.file}).`;
155
+ return `${c.words} An approval is attached, but ${c.approval.why}.`;
156
+ }
157
+ // Annotate the CommonJS export names for ESM import in node:
158
+ 0 && (module.exports = {
159
+ NEEDS,
160
+ changeWords,
161
+ diffRules
162
+ });
@@ -0,0 +1,47 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var rule_preview_exports = {};
19
+ __export(rule_preview_exports, {
20
+ NO_CHANGE: () => NO_CHANGE,
21
+ previewChange: () => previewChange,
22
+ previewJson: () => previewJson
23
+ });
24
+ module.exports = __toCommonJS(rule_preview_exports);
25
+ var import_architecture_rules = require("./architecture-rules");
26
+ var import_rule_changes = require("./rule-changes");
27
+ const NO_CHANGE = "This changes nothing about how code is judged.";
28
+ function previewChange(projectRoot, id, next, edges) {
29
+ const current = (0, import_architecture_rules.findRule)(projectRoot, id);
30
+ const change = (0, import_rule_changes.diffRules)(current ? [current] : [], next ? [next] : [], edges ?? [])[0] ?? null;
31
+ const breaches = edges && next && next.strength !== "guide" ? (0, import_architecture_rules.checkEdges)([next], edges).length : null;
32
+ return { change, breaches, words: change ? change.words : NO_CHANGE, needsConfirm: change?.effect === "loosens" };
33
+ }
34
+ function previewJson(p) {
35
+ return {
36
+ change: p.change ? { rule: p.change.rule, change: p.change.change, effect: p.change.effect, allowed: p.change.allowed, forbidden: p.change.forbidden, words: p.change.words } : null,
37
+ words: p.words,
38
+ breaches: p.breaches,
39
+ needsConfirm: p.needsConfirm
40
+ };
41
+ }
42
+ // Annotate the CommonJS export names for ESM import in node:
43
+ 0 && (module.exports = {
44
+ NO_CHANGE,
45
+ previewChange,
46
+ previewJson
47
+ });