codetrellis 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (449) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +27 -2
  3. package/bin/codetrellis.mjs +4 -0
  4. package/package.json +43 -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/clock.js +57 -0
  102. package/src/backend/services/cloud-files.js +191 -0
  103. package/src/backend/services/coalesce.js +50 -0
  104. package/src/backend/services/code-breakpoints.js +291 -0
  105. package/src/backend/services/comment-service.js +168 -0
  106. package/src/backend/services/commit-attribution.js +134 -0
  107. package/src/backend/services/commit-edges.js +99 -0
  108. package/src/backend/services/confined-fs.js +241 -0
  109. package/src/backend/services/conformity-gate.js +132 -0
  110. package/src/backend/services/contribution-service.js +409 -0
  111. package/src/backend/services/coverage-service.js +173 -0
  112. package/src/backend/services/criteria-service.js +721 -0
  113. package/src/backend/services/criterion-checks.js +387 -0
  114. package/src/backend/services/criterion-loop-service.js +411 -0
  115. package/src/backend/services/cross-system-service.js +231 -0
  116. package/src/backend/services/database.js +916 -0
  117. package/src/backend/services/db-schema.js +1358 -0
  118. package/src/backend/services/deviation-service.js +344 -0
  119. package/src/backend/services/diff-engine.js +168 -0
  120. package/src/backend/services/evidence.js +363 -0
  121. package/src/backend/services/external-intake-service.js +269 -0
  122. package/src/backend/services/external-pointer-service.js +195 -0
  123. package/src/backend/services/external-refs-service.js +214 -0
  124. package/src/backend/services/file-history.js +158 -0
  125. package/src/backend/services/file-watcher.js +193 -0
  126. package/src/backend/services/folder-requests.js +118 -0
  127. package/src/backend/services/freeze-service.js +189 -0
  128. package/src/backend/services/gemini-cli-hook.js +172 -0
  129. package/src/backend/services/git-activity-service.js +325 -0
  130. package/src/backend/services/git-blobs.js +70 -0
  131. package/src/backend/services/git-branches.js +357 -0
  132. package/src/backend/services/git-checkout.js +153 -0
  133. package/src/backend/services/git-commit-service.js +91 -0
  134. package/src/backend/services/git-env.js +121 -0
  135. package/src/backend/services/git-identity.js +84 -0
  136. package/src/backend/services/git-refs.js +386 -0
  137. package/src/backend/services/git-safety.js +58 -0
  138. package/src/backend/services/grant-guard.js +67 -0
  139. package/src/backend/services/html-view-policy.js +135 -0
  140. package/src/backend/services/human-decision.js +55 -0
  141. package/src/backend/services/importers.js +159 -0
  142. package/src/backend/services/intent-service.js +105 -0
  143. package/src/backend/services/ipc-dispatcher.js +164 -0
  144. package/src/backend/services/item-git-state.js +208 -0
  145. package/src/backend/services/line-changes.js +232 -0
  146. package/src/backend/services/line-history.js +174 -0
  147. package/src/backend/services/local-api-changes.js +40 -0
  148. package/src/backend/services/logger.js +217 -0
  149. package/src/backend/services/material-footprints.js +203 -0
  150. package/src/backend/services/material-place.js +82 -0
  151. package/src/backend/services/material-reader/child.js +4 -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/read.js +430 -0
  156. package/src/backend/services/material-reader/reader-host.js +202 -0
  157. package/src/backend/services/material-signals.js +141 -0
  158. package/src/backend/services/mcp-capabilities.js +390 -0
  159. package/src/backend/services/mdns-service.js +304 -0
  160. package/src/backend/services/mobile-api-server.js +281 -0
  161. package/src/backend/services/mobile-approvals.js +306 -0
  162. package/src/backend/services/mobile-awareness.js +180 -0
  163. package/src/backend/services/mobile-breakpoints.js +115 -0
  164. package/src/backend/services/mobile-budget.js +98 -0
  165. package/src/backend/services/mobile-freeze.js +106 -0
  166. package/src/backend/services/mobile-proposals.js +100 -0
  167. package/src/backend/services/mobile-rpc-service.js +1289 -0
  168. package/src/backend/services/mobile-workstreams.js +160 -0
  169. package/src/backend/services/monorepo-detector.js +131 -0
  170. package/src/backend/services/other-work.js +45 -0
  171. package/src/backend/services/pack-seal.js +129 -0
  172. package/src/backend/services/paired-device-service.js +192 -0
  173. package/src/backend/services/pairing-server.js +323 -0
  174. package/src/backend/services/pairing-service.js +200 -0
  175. package/src/backend/services/pantry-resolution-service.js +166 -0
  176. package/src/backend/services/parsers/base.js +124 -0
  177. package/src/backend/services/parsers/csharp.js +224 -0
  178. package/src/backend/services/parsers/go.js +180 -0
  179. package/src/backend/services/parsers/index.js +101 -0
  180. package/src/backend/services/parsers/java.js +103 -0
  181. package/src/backend/services/parsers/kotlin.js +252 -0
  182. package/src/backend/services/parsers/php.js +113 -0
  183. package/src/backend/services/parsers/python.js +189 -0
  184. package/src/backend/services/parsers/ruby.js +212 -0
  185. package/src/backend/services/parsers/rust.js +97 -0
  186. package/src/backend/services/parsers/swift.js +221 -0
  187. package/src/backend/services/parsers/typescript.js +235 -0
  188. package/src/backend/services/pattern-scan.js +65 -0
  189. package/src/backend/services/patterns.js +281 -0
  190. package/src/backend/services/peer-audit-service.js +123 -0
  191. package/src/backend/services/peer-auth.js +153 -0
  192. package/src/backend/services/peer-capabilities.js +209 -0
  193. package/src/backend/services/peer-connection-service.js +450 -0
  194. package/src/backend/services/peer-grants.js +33 -0
  195. package/src/backend/services/persistence.js +116 -0
  196. package/src/backend/services/personal-sync-service.js +232 -0
  197. package/src/backend/services/pipeline-approvals.js +72 -0
  198. package/src/backend/services/pipeline.js +232 -0
  199. package/src/backend/services/plan-arrivals.js +68 -0
  200. package/src/backend/services/plan-changes-service.js +273 -0
  201. package/src/backend/services/plan-conflict-service.js +288 -0
  202. package/src/backend/services/plan-dependencies.js +91 -0
  203. package/src/backend/services/plan-doc-guard.js +90 -0
  204. package/src/backend/services/plan-documents-service.js +275 -0
  205. package/src/backend/services/plan-event-service.js +154 -0
  206. package/src/backend/services/plan-file-refs.js +106 -0
  207. package/src/backend/services/plan-file-service.js +1564 -0
  208. package/src/backend/services/plan-history-service.js +156 -0
  209. package/src/backend/services/plan-import-service.js +261 -0
  210. package/src/backend/services/plan-item-service.js +1223 -0
  211. package/src/backend/services/plan-migrate-service.js +395 -0
  212. package/src/backend/services/plan-overlay-service.js +173 -0
  213. package/src/backend/services/plan-phases-service.js +182 -0
  214. package/src/backend/services/plan-progress-service.js +134 -0
  215. package/src/backend/services/plan-review-service.js +262 -0
  216. package/src/backend/services/plan-service.js +682 -0
  217. package/src/backend/services/plan-status.js +113 -0
  218. package/src/backend/services/plan-template-publish-service.js +217 -0
  219. package/src/backend/services/plan-templates-service.js +242 -0
  220. package/src/backend/services/plan-templates.js +1164 -0
  221. package/src/backend/services/planned-overlap-actions.js +200 -0
  222. package/src/backend/services/plans-home.js +224 -0
  223. package/src/backend/services/play-forward.js +256 -0
  224. package/src/backend/services/playback-service.js +117 -0
  225. package/src/backend/services/power-service.js +167 -0
  226. package/src/backend/services/power-signals.js +81 -0
  227. package/src/backend/services/pr-draft-service.js +142 -0
  228. package/src/backend/services/presence-service.js +122 -0
  229. package/src/backend/services/pricing.js +60 -0
  230. package/src/backend/services/project-config-service.js +474 -0
  231. package/src/backend/services/project-scanner.js +184 -0
  232. package/src/backend/services/projection-service.js +69 -0
  233. package/src/backend/services/push-notification-service.js +288 -0
  234. package/src/backend/services/recent-projects-service.js +204 -0
  235. package/src/backend/services/record-chain.js +162 -0
  236. package/src/backend/services/recurrence-rule.js +63 -0
  237. package/src/backend/services/recurring-agent.js +89 -0
  238. package/src/backend/services/recurring-scheduler.js +77 -0
  239. package/src/backend/services/recurring-service.js +276 -0
  240. package/src/backend/services/reference-service.js +169 -0
  241. package/src/backend/services/release-public-key.js +30 -0
  242. package/src/backend/services/release-signature.js +64 -0
  243. package/src/backend/services/remote-audio-service.js +224 -0
  244. package/src/backend/services/remote-interaction-service.js +275 -0
  245. package/src/backend/services/remote-terminal-service.js +324 -0
  246. package/src/backend/services/rendition/child/main.js +76 -0
  247. package/src/backend/services/rendition/engine-host.js +249 -0
  248. package/src/backend/services/rendition/engine-lock.js +39 -0
  249. package/src/backend/services/rendition/engine-lock.json +14 -0
  250. package/src/backend/services/rendition/engine-manifest.js +97 -0
  251. package/src/backend/services/rendition/network-proof.js +73 -0
  252. package/src/backend/services/rendition/rendition-service.js +175 -0
  253. package/src/backend/services/replay-frames.js +387 -0
  254. package/src/backend/services/replay-state.js +201 -0
  255. package/src/backend/services/resolvers/base.js +108 -0
  256. package/src/backend/services/resolvers/csharp.js +109 -0
  257. package/src/backend/services/resolvers/go.js +105 -0
  258. package/src/backend/services/resolvers/index.js +60 -0
  259. package/src/backend/services/resolvers/java.js +63 -0
  260. package/src/backend/services/resolvers/kotlin.js +109 -0
  261. package/src/backend/services/resolvers/php.js +89 -0
  262. package/src/backend/services/resolvers/python.js +154 -0
  263. package/src/backend/services/resolvers/ruby.js +103 -0
  264. package/src/backend/services/resolvers/rust.js +77 -0
  265. package/src/backend/services/resolvers/swift.js +98 -0
  266. package/src/backend/services/resolvers/typescript.js +71 -0
  267. package/src/backend/services/retention.js +54 -0
  268. package/src/backend/services/review-architecture.js +236 -0
  269. package/src/backend/services/review-attest.js +68 -0
  270. package/src/backend/services/review-bundle.js +226 -0
  271. package/src/backend/services/review-graduation.js +93 -0
  272. package/src/backend/services/review-host/bitbucket.js +79 -0
  273. package/src/backend/services/review-host/detect.js +80 -0
  274. package/src/backend/services/review-host/github.js +97 -0
  275. package/src/backend/services/review-host/gitlab.js +77 -0
  276. package/src/backend/services/review-host/host-state.js +103 -0
  277. package/src/backend/services/review-host/http.js +58 -0
  278. package/src/backend/services/review-host/switch.js +120 -0
  279. package/src/backend/services/review-marks.js +72 -0
  280. package/src/backend/services/review-notes.js +169 -0
  281. package/src/backend/services/review-other-work.js +90 -0
  282. package/src/backend/services/review-queue-service.js +147 -0
  283. package/src/backend/services/review-risk.js +127 -0
  284. package/src/backend/services/review-task.js +121 -0
  285. package/src/backend/services/rule-approvals.js +268 -0
  286. package/src/backend/services/rule-baseline.js +134 -0
  287. package/src/backend/services/rule-changes.js +162 -0
  288. package/src/backend/services/rule-preview.js +47 -0
  289. package/src/backend/services/rule-proposals.js +104 -0
  290. package/src/backend/services/rule-scope.js +76 -0
  291. package/src/backend/services/rulebook.js +286 -0
  292. package/src/backend/services/rules-at.js +56 -0
  293. package/src/backend/services/rules-overview.js +88 -0
  294. package/src/backend/services/schema-reconciler.js +250 -0
  295. package/src/backend/services/secret-store.js +119 -0
  296. package/src/backend/services/section-workstreams.js +95 -0
  297. package/src/backend/services/self-write-tracker.js +75 -0
  298. package/src/backend/services/sensor-bridge-service.js +285 -0
  299. package/src/backend/services/session-service.js +192 -0
  300. package/src/backend/services/settings-service.js +324 -0
  301. package/src/backend/services/signal-breakpoints.js +172 -0
  302. package/src/backend/services/signed-approval-record.js +86 -0
  303. package/src/backend/services/signed-approvals.js +244 -0
  304. package/src/backend/services/signoff-pack.js +328 -0
  305. package/src/backend/services/signoff-rows.js +114 -0
  306. package/src/backend/services/skill-arrival-service.js +138 -0
  307. package/src/backend/services/skill-model.js +193 -0
  308. package/src/backend/services/skill-use-service.js +140 -0
  309. package/src/backend/services/skills-service.js +150 -0
  310. package/src/backend/services/snapshot-compare-service.js +397 -0
  311. package/src/backend/services/source-control.js +189 -0
  312. package/src/backend/services/spec-links-service.js +123 -0
  313. package/src/backend/services/spec-proposal-withdraw.js +50 -0
  314. package/src/backend/services/spec-proposals-service.js +470 -0
  315. package/src/backend/services/sql/embedded.js +95 -0
  316. package/src/backend/services/sql/index.js +63 -0
  317. package/src/backend/services/sql/refs.js +357 -0
  318. package/src/backend/services/sql/schema.js +312 -0
  319. package/src/backend/services/sql/tokenizer.js +195 -0
  320. package/src/backend/services/stack-overlaps.js +117 -0
  321. package/src/backend/services/stack-service.js +225 -0
  322. package/src/backend/services/state-sync-service.js +384 -0
  323. package/src/backend/services/stuck-sensor-service.js +200 -0
  324. package/src/backend/services/system-discovery.js +481 -0
  325. package/src/backend/services/system-docs-service.js +701 -0
  326. package/src/backend/services/task-attachments-service.js +340 -0
  327. package/src/backend/services/task-grounding.js +60 -0
  328. package/src/backend/services/task-records/check-run-record.js +146 -0
  329. package/src/backend/services/task-records/check-runs.js +115 -0
  330. package/src/backend/services/task-records/heads.js +88 -0
  331. package/src/backend/services/task-records/material-reads.js +225 -0
  332. package/src/backend/services/task-records/read-record.js +100 -0
  333. package/src/backend/services/task-records/record.js +173 -0
  334. package/src/backend/services/task-records/run-record.js +136 -0
  335. package/src/backend/services/task-records/shared-state.js +548 -0
  336. package/src/backend/services/task-records/signing.js +140 -0
  337. package/src/backend/services/task-records/split-signals.js +52 -0
  338. package/src/backend/services/task-records/test-runs.js +164 -0
  339. package/src/backend/services/task-records/trust.js +243 -0
  340. package/src/backend/services/task-rules.js +81 -0
  341. package/src/backend/services/task-workstreams.js +90 -0
  342. package/src/backend/services/terminal-history-service.js +266 -0
  343. package/src/backend/services/terminal-service.js +267 -0
  344. package/src/backend/services/test-clock.js +53 -0
  345. package/src/backend/services/tests/grounding.js +266 -0
  346. package/src/backend/services/tests/junit.js +104 -0
  347. package/src/backend/services/tests/teammate-runs.js +134 -0
  348. package/src/backend/services/tests/test-results.js +234 -0
  349. package/src/backend/services/tree-watcher.js +204 -0
  350. package/src/backend/services/trellis-service.js +204 -0
  351. package/src/backend/services/trusted-roots.js +186 -0
  352. package/src/backend/services/update-download-service.js +342 -0
  353. package/src/backend/services/update-service.js +266 -0
  354. package/src/backend/services/watch-ignore.js +76 -0
  355. package/src/backend/services/webhook-egress.js +206 -0
  356. package/src/backend/services/webrtc-service.js +413 -0
  357. package/src/backend/services/work-changes.js +59 -0
  358. package/src/backend/services/workstream-binding.js +82 -0
  359. package/src/backend/services/workstream-commits.js +116 -0
  360. package/src/backend/services/workstream-imports.js +177 -0
  361. package/src/backend/services/workstream-service.js +335 -0
  362. package/src/backend/services/workstream-symbols.js +223 -0
  363. package/src/backend/services/workstream-watch-service.js +391 -0
  364. package/src/backend/services/worktree-service.js +235 -0
  365. package/src/cli/agent.js +100 -0
  366. package/src/cli/args.js +201 -0
  367. package/src/cli/conformity.js +106 -0
  368. package/src/cli/desktop.js +91 -0
  369. package/src/cli/main.js +409 -0
  370. package/src/cli/pipeline.js +109 -0
  371. package/src/cli/plan-verbs.js +259 -0
  372. package/src/cli/review-adapters.js +218 -0
  373. package/src/cli/review-output.js +93 -0
  374. package/src/cli/review-post.js +89 -0
  375. package/src/cli/review-sink.js +183 -0
  376. package/src/cli/review-skill.js +44 -0
  377. package/src/cli/review-verify.js +104 -0
  378. package/src/cli/review.js +386 -0
  379. package/src/cli/sarif.js +148 -0
  380. package/src/cli/verbs.js +359 -0
  381. package/src/shared/build-info.js +39 -0
  382. package/src/shared/lib/agent-review.js +199 -0
  383. package/src/shared/lib/agent-turns.js +140 -0
  384. package/src/shared/lib/awareness-digest.js +120 -0
  385. package/src/shared/lib/branch-name.js +45 -0
  386. package/src/shared/lib/breakpoint-words.js +118 -0
  387. package/src/shared/lib/budget-words.js +56 -0
  388. package/src/shared/lib/burst.js +69 -0
  389. package/src/shared/lib/call-entry.js +105 -0
  390. package/src/shared/lib/check-compare.js +42 -0
  391. package/src/shared/lib/check-words.js +216 -0
  392. package/src/shared/lib/csv.js +62 -0
  393. package/src/shared/lib/folder-entry.js +87 -0
  394. package/src/shared/lib/freeze-words.js +60 -0
  395. package/src/shared/lib/fuzzy.js +84 -0
  396. package/src/shared/lib/git-state-words.js +80 -0
  397. package/src/shared/lib/grep-entry.js +86 -0
  398. package/src/shared/lib/grounding-line.js +61 -0
  399. package/src/shared/lib/import-line.js +71 -0
  400. package/src/shared/lib/item-status.js +249 -0
  401. package/src/shared/lib/line-changes.js +53 -0
  402. package/src/shared/lib/locator.js +71 -0
  403. package/src/shared/lib/matcher.js +120 -0
  404. package/src/shared/lib/merge-order.js +65 -0
  405. package/src/shared/lib/open-findings.js +68 -0
  406. package/src/shared/lib/other-work.js +108 -0
  407. package/src/shared/lib/package-entry.js +142 -0
  408. package/src/shared/lib/plan-vocab.js +40 -0
  409. package/src/shared/lib/pptx-xml.js +86 -0
  410. package/src/shared/lib/proposal-words.js +61 -0
  411. package/src/shared/lib/recurrence.js +183 -0
  412. package/src/shared/lib/references.js +72 -0
  413. package/src/shared/lib/rule-pattern.js +56 -0
  414. package/src/shared/lib/sdp-fingerprint.js +115 -0
  415. package/src/shared/lib/sdp-minimal.js +123 -0
  416. package/src/shared/lib/secret-paths.js +34 -0
  417. package/src/shared/lib/signal-words.js +172 -0
  418. package/src/shared/lib/signoff.js +56 -0
  419. package/src/shared/lib/skills-note.js +60 -0
  420. package/src/shared/lib/spec-sections.js +78 -0
  421. package/src/shared/lib/symbol-entry.js +60 -0
  422. package/src/shared/lib/tool-phrasing.js +338 -0
  423. package/src/shared/lib/turn-gap.js +27 -0
  424. package/src/shared/lib/workstream-words.js +38 -0
  425. package/src/shared/lib/xlsx-xml.js +144 -0
  426. package/src/shared/lib/zip-reader.js +99 -0
  427. package/src/shared/types/agent.js +27 -0
  428. package/src/shared/types/architecture-rules.js +30 -0
  429. package/src/shared/types/ast.js +15 -0
  430. package/src/shared/types/breakpoint.js +33 -0
  431. package/src/shared/types/channel.js +41 -0
  432. package/src/shared/types/criteria.js +15 -0
  433. package/src/shared/types/graph.js +15 -0
  434. package/src/shared/types/index.js +53 -0
  435. package/src/shared/types/peer.js +36 -0
  436. package/src/shared/types/pipeline.js +15 -0
  437. package/src/shared/types/plan.js +15 -0
  438. package/src/shared/types/play-forward.js +15 -0
  439. package/src/shared/types/power.js +15 -0
  440. package/src/shared/types/presence.js +15 -0
  441. package/src/shared/types/project-config.js +35 -0
  442. package/src/shared/types/project.js +15 -0
  443. package/src/shared/types/record.js +15 -0
  444. package/src/shared/types/recurring.js +15 -0
  445. package/src/shared/types/review.js +15 -0
  446. package/src/shared/types/settings.js +114 -0
  447. package/src/shared/types/stack.js +15 -0
  448. package/src/shared/types/system-doc.js +15 -0
  449. package/src/shared/types/system.js +15 -0
@@ -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 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 record_chain_exports = {};
19
+ __export(record_chain_exports, {
20
+ GENESIS: () => GENESIS,
21
+ beginRecord: () => beginRecord,
22
+ digestOf: () => digestOf,
23
+ linkEvent: () => linkEvent,
24
+ linkHash: () => linkHash,
25
+ recordHead: () => recordHead,
26
+ trimRecord: () => trimRecord,
27
+ verifyRecord: () => verifyRecord
28
+ });
29
+ module.exports = __toCommonJS(record_chain_exports);
30
+ var import_node_crypto = require("node:crypto");
31
+ var import_database = require("./database");
32
+ var import_persistence = require("./persistence");
33
+ const GENESIS = "0".repeat(64);
34
+ const sha256 = (s) => (0, import_node_crypto.createHash)("sha256").update(s).digest("hex");
35
+ function digestOf(e) {
36
+ return sha256(JSON.stringify([e.id, e.at, e.source, e.type, e.session_id, e.agent_type, e.payload]));
37
+ }
38
+ function linkHash(prev, seq, eventId, digest) {
39
+ return sha256(`${prev}
40
+ ${seq}
41
+ ${eventId}
42
+ ${digest}`);
43
+ }
44
+ function rowsOf(sql, params = []) {
45
+ const res = (0, import_database.getDb)().exec(sql, params);
46
+ if (!res.length) return [];
47
+ const { columns, values } = res[0];
48
+ return values.map((v) => Object.fromEntries(columns.map((c, i) => [c, v[i]])));
49
+ }
50
+ const EVENT_COLS = "id, at, source, type, session_id, agent_type, payload";
51
+ function anchor() {
52
+ const a = rowsOf("SELECT through_seq, hash, at FROM record_anchor WHERE id = 1")[0];
53
+ return a ? { seq: Number(a.through_seq), hash: a.hash, at: Number(a.at) } : { seq: 0, hash: GENESIS, at: 0 };
54
+ }
55
+ function recordHead() {
56
+ const last = rowsOf("SELECT seq, hash FROM record_chain ORDER BY seq DESC LIMIT 1")[0];
57
+ if (last) return { seq: Number(last.seq), hash: last.hash };
58
+ const a = anchor();
59
+ return { seq: a.seq, hash: a.hash };
60
+ }
61
+ function linkEvent(eventId, now = Date.now()) {
62
+ const db = (0, import_database.getDb)();
63
+ if (rowsOf("SELECT 1 FROM record_chain WHERE event_id = ?", [eventId]).length) return null;
64
+ const e = rowsOf(`SELECT ${EVENT_COLS} FROM agent_events WHERE id = ?`, [eventId])[0];
65
+ if (!e) return null;
66
+ const head = recordHead();
67
+ const seq = head.seq + 1;
68
+ const digest = digestOf(e);
69
+ const last = Number(rowsOf("SELECT MAX(linked_at) AS t FROM record_chain")[0]?.t ?? 0);
70
+ const linkedAt = Math.max(last, Math.min(Number(e.at), now));
71
+ db.run(
72
+ "INSERT INTO record_chain (seq, event_id, linked_at, digest, prev, hash) VALUES (?, ?, ?, ?, ?, ?)",
73
+ [seq, eventId, linkedAt, digest, head.hash, linkHash(head.hash, seq, eventId, digest)]
74
+ );
75
+ (0, import_persistence.markDirty)();
76
+ return seq;
77
+ }
78
+ function beginRecord(now = Date.now()) {
79
+ if (rowsOf("SELECT 1 FROM record_chain LIMIT 1").length || anchor().seq > 0) return 0;
80
+ const ids = rowsOf(
81
+ "SELECT e.id FROM agent_events e LEFT JOIN record_chain c ON c.event_id = e.id WHERE c.event_id IS NULL ORDER BY e.at ASC, e.rowid ASC"
82
+ ).map((r) => r.id);
83
+ let n = 0;
84
+ for (const id of ids) if (linkEvent(id, now) !== null) n++;
85
+ return n;
86
+ }
87
+ function trimRecord(cutoff, maxRows, now = Date.now()) {
88
+ const db = (0, import_database.getDb)();
89
+ const count = Number(rowsOf("SELECT COUNT(*) AS n FROM record_chain")[0]?.n ?? 0);
90
+ const byTime = Number(rowsOf("SELECT MAX(seq) AS s FROM record_chain WHERE linked_at < ?", [cutoff])[0]?.s ?? 0);
91
+ const over = count - maxRows;
92
+ const byCount = over > 0 ? Number(rowsOf("SELECT seq FROM record_chain ORDER BY seq ASC LIMIT 1 OFFSET ?", [over - 1])[0]?.seq ?? 0) : 0;
93
+ const through = Math.max(byTime, byCount);
94
+ if (through <= 0) return 0;
95
+ const last = rowsOf("SELECT hash FROM record_chain WHERE seq = ?", [through])[0];
96
+ if (!last) return 0;
97
+ const before = Number(rowsOf("SELECT COUNT(*) AS n FROM agent_events")[0]?.n ?? 0);
98
+ db.run("DELETE FROM agent_events WHERE id IN (SELECT event_id FROM record_chain WHERE seq <= ?)", [through]);
99
+ db.run("DELETE FROM record_chain WHERE seq <= ?", [through]);
100
+ db.run(
101
+ "INSERT INTO record_anchor (id, through_seq, hash, at) VALUES (1, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET through_seq = excluded.through_seq, hash = excluded.hash, at = excluded.at",
102
+ [through, last.hash, now]
103
+ );
104
+ (0, import_persistence.markDirty)();
105
+ return before - Number(rowsOf("SELECT COUNT(*) AS n FROM agent_events")[0]?.n ?? 0);
106
+ }
107
+ const MAX_PROBLEMS = 50;
108
+ const PROBLEM_WORDS = {
109
+ changed: "its content changed after it was written",
110
+ removed: "it was removed",
111
+ relinked: "its link in the chain was changed",
112
+ unlinked: "it was added to the log outside the record"
113
+ };
114
+ const day = (ms) => new Date(ms).toISOString().slice(0, 10);
115
+ function verifyRecord() {
116
+ const a = anchor();
117
+ const links = rowsOf("SELECT seq, event_id, linked_at, digest, prev, hash FROM record_chain ORDER BY seq ASC");
118
+ const events = new Map(rowsOf(`SELECT ${EVENT_COLS} FROM agent_events`).map((e) => [e.id, e]));
119
+ const problems = [];
120
+ const say = (p) => {
121
+ if (problems.length < MAX_PROBLEMS) problems.push(p);
122
+ };
123
+ const info = (id) => {
124
+ const e = events.get(id);
125
+ return { at: e ? Number(e.at) : null, type: e?.type ?? null, agentType: e?.agent_type ?? null };
126
+ };
127
+ let prev = a.hash;
128
+ let expected = a.seq + 1;
129
+ for (const l of links) {
130
+ const seq = Number(l.seq);
131
+ if (seq !== expected) {
132
+ say({ seq: expected, eventId: "", kind: "removed", at: null, type: null, agentType: null });
133
+ }
134
+ if (l.prev !== prev || linkHash(l.prev, seq, l.event_id, l.digest) !== l.hash) {
135
+ say({ seq, eventId: l.event_id, kind: "relinked", ...info(l.event_id) });
136
+ }
137
+ const e = events.get(l.event_id);
138
+ if (!e) say({ seq, eventId: l.event_id, kind: "removed", at: null, type: null, agentType: null });
139
+ else if (digestOf(e) !== l.digest) say({ seq, eventId: l.event_id, kind: "changed", ...info(l.event_id) });
140
+ events.delete(l.event_id);
141
+ prev = l.hash;
142
+ expected = seq + 1;
143
+ }
144
+ for (const e of events.values()) say({ seq: null, eventId: e.id, kind: "unlinked", at: Number(e.at), type: e.type, agentType: e.agent_type });
145
+ const head = links.length ? { seq: Number(links[links.length - 1].seq), hash: links[links.length - 1].hash } : { seq: a.seq, hash: a.hash };
146
+ const since = links.length ? Number(links[0].linked_at) : null;
147
+ const ok = problems.length === 0;
148
+ const kept = `${links.length.toLocaleString("en-GB")} entr${links.length === 1 ? "y" : "ies"}${since ? ` since ${day(since)}` : ""}`;
149
+ const words = ok ? links.length === 0 ? "Nothing is in the record yet." : `Intact: ${kept} match the chain${a.seq ? `; older entries were removed by retention on ${day(a.at)}` : ""}.` : `Changed after it was written: ${problems.length}${problems.length === MAX_PROBLEMS ? "+" : ""} of ${kept}. ` + problems.slice(0, 3).map((p) => `${p.seq !== null ? `#${p.seq}` : "an event"}${p.type ? ` (${p.type.replace(/_/g, " ")}${p.agentType ? ` by ${p.agentType}` : ""}${p.at ? `, ${day(p.at)}` : ""})` : ""}: ${PROBLEM_WORDS[p.kind]}`).join("; ") + ".";
150
+ return { ok, entries: links.length, since, trimmedThrough: a.seq, head, problems, words };
151
+ }
152
+ // Annotate the CommonJS export names for ESM import in node:
153
+ 0 && (module.exports = {
154
+ GENESIS,
155
+ beginRecord,
156
+ digestOf,
157
+ linkEvent,
158
+ linkHash,
159
+ recordHead,
160
+ trimRecord,
161
+ verifyRecord
162
+ });
@@ -0,0 +1,63 @@
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 recurrence_rule_exports = {};
19
+ __export(recurrence_rule_exports, {
20
+ parseRecurrenceRule: () => parseRecurrenceRule
21
+ });
22
+ module.exports = __toCommonJS(recurrence_rule_exports);
23
+ var import_recurrence = require("../../shared/lib/recurrence");
24
+ var import_skill_model = require("./skill-model");
25
+ const ID = /^[a-z0-9][a-z0-9-]{0,62}$/;
26
+ const PLAYBOOK = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
27
+ const AT = /^([01]\d|2[0-3]):[0-5]\d$/;
28
+ function parseRecurrenceRule(raw) {
29
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { rule: null, problems: ["a rule must be an object"] };
30
+ const r = raw;
31
+ const problems = [];
32
+ const str = (k) => typeof r[k] === "string" ? r[k].trim() : "";
33
+ const id = str("id");
34
+ if (!ID.test(id)) problems.push("id must be lower-case letters, digits and dashes, at most 63");
35
+ const playbook = str("playbook");
36
+ if (!PLAYBOOK.test(playbook)) problems.push("playbook must name a playbook (a plan template id)");
37
+ const title = str("title");
38
+ if (!title || title.length > 120) problems.push("title must be 1 to 120 characters");
39
+ const every = r.every === "day" || r.every === "week" || r.every === "month" ? r.every : null;
40
+ if (!every) problems.push("every must be day, week or month");
41
+ let on = typeof r.on === "number" && Number.isInteger(r.on) ? r.on : every === "day" ? 1 : NaN;
42
+ if (every === "week" && !(on >= 1 && on <= 7)) problems.push("on must be the weekday, 1 (Monday) to 7 (Sunday)");
43
+ if (every === "month" && !(on >= 1 && on <= 28)) problems.push("on must be the day of the month, 1 to 28");
44
+ if (every === "day") on = 1;
45
+ const at = str("at");
46
+ if (!AT.test(at)) problems.push("at must be a time, HH:MM");
47
+ const timeZone = str("timeZone");
48
+ if (!timeZone || !(0, import_recurrence.isTimeZone)(timeZone)) problems.push("timeZone must be an IANA time zone, e.g. Europe/London");
49
+ const { skills, problems: skillProblems } = (0, import_skill_model.normaliseSkills)(r.skills);
50
+ problems.push(...skillProblems);
51
+ const since = str("since");
52
+ if (!since || Number.isNaN(Date.parse(since))) problems.push("since must be an ISO date");
53
+ const by = str("by").slice(0, 200);
54
+ if (problems.length > 0 || !every) return { rule: null, problems };
55
+ return {
56
+ rule: { id, playbook, title, every, on, at, timeZone, carryOver: r.carryOver === true, skills, since: new Date(since).toISOString(), by },
57
+ problems: []
58
+ };
59
+ }
60
+ // Annotate the CommonJS export names for ESM import in node:
61
+ 0 && (module.exports = {
62
+ parseRecurrenceRule
63
+ });
@@ -0,0 +1,89 @@
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 recurring_agent_exports = {};
19
+ __export(recurring_agent_exports, {
20
+ RUN_AGENTS: () => RUN_AGENTS,
21
+ isRunAgent: () => isRunAgent,
22
+ runAgentsFor: () => runAgentsFor,
23
+ runCommand: () => runCommand,
24
+ runPrompt: () => runPrompt,
25
+ setRunAgent: () => setRunAgent,
26
+ startRunAgent: () => startRunAgent
27
+ });
28
+ module.exports = __toCommonJS(recurring_agent_exports);
29
+ var import_database = require("./database");
30
+ var import_persistence = require("./persistence");
31
+ var import_terminal_service = require("./terminal-service");
32
+ const RUN_AGENTS = { claude: "Claude Code", codex: "Codex" };
33
+ function isRunAgent(v) {
34
+ return v === "claude" || v === "codex";
35
+ }
36
+ function runAgentsFor(projectRoot) {
37
+ const out = {};
38
+ const res = (0, import_database.getDb)().exec("SELECT rule_id, agent, by_name, at FROM recurring_agents WHERE project_root = ?", [projectRoot]);
39
+ for (const row of res[0]?.values ?? []) {
40
+ const [ruleId, agent, by, at] = row;
41
+ if (isRunAgent(agent)) out[ruleId] = { agent, by, at };
42
+ }
43
+ return out;
44
+ }
45
+ function setRunAgent(projectRoot, ruleId, agent, by, now = Date.now()) {
46
+ if (agent === null) {
47
+ (0, import_database.getDb)().run("DELETE FROM recurring_agents WHERE project_root = ? AND rule_id = ?", [projectRoot, ruleId]);
48
+ } else {
49
+ (0, import_database.getDb)().run("INSERT OR REPLACE INTO recurring_agents (project_root, rule_id, agent, by_name, at) VALUES (?, ?, ?, ?, ?)", [projectRoot, ruleId, agent, by, now]);
50
+ }
51
+ (0, import_persistence.markDirty)();
52
+ return agent === null ? null : { agent, by, at: now };
53
+ }
54
+ function runPrompt(plan) {
55
+ const title = plan.title.replace(/['"`$\\\n\r]/g, " ").replace(/\s+/g, " ").trim();
56
+ return `Work the CodeTrellis plan "${title}" (plan_uid ${plan.uid}): call get_next_item with that plan_uid, claim the task, read its brief with get_brief, do it, and repeat until no task is left.`;
57
+ }
58
+ function runCommand(agent, plan, program = process.env.CODETRELLIS_RUN_AGENT_COMMAND || agent) {
59
+ return `${program} '${runPrompt(plan)}'
60
+ `;
61
+ }
62
+ const SHELL_SETTLE_MS = 500;
63
+ function startRunAgent(projectRoot, ruleId, plan, may, onCreated) {
64
+ const setting = runAgentsFor(projectRoot)[ruleId];
65
+ if (!setting) return null;
66
+ const name = RUN_AGENTS[setting.agent];
67
+ if (may !== true) return { agent: setting.agent, terminalId: null, words: `${name} was not started: ${may}` };
68
+ try {
69
+ const session = (0, import_terminal_service.createTerminal)({ preset: "shell", cwd: projectRoot, title: `${plan.title} \xB7 ${name}` });
70
+ setTimeout(() => {
71
+ (0, import_terminal_service.writeTerminal)(session.id, runCommand(setting.agent, plan));
72
+ }, SHELL_SETTLE_MS);
73
+ onCreated?.(session);
74
+ return { agent: setting.agent, terminalId: session.id, words: `${name} started in a terminal on the computer` };
75
+ } catch (err) {
76
+ const message = err instanceof Error ? err.message : String(err);
77
+ return { agent: setting.agent, terminalId: null, words: `${name} was not started: ${message}` };
78
+ }
79
+ }
80
+ // Annotate the CommonJS export names for ESM import in node:
81
+ 0 && (module.exports = {
82
+ RUN_AGENTS,
83
+ isRunAgent,
84
+ runAgentsFor,
85
+ runCommand,
86
+ runPrompt,
87
+ setRunAgent,
88
+ startRunAgent
89
+ });
@@ -0,0 +1,77 @@
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 recurring_scheduler_exports = {};
19
+ __export(recurring_scheduler_exports, {
20
+ startRecurringScheduler: () => startRecurringScheduler,
21
+ startRunsDueBetween: () => startRunsDueBetween,
22
+ stopRecurringScheduler: () => stopRecurringScheduler
23
+ });
24
+ module.exports = __toCommonJS(recurring_scheduler_exports);
25
+ var import_recurrence = require("../../shared/lib/recurrence");
26
+ var import_trusted_roots = require("./trusted-roots");
27
+ var import_recurring_service = require("./recurring-service");
28
+ var import_plan_service = require("./plan-service");
29
+ const SCHEDULE = { author: "schedule", authorType: "system" };
30
+ const tickMs = () => Number(process.env.CODETRELLIS_RECURRING_TICK_MS) || 6e4;
31
+ let lastTick = null;
32
+ let timer = null;
33
+ function startRunsDueBetween(roots, from, now) {
34
+ const started = [];
35
+ for (const root of roots) {
36
+ let rules;
37
+ try {
38
+ rules = (0, import_recurring_service.rulesOf)(root);
39
+ } catch {
40
+ continue;
41
+ }
42
+ for (const rule of rules) {
43
+ const p = (0, import_recurrence.currentPeriod)(rule, now);
44
+ const at = (0, import_recurrence.dueAt)(rule, p);
45
+ if (at <= from || at > now || at < Date.parse(rule.since)) continue;
46
+ if ((0, import_plan_service.getPlan)((0, import_recurring_service.runUid)(root, rule.id, (0, import_recurrence.periodId)(p)))) continue;
47
+ try {
48
+ started.push({ root, run: (0, import_recurring_service.startRun)(root, rule.id, SCHEDULE, now) });
49
+ } catch (err) {
50
+ console.warn(`[Recurring] Could not start ${rule.title} in ${root}:`, err instanceof Error ? err.message : err);
51
+ }
52
+ }
53
+ }
54
+ return started;
55
+ }
56
+ function startRecurringScheduler(onStarted) {
57
+ if (timer) return;
58
+ lastTick = Date.now();
59
+ timer = setInterval(() => {
60
+ const now = Date.now();
61
+ const from = lastTick ?? now;
62
+ lastTick = now;
63
+ for (const { root, run } of startRunsDueBetween((0, import_trusted_roots.listTrustedRoots)(), from, now)) onStarted(root, run);
64
+ }, tickMs());
65
+ timer.unref?.();
66
+ }
67
+ function stopRecurringScheduler() {
68
+ if (timer) clearInterval(timer);
69
+ timer = null;
70
+ lastTick = null;
71
+ }
72
+ // Annotate the CommonJS export names for ESM import in node:
73
+ 0 && (module.exports = {
74
+ startRecurringScheduler,
75
+ startRunsDueBetween,
76
+ stopRecurringScheduler
77
+ });
@@ -0,0 +1,276 @@
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 recurring_service_exports = {};
29
+ __export(recurring_service_exports, {
30
+ RecurringError: () => RecurringError,
31
+ dismissDue: () => dismissDue,
32
+ recurrenceOf: () => recurrenceOf,
33
+ removeRule: () => removeRule,
34
+ rulesOf: () => rulesOf,
35
+ runInfo: () => runInfo,
36
+ runUid: () => runUid,
37
+ seriesFor: () => seriesFor,
38
+ seriesOf: () => seriesOf,
39
+ setRule: () => setRule,
40
+ startRun: () => startRun
41
+ });
42
+ module.exports = __toCommonJS(recurring_service_exports);
43
+ var import_node_crypto = __toESM(require("node:crypto"));
44
+ var import_node_path = __toESM(require("node:path"));
45
+ var import_recurrence = require("../../shared/lib/recurrence");
46
+ var import_project_config_service = require("./project-config-service");
47
+ var import_recurrence_rule = require("./recurrence-rule");
48
+ var import_plan_templates = require("./plan-templates");
49
+ var import_plan_templates_service = require("./plan-templates-service");
50
+ var import_plan_service = require("./plan-service");
51
+ var planItemService = __toESM(require("./plan-item-service"));
52
+ var import_git_identity = require("./git-identity");
53
+ var import_plans_home = require("./plans-home");
54
+ var import_database = require("./database");
55
+ var import_persistence = require("./persistence");
56
+ var import_recurring_agent = require("./recurring-agent");
57
+ var import_plan_file_service = require("./plan-file-service");
58
+ const SHOWN = 8;
59
+ const LOOK_BACK = 52;
60
+ class RecurringError extends Error {
61
+ constructor(message, status) {
62
+ super(message);
63
+ this.status = status;
64
+ }
65
+ status;
66
+ }
67
+ function rulesOf(projectRoot) {
68
+ return (0, import_project_config_service.getProjectConfig)(projectRoot).recurring ?? [];
69
+ }
70
+ function ruleOf(projectRoot, id) {
71
+ const rule = rulesOf(projectRoot).find((r) => r.id === id);
72
+ if (!rule) throw new RecurringError(`No recurring playbook "${id}" in this project`, 404);
73
+ return rule;
74
+ }
75
+ function setRule(projectRoot, raw, by, now = Date.now()) {
76
+ const existing = rulesOf(projectRoot).find((r) => r.id === raw.id);
77
+ const { rule, problems } = (0, import_recurrence_rule.parseRecurrenceRule)({ ...raw, since: existing?.since ?? new Date(now).toISOString(), by });
78
+ if (!rule) throw new RecurringError(problems.join("; "), 400);
79
+ if (!(0, import_plan_templates.getTemplate)(rule.playbook, projectRoot)) throw new RecurringError(`No playbook "${rule.playbook}" in this project`, 400);
80
+ (0, import_project_config_service.updateProjectConfig)(projectRoot, { recurring: [...rulesOf(projectRoot).filter((r) => r.id !== rule.id), rule] });
81
+ return rule;
82
+ }
83
+ function removeRule(projectRoot, id) {
84
+ ruleOf(projectRoot, id);
85
+ (0, import_project_config_service.updateProjectConfig)(projectRoot, { recurring: rulesOf(projectRoot).filter((r) => r.id !== id) });
86
+ }
87
+ function seriesKey(projectRoot) {
88
+ const folder = (0, import_project_config_service.getProjectConfig)(projectRoot).plans?.folder;
89
+ if (folder?.kind === "git") return `git:${(0, import_plans_home.normaliseRemote)(folder.remote)}`;
90
+ if (folder?.kind === "synced") return `synced:${folder.provider}:${folder.place}`;
91
+ const origin = (0, import_git_identity.getNormalisedOriginUrl)(projectRoot);
92
+ return origin ? `origin:${origin}` : `folder:${import_node_path.default.basename(import_node_path.default.resolve(projectRoot))}`;
93
+ }
94
+ function runUid(projectRoot, ruleId, period) {
95
+ const h = import_node_crypto.default.createHash("sha256").update(`codetrellis-recurring\0${seriesKey(projectRoot)}\0${ruleId}\0${period}`).digest("hex");
96
+ return `${h.slice(0, 8)}-${h.slice(8, 12)}-5${h.slice(13, 16)}-${(parseInt(h[16], 16) & 3 | 8).toString(16)}${h.slice(17, 20)}-${h.slice(20, 32)}`;
97
+ }
98
+ const SETTLED = /* @__PURE__ */ new Set(["done", "skipped"]);
99
+ function runState(plan) {
100
+ return plan.status === "completed" || plan.status === "archived" ? "done" : "in_progress";
101
+ }
102
+ function runWords(label, state, rule, due) {
103
+ switch (state) {
104
+ case "done":
105
+ return `${label} \u2713 done`;
106
+ case "in_progress":
107
+ return `${label} \u25D0 in progress`;
108
+ case "missed":
109
+ return `${label} \u2717 missed`;
110
+ case "due":
111
+ return `${label} due ${(0, import_recurrence.sinceWords)(rule, due)}`;
112
+ case "next":
113
+ return `${label} next, ${(0, import_recurrence.momentWords)(rule.timeZone, due)}`;
114
+ }
115
+ }
116
+ function seriesOf(projectRoot, rule, now = Date.now()) {
117
+ const since = Date.parse(rule.since);
118
+ const current = (0, import_recurrence.currentPeriod)(rule, now);
119
+ const past = [];
120
+ for (let p = current, i = 0; i < SHOWN && (0, import_recurrence.dueAt)(rule, p) >= since; p = (0, import_recurrence.previousPeriod)(p), i++) past.unshift(p);
121
+ const runs = past.map((p) => {
122
+ const period = (0, import_recurrence.periodId)(p);
123
+ const at = (0, import_recurrence.dueAt)(rule, p);
124
+ const plan = (0, import_plan_service.getPlan)(runUid(projectRoot, rule.id, period));
125
+ const state = plan ? runState(plan) : p === current ? "due" : "missed";
126
+ const label = (0, import_recurrence.periodLabel)(p);
127
+ return { period, label, dueAt: at, state, planUid: plan?.uid ?? null, words: runWords(label, state, rule, at) };
128
+ });
129
+ const next = (0, import_recurrence.nextPeriod)(current);
130
+ const nextAt = (0, import_recurrence.dueAt)(rule, next);
131
+ runs.push({ period: (0, import_recurrence.periodId)(next), label: (0, import_recurrence.periodLabel)(next), dueAt: nextAt, state: "next", planUid: null, words: runWords((0, import_recurrence.periodLabel)(next), "next", rule, nextAt) });
132
+ const open = runs.find((r) => r.state === "due");
133
+ return {
134
+ rule,
135
+ words: (0, import_recurrence.seriesWords)(rule),
136
+ runs,
137
+ due: open ? { period: open.period, label: open.label, since: open.dueAt, words: `${rule.title} is due ${(0, import_recurrence.sinceWords)(rule, open.dueAt)}`, dismissed: isDismissed(projectRoot, rule.id, open.period) } : null,
138
+ agent: (0, import_recurring_agent.runAgentsFor)(projectRoot)[rule.id] ?? null
139
+ };
140
+ }
141
+ function seriesFor(projectRoot, now = Date.now()) {
142
+ return rulesOf(projectRoot).map((r) => seriesOf(projectRoot, r, now));
143
+ }
144
+ function runInfo(planUid) {
145
+ const row = (0, import_database.getDb)().exec("SELECT rule_id, period, label, previous_uid, carried_json, started_by, started_at FROM recurring_runs WHERE plan_uid = ?", [planUid])[0]?.values[0];
146
+ if (!row) return null;
147
+ let carried = [];
148
+ try {
149
+ carried = JSON.parse(String(row[4]));
150
+ } catch {
151
+ }
152
+ return {
153
+ rule: String(row[0]),
154
+ period: String(row[1]),
155
+ label: String(row[2]),
156
+ previous: row[3] === null ? null : String(row[3]),
157
+ carried,
158
+ startedBy: String(row[5]),
159
+ startedAt: Number(row[6])
160
+ };
161
+ }
162
+ function isDismissed(projectRoot, ruleId, period) {
163
+ return ((0, import_database.getDb)().exec("SELECT 1 FROM recurring_dismissed WHERE project_root = ? AND rule_id = ? AND period = ?", [projectRoot, ruleId, period])[0]?.values.length ?? 0) > 0;
164
+ }
165
+ function dismissDue(projectRoot, ruleId, by, now = Date.now()) {
166
+ const s = seriesOf(projectRoot, ruleOf(projectRoot, ruleId), now);
167
+ if (!s.due) throw new RecurringError(`${s.rule.title} has no run due now`, 409);
168
+ (0, import_database.getDb)().run("INSERT OR REPLACE INTO recurring_dismissed (project_root, rule_id, period, by_name, at) VALUES (?, ?, ?, ?, ?)", [projectRoot, ruleId, s.due.period, by, now]);
169
+ (0, import_persistence.markDirty)();
170
+ return { period: s.due.period, label: s.due.label };
171
+ }
172
+ function startRun(projectRoot, ruleId, by, now = Date.now()) {
173
+ const rule = ruleOf(projectRoot, ruleId);
174
+ const p = (0, import_recurrence.currentPeriod)(rule, now);
175
+ if ((0, import_recurrence.dueAt)(rule, p) < Date.parse(rule.since)) {
176
+ throw new RecurringError(`${rule.title} is not due yet: the first run is ${(0, import_recurrence.momentWords)(rule.timeZone, (0, import_recurrence.dueAt)(rule, (0, import_recurrence.nextPeriod)(p)))}`, 409);
177
+ }
178
+ const period = (0, import_recurrence.periodId)(p);
179
+ const label = (0, import_recurrence.periodLabel)(p);
180
+ const uid = runUid(projectRoot, rule.id, period);
181
+ const existing = (0, import_plan_service.getPlan)(uid);
182
+ if (existing) {
183
+ return { plan: existing, created: false, info: runInfo(uid) ?? { rule: rule.id, period, label, previous: null, carried: [] } };
184
+ }
185
+ let previous = null;
186
+ for (let q = (0, import_recurrence.previousPeriod)(p), i = 0; i < LOOK_BACK; q = (0, import_recurrence.previousPeriod)(q), i++) {
187
+ const u = runUid(projectRoot, rule.id, (0, import_recurrence.periodId)(q));
188
+ if ((0, import_plan_service.getPlan)(u)) {
189
+ previous = { uid: u, label: (0, import_recurrence.periodLabel)(q) };
190
+ break;
191
+ }
192
+ }
193
+ const applied = (0, import_plan_templates_service.applyTemplate)({
194
+ templateId: rule.playbook,
195
+ projectPath: projectRoot,
196
+ title: `${rule.title} \u2014 ${label}`,
197
+ author: by.author,
198
+ authorType: by.authorType,
199
+ uid
200
+ });
201
+ const actions = () => planItemService.listAllItems(uid).filter((i) => i.kind === "action");
202
+ if (rule.skills.length > 0) {
203
+ for (const item of actions()) {
204
+ const have = new Set((item.skills ?? []).map((s) => s.name));
205
+ const add = rule.skills.filter((s) => !have.has(s.name));
206
+ if (add.length > 0) planItemService.updateItem(item.uid, { skills: [...item.skills ?? [], ...add], author: by.author, authorType: by.authorType });
207
+ }
208
+ }
209
+ const carried = [];
210
+ if (rule.carryOver && previous) {
211
+ const titles = new Set(actions().map((i) => i.title.trim().toLowerCase()));
212
+ for (const item of planItemService.listAllItems(previous.uid)) {
213
+ if (item.kind !== "action" || SETTLED.has(item.status ?? "") || titles.has(item.title.trim().toLowerCase())) continue;
214
+ const copy = planItemService.createItem({
215
+ planUid: uid,
216
+ kind: "action",
217
+ title: item.title,
218
+ body: item.body,
219
+ fileSpecs: item.fileSpecs,
220
+ skills: item.skills,
221
+ author: by.author,
222
+ authorType: by.authorType
223
+ });
224
+ carried.push({ itemUid: copy.uid, from: previous.label });
225
+ }
226
+ }
227
+ (0, import_database.getDb)().run(
228
+ "INSERT OR REPLACE INTO recurring_runs (plan_uid, project_root, rule_id, period, label, previous_uid, carried_json, started_at, started_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
229
+ [uid, projectRoot, rule.id, period, label, previous?.uid ?? null, JSON.stringify(carried), now, by.author]
230
+ );
231
+ (0, import_persistence.markDirty)();
232
+ (0, import_plan_file_service.exportIfSharedByDefault)(uid, projectRoot);
233
+ return { plan: (0, import_plan_service.getPlan)(uid) ?? applied.plan, created: true, info: { rule: rule.id, period, label, previous: previous?.uid ?? null, carried, startedBy: by.author, startedAt: now } };
234
+ }
235
+ function recurrenceOf(projectRoot, planUid, now = Date.now()) {
236
+ const rules = rulesOf(projectRoot);
237
+ let info = runInfo(planUid);
238
+ if (!info) {
239
+ outer: for (const rule2 of rules) {
240
+ for (let p = (0, import_recurrence.currentPeriod)(rule2, now), i = 0; i < LOOK_BACK; p = (0, import_recurrence.previousPeriod)(p), i++) {
241
+ if (runUid(projectRoot, rule2.id, (0, import_recurrence.periodId)(p)) === planUid) {
242
+ info = { rule: rule2.id, period: (0, import_recurrence.periodId)(p), label: (0, import_recurrence.periodLabel)(p), previous: null, carried: [] };
243
+ break outer;
244
+ }
245
+ }
246
+ }
247
+ }
248
+ if (!info) return null;
249
+ const rule = rules.find((r) => r.id === info.rule);
250
+ const title = rule?.title ?? info.rule;
251
+ const carriedTasks = info.carried.map((c) => ({ ...c, title: planItemService.getItem(c.itemUid)?.title ?? "(removed)" }));
252
+ const who = info.startedBy === "schedule" ? "started by the schedule" : info.startedBy ? `started by ${info.startedBy}` : null;
253
+ const from = info.carried[0]?.from;
254
+ const carriedWords = carriedTasks.length ? `${carriedTasks.length} ${carriedTasks.length === 1 ? "task" : "tasks"} carried from ${from}` : null;
255
+ return {
256
+ ...info,
257
+ title,
258
+ words: rule ? (0, import_recurrence.seriesWords)(rule) : "",
259
+ line: [title, `${info.label} run`, who, carriedWords].filter(Boolean).join(" \xB7 "),
260
+ carriedTasks
261
+ };
262
+ }
263
+ // Annotate the CommonJS export names for ESM import in node:
264
+ 0 && (module.exports = {
265
+ RecurringError,
266
+ dismissDue,
267
+ recurrenceOf,
268
+ removeRule,
269
+ rulesOf,
270
+ runInfo,
271
+ runUid,
272
+ seriesFor,
273
+ seriesOf,
274
+ setRule,
275
+ startRun
276
+ });