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,136 @@
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 run_record_exports = {};
19
+ __export(run_record_exports, {
20
+ MAX_RUN_RECORD_BYTES: () => MAX_RUN_RECORD_BYTES,
21
+ isRunPath: () => isRunPath,
22
+ parseRunRecord: () => parseRunRecord,
23
+ runFilesOf: () => runFilesOf,
24
+ runRecordBytes: () => runRecordBytes,
25
+ serializeRunRecord: () => serializeRunRecord
26
+ });
27
+ module.exports = __toCommonJS(run_record_exports);
28
+ var import_yaml = require("yaml");
29
+ var import_signing = require("./signing");
30
+ const KIND = "test-run";
31
+ const MAX_RUN_RECORD_BYTES = 512 * 1024;
32
+ const MAX_FILES = 5e3;
33
+ const MAX_FAILING_PER_FILE = 50;
34
+ const MAX_DIRTY = 500;
35
+ const WRITER = /^[a-f0-9]{8,32}$/;
36
+ const SHA = /^[a-f0-9]{40}$/;
37
+ const text = (v, max) => typeof v === "string" && v.length > 0 ? v.slice(0, max) : null;
38
+ const count = (v) => Number.isSafeInteger(v) && v >= 0 ? v : 0;
39
+ function isRunPath(p) {
40
+ return typeof p === "string" && p.length > 0 && p.length <= 1024 && !p.includes("\\") && !p.includes("\0") && !p.startsWith("/") && !/^[A-Za-z]:/.test(p) && !p.split("/").some((x) => x === ".." || x === "");
41
+ }
42
+ function bodyOf(r) {
43
+ return {
44
+ kind: KIND,
45
+ writer: r.writer,
46
+ name: r.name,
47
+ counter: r.counter,
48
+ at: new Date(r.at).toISOString(),
49
+ by: r.by,
50
+ commit: r.commit,
51
+ dirty: r.dirty,
52
+ report: r.report,
53
+ totals: r.totals,
54
+ files: r.files.map((f) => ({ file: f.file, passed: f.passed, failed: f.failed, skipped: f.skipped, failing: f.failing.map((x) => ({ name: x.name, result: x.result, why: x.why })) }))
55
+ };
56
+ }
57
+ function runRecordBytes(r) {
58
+ return (0, import_signing.canonicalJson)(bodyOf(r));
59
+ }
60
+ function serializeRunRecord(r, signature) {
61
+ const body = signature ? { ...bodyOf(r), signature } : bodyOf(r);
62
+ return `# CodeTrellis: one device's latest test run, by test file, and the commit it ran against.
63
+ ${(0, import_yaml.stringify)(body, { lineWidth: 0 })}`;
64
+ }
65
+ function parseRunRecord(source) {
66
+ if (Buffer.byteLength(source, "utf8") > MAX_RUN_RECORD_BYTES) return { error: "larger than a run record can be" };
67
+ let raw;
68
+ try {
69
+ raw = (0, import_yaml.parse)(source, { maxAliasCount: 0 });
70
+ } catch {
71
+ return { error: "not YAML" };
72
+ }
73
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { error: "not a record" };
74
+ const { signature: rawSignature, ...r } = raw;
75
+ if (r.kind !== KIND) return { error: "not a test-run record" };
76
+ const writer = typeof r.writer === "string" && WRITER.test(r.writer) ? r.writer : null;
77
+ if (!writer) return { error: "no writer" };
78
+ const counter = Number.isSafeInteger(r.counter) && r.counter > 0 ? r.counter : null;
79
+ if (!counter) return { error: "no counter" };
80
+ const at = typeof r.at === "string" ? Date.parse(r.at) : NaN;
81
+ if (!Number.isFinite(at)) return { error: "no time" };
82
+ const by = r.by && typeof r.by === "object" ? r.by : {};
83
+ const t = r.totals && typeof r.totals === "object" ? r.totals : {};
84
+ const files = [];
85
+ for (const f of Array.isArray(r.files) ? r.files.slice(0, MAX_FILES) : []) {
86
+ if (!f || typeof f !== "object" || !isRunPath(f.file)) continue;
87
+ const ff = f;
88
+ const failing = [];
89
+ for (const x of Array.isArray(ff.failing) ? ff.failing.slice(0, MAX_FAILING_PER_FILE) : []) {
90
+ const xx = x && typeof x === "object" ? x : {};
91
+ const name = text(xx.name, 300);
92
+ if (!name) continue;
93
+ failing.push({ name, result: xx.result === "error" ? "error" : "failed", why: text(xx.why, 500) });
94
+ }
95
+ files.push({ file: ff.file, passed: count(ff.passed), failed: Math.max(count(ff.failed), failing.length), skipped: count(ff.skipped), failing });
96
+ }
97
+ return {
98
+ signed: { bytes: (0, import_signing.canonicalJson)(r), signature: (0, import_signing.parseSignature)(rawSignature) },
99
+ record: {
100
+ writer,
101
+ name: text(r.name, 120) ?? "someone",
102
+ counter,
103
+ at,
104
+ by: { author: text(by.author, 120) ?? "someone", authorType: text(by.authorType, 40) ?? "unknown" },
105
+ commit: typeof r.commit === "string" && SHA.test(r.commit) ? r.commit : null,
106
+ dirty: (Array.isArray(r.dirty) ? r.dirty : []).filter(isRunPath).slice(0, MAX_DIRTY),
107
+ report: text(r.report, 300) ?? "a test report",
108
+ totals: { tests: count(t.tests), passed: count(t.passed), failed: count(t.failed), errors: count(t.errors), skipped: count(t.skipped) },
109
+ files
110
+ }
111
+ };
112
+ }
113
+ function runFilesOf(cases) {
114
+ const by = /* @__PURE__ */ new Map();
115
+ for (const c of cases) {
116
+ if (!c.testFile || !isRunPath(c.testFile)) continue;
117
+ let f = by.get(c.testFile);
118
+ if (!f) {
119
+ f = { file: c.testFile, passed: 0, failed: 0, skipped: 0, failing: [] };
120
+ by.set(c.testFile, f);
121
+ }
122
+ if (c.result === "passed") f.passed++;
123
+ else if (c.result === "skipped") f.skipped++;
124
+ else if (++f.failed <= MAX_FAILING_PER_FILE) f.failing.push({ name: c.name.slice(0, 300), result: c.result === "error" ? "error" : "failed", why: c.message ? c.message.slice(0, 500) : null });
125
+ }
126
+ return [...by.values()].sort((a, b) => a.file.localeCompare(b.file)).slice(0, MAX_FILES);
127
+ }
128
+ // Annotate the CommonJS export names for ESM import in node:
129
+ 0 && (module.exports = {
130
+ MAX_RUN_RECORD_BYTES,
131
+ isRunPath,
132
+ parseRunRecord,
133
+ runFilesOf,
134
+ runRecordBytes,
135
+ serializeRunRecord
136
+ });
@@ -0,0 +1,548 @@
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 shared_state_exports = {};
29
+ __export(shared_state_exports, {
30
+ RECORDS_DIR: () => RECORDS_DIR,
31
+ getSharedTaskState: () => getSharedTaskState,
32
+ isSharingMaterialReads: () => isSharingMaterialReads,
33
+ isSharingTaskState: () => isSharingTaskState,
34
+ keepMyState: () => keepMyState,
35
+ readAndTell: () => readAndTell,
36
+ readProjectRecords: () => readProjectRecords,
37
+ setCheckRunsChangedListener: () => setCheckRunsChangedListener,
38
+ setRecordAppliedListener: () => setRecordAppliedListener,
39
+ setRunsChangedListener: () => setRunsChangedListener,
40
+ setSharedMaterialReads: () => setSharedMaterialReads,
41
+ setSharedTaskState: () => setSharedTaskState,
42
+ setSplitChangedListener: () => setSplitChangedListener,
43
+ shareMaterialRead: () => shareMaterialRead,
44
+ startRecordWatcher: () => startRecordWatcher,
45
+ stopRecordWatcher: () => stopRecordWatcher,
46
+ trustTeammateKey: () => trustTeammateKey,
47
+ writeRecordFor: () => writeRecordFor,
48
+ writerId: () => writerId,
49
+ writerName: () => writerName
50
+ });
51
+ module.exports = __toCommonJS(shared_state_exports);
52
+ var import_node_fs = __toESM(require("node:fs"));
53
+ var import_node_path = __toESM(require("node:path"));
54
+ var import_node_crypto = __toESM(require("node:crypto"));
55
+ var import_chokidar = __toESM(require("chokidar"));
56
+ var import_database = require("../database");
57
+ var import_persistence = require("../persistence");
58
+ var import_confined_fs = require("../confined-fs");
59
+ var import_settings_service = require("../settings-service");
60
+ var import_plan_service = require("../plan-service");
61
+ var import_plan_item_service = require("../plan-item-service");
62
+ var import_plan_file_service = require("../plan-file-service");
63
+ var import_plans_home = require("../plans-home");
64
+ var import_heads = require("./heads");
65
+ var import_cloud_files = require("../cloud-files");
66
+ var import_record = require("./record");
67
+ var import_material_reads = require("./material-reads");
68
+ var import_test_runs = require("./test-runs");
69
+ var import_teammate_runs = require("../tests/teammate-runs");
70
+ var import_test_results = require("../tests/test-results");
71
+ var import_check_runs = require("./check-runs");
72
+ var import_check_runs2 = require("../check-runs");
73
+ var import_trust = require("./trust");
74
+ const MAX_RECORDS_PER_ITEM = 5e3;
75
+ const RECORDS_DIR = import_node_path.default.join(".codetrellis", "records");
76
+ function rowOf(projectRoot) {
77
+ const v = (0, import_database.getDb)().exec("SELECT enabled, changed_at, changed_by FROM shared_task_state WHERE project_root = ?", [projectRoot])[0]?.values[0];
78
+ return v ? { enabled: Number(v[0]) === 1, changedAt: Number(v[1]), changedBy: String(v[2]) } : null;
79
+ }
80
+ function isSharingTaskState(projectRoot) {
81
+ return rowOf(projectRoot)?.enabled === true;
82
+ }
83
+ function writerId() {
84
+ const v = (0, import_database.getDb)().exec("SELECT writer FROM task_record_writer WHERE id = 1")[0]?.values[0];
85
+ if (v) return String(v[0]);
86
+ const id = import_node_crypto.default.randomBytes(8).toString("hex");
87
+ (0, import_database.getDb)().run("INSERT OR IGNORE INTO task_record_writer (id, writer) VALUES (1, ?)", [id]);
88
+ (0, import_persistence.markDirty)();
89
+ return writerId();
90
+ }
91
+ function writerName(projectRoot) {
92
+ return (0, import_settings_service.getSettings)().identity.displayName || (0, import_settings_service.readGitIdentity)(projectRoot).name || "someone";
93
+ }
94
+ function counts(projectRoot) {
95
+ const writers = /* @__PURE__ */ new Set();
96
+ let records = 0;
97
+ for (const { files } of itemFolders(projectRoot)) {
98
+ for (const f of files) {
99
+ records++;
100
+ const m = /^([a-f0-9]{8,32})-\d+/.exec(f);
101
+ if (m) writers.add(m[1]);
102
+ }
103
+ }
104
+ return { records, writers: writers.size };
105
+ }
106
+ function checkedCounts(projectRoot) {
107
+ const me = writerId();
108
+ const ctx = (0, import_trust.checkContext)(projectRoot);
109
+ let verified = 0;
110
+ const reasons = /* @__PURE__ */ new Map();
111
+ const home = (0, import_plans_home.plansHome)(projectRoot);
112
+ for (const f of home ? itemFolders(projectRoot) : []) {
113
+ for (const r of readFolder(home, f)) {
114
+ if (r.writer === me) continue;
115
+ const v = (0, import_trust.verifyTaskRecord)(r, signedOf(r), ctx);
116
+ if (v.verified) verified++;
117
+ else reasons.set(v.why, (reasons.get(v.why) ?? 0) + 1);
118
+ }
119
+ }
120
+ const list = [...reasons].map(([why, n]) => ({ why, records: n })).sort((a, b) => b.records - a.records);
121
+ return { verified, unverified: list.reduce((t, r) => t + r.records, 0), reasons: list };
122
+ }
123
+ function getSharedTaskState(projectRoot) {
124
+ const row = rowOf(projectRoot);
125
+ const enabled = row?.enabled === true;
126
+ const { records, writers } = counts(projectRoot);
127
+ const name = writerName(projectRoot);
128
+ const home = (0, import_plans_home.plansHome)(projectRoot);
129
+ if (home) (0, import_trust.readKeyIntroductions)(home, writerId());
130
+ const found = records ? ` ${records} record${records === 1 ? "" : "s"} from ${writers} ${writers === 1 ? "device" : "devices"} are in the project's files.` : "";
131
+ return {
132
+ project: projectRoot,
133
+ enabled,
134
+ changedAt: row?.changedAt ?? null,
135
+ changedBy: row?.changedBy ?? null,
136
+ writer: writerId(),
137
+ name,
138
+ records,
139
+ writers,
140
+ says: enabled ? `On: each change to a task's state here is written to ${RECORDS_DIR} as ${name}, and teammates' records are read.${found}` : `Off. Task state stays on this device; teammates who pull see the plan, not who is doing what.${found}`,
141
+ signing: (0, import_trust.signingWay)(projectRoot),
142
+ // Introduced where the records go: the project, or its linked plans folder.
143
+ keys: (0, import_trust.listTeammateKeys)(home && home !== projectRoot ? [projectRoot, home] : [projectRoot]),
144
+ checked: checkedCounts(projectRoot),
145
+ materialReads: materialReadsStatus(projectRoot, enabled, home),
146
+ runs: runsStatus(projectRoot, enabled, home)
147
+ };
148
+ }
149
+ function runsStatus(projectRoot, sharing, home) {
150
+ const teammates = (0, import_teammate_runs.listTeammateRuns)(projectRoot).map((r) => ({
151
+ who: r.who,
152
+ verified: r.verified,
153
+ at: r.at,
154
+ commit: r.commit,
155
+ tests: r.totals.tests,
156
+ failing: r.totals.failed + r.totals.errors
157
+ }));
158
+ const from = teammates.length ? ` Runs from ${[...new Set(teammates.map((t) => t.who))].join(", ")} are here.` : "";
159
+ return {
160
+ mine: (0, import_test_runs.myRunCount)(home, writerId()),
161
+ teammates,
162
+ says: sharing ? `On with task state: each test run reported here is written to ${import_test_runs.RUNS_DIR}, and teammates' runs ground your files by the commit they ran on.${from}` : "Shared with task state: turn that on first."
163
+ };
164
+ }
165
+ (0, import_test_results.setReportListener)((run) => {
166
+ if (!isSharingTaskState(run.projectRoot)) return;
167
+ const home = (0, import_plans_home.plansHome)(run.projectRoot);
168
+ if (!home) return;
169
+ (0, import_test_runs.writeRunRecord)({ projectRoot: run.projectRoot, home, me: writerId(), name: writerName(run.projectRoot) }, run);
170
+ });
171
+ (0, import_check_runs2.setCheckRunListener)((run) => {
172
+ if (!isSharingTaskState(run.projectRoot)) return;
173
+ const home = (0, import_plans_home.plansHome)(run.projectRoot);
174
+ if (!home) return;
175
+ (0, import_check_runs.writeCheckRunRecord)({ projectRoot: run.projectRoot, home, me: writerId(), name: writerName(run.projectRoot) }, run);
176
+ });
177
+ function materialReadsStatus(projectRoot, sharing, home) {
178
+ const choice = (0, import_material_reads.materialReadsChoice)(projectRoot, sharing);
179
+ const n = (0, import_material_reads.readCounts)(projectRoot, home, writerId());
180
+ const people = n.people.length ? n.people.join(", ") : null;
181
+ const says = !sharing ? "Shared with task state: turn that on first." : !choice.enabled ? "Off: which version of each material your tasks read stays on this device, and teammates' reads are not used." : `On: which version of each material your tasks read is written to ${import_material_reads.READS_DIR}, and teammates' reads are compared with yours.${people ? ` Reads from ${people} are here.` : ""}`;
182
+ return { ...choice, ...n, says };
183
+ }
184
+ function isSharingMaterialReads(projectRoot) {
185
+ return (0, import_material_reads.materialReadsChoice)(projectRoot, isSharingTaskState(projectRoot)).enabled;
186
+ }
187
+ function setSharedMaterialReads(projectRoot, enabled, by) {
188
+ (0, import_material_reads.setMaterialReadsChoice)(projectRoot, enabled, by);
189
+ if (!enabled) (0, import_material_reads.forgetTeammateReads)(projectRoot);
190
+ else {
191
+ const home = (0, import_plans_home.plansHome)(projectRoot);
192
+ if (home && isSharingTaskState(projectRoot)) (0, import_material_reads.readTeammateReads)(projectRoot, home, writerId());
193
+ }
194
+ splitsChanged(projectRoot);
195
+ return getSharedTaskState(projectRoot);
196
+ }
197
+ function shareMaterialRead(itemUid, attachmentUid, by) {
198
+ const item = (0, import_plan_item_service.getItem)(itemUid);
199
+ if (!item) return null;
200
+ const root = sharingRootOf(item.planUid);
201
+ if (!root || !isSharingMaterialReads(root)) return null;
202
+ const home = (0, import_plans_home.plansHome)(root);
203
+ if (!home) return null;
204
+ const att = (0, import_database.getDb)().exec("SELECT value, sha256, kind FROM attachments WHERE uid = ?", [attachmentUid])[0]?.values[0];
205
+ if (!att || String(att[2]) !== "file_ref") return null;
206
+ try {
207
+ return (0, import_material_reads.writeReadRecord)(
208
+ { projectRoot: root, home, me: writerId(), name: writerName(root) },
209
+ { plan: item.planUid, item: item.uid, by, material: String(att[0]), attachment: attachmentUid, sha256: att[1] == null ? null : String(att[1]) }
210
+ );
211
+ } catch (err) {
212
+ console.warn("[TaskRecords] could not write a material-read record:", err.message);
213
+ return null;
214
+ }
215
+ }
216
+ function setSharedTaskState(projectRoot, enabled, by) {
217
+ (0, import_database.getDb)().run(
218
+ `INSERT INTO shared_task_state (project_root, enabled, changed_at, changed_by) VALUES (?, ?, ?, ?)
219
+ ON CONFLICT(project_root) DO UPDATE SET enabled = excluded.enabled, changed_at = excluded.changed_at, changed_by = excluded.changed_by`,
220
+ [projectRoot, enabled ? 1 : 0, Date.now(), by]
221
+ );
222
+ (0, import_persistence.markDirty)();
223
+ if (enabled) {
224
+ void startRecordWatcher(projectRoot);
225
+ readProjectRecords(projectRoot);
226
+ } else {
227
+ stopRecordWatcher(projectRoot);
228
+ if ((0, import_material_reads.forgetTeammateReads)(projectRoot)) splitsChanged(projectRoot);
229
+ if ((0, import_teammate_runs.forgetTeammateRuns)({ projectRoot })) runsChanged(projectRoot);
230
+ if ((0, import_check_runs2.forgetTeammateCheckRuns)({ projectRoot })) checkRunsChanged(projectRoot);
231
+ }
232
+ return getSharedTaskState(projectRoot);
233
+ }
234
+ function itemFolders(projectRoot, onlyPlan) {
235
+ const home = (0, import_plans_home.plansHome)(projectRoot);
236
+ if (!home) return [];
237
+ const root = import_node_path.default.join(home, RECORDS_DIR);
238
+ const out = [];
239
+ const dirs = (d) => {
240
+ try {
241
+ return import_node_fs.default.readdirSync(d, { withFileTypes: true }).filter((e) => e.isDirectory() && (0, import_record.isRecordId)(e.name)).map((e) => e.name);
242
+ } catch {
243
+ return [];
244
+ }
245
+ };
246
+ for (const plan of dirs(root)) {
247
+ if (onlyPlan && plan !== onlyPlan) continue;
248
+ for (const item of dirs(import_node_path.default.join(root, plan))) {
249
+ const dir = import_node_path.default.join(root, plan, item);
250
+ let files = [];
251
+ try {
252
+ files = import_node_fs.default.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".yaml") && !e.name.startsWith(".")).map((e) => e.name).slice(0, MAX_RECORDS_PER_ITEM);
253
+ } catch {
254
+ }
255
+ out.push({ plan, item, dir, files });
256
+ }
257
+ }
258
+ return out;
259
+ }
260
+ const signedParts = /* @__PURE__ */ new WeakMap();
261
+ const UNSIGNED = { bytes: "", signature: null };
262
+ const signedOf = (r) => signedParts.get(r) ?? UNSIGNED;
263
+ function readOne(home, f, name) {
264
+ if ((0, import_cloud_files.isPlaceholder)(import_node_path.default.join(f.dir, name))) return null;
265
+ let text;
266
+ try {
267
+ text = (0, import_confined_fs.readTextWithin)(home, import_node_path.default.join(f.dir, name), "task record");
268
+ } catch {
269
+ return null;
270
+ }
271
+ const parsed = (0, import_record.parseRecord)(text, { plan: f.plan, item: f.item });
272
+ if (!("record" in parsed)) return null;
273
+ signedParts.set(parsed.record, parsed.signed);
274
+ return parsed.record;
275
+ }
276
+ function readFolder(home, f) {
277
+ const out = [];
278
+ for (const name of f.files) {
279
+ const r = readOne(home, f, name);
280
+ if (r) out.push(r);
281
+ }
282
+ return out;
283
+ }
284
+ function itemFolder(projectRoot, home, planUid, itemUid) {
285
+ const dir = import_node_path.default.join(home, RECORDS_DIR, planUid, itemUid);
286
+ return itemFolders(projectRoot, planUid).find((f) => f.item === itemUid) ?? { plan: planUid, item: itemUid, dir, files: [] };
287
+ }
288
+ let splitListener;
289
+ let runsListener;
290
+ function setRunsChangedListener(fn) {
291
+ runsListener = fn;
292
+ }
293
+ function runsChanged(projectRoot) {
294
+ try {
295
+ runsListener?.(projectRoot);
296
+ } catch {
297
+ }
298
+ }
299
+ let checkRunsListener;
300
+ function setCheckRunsChangedListener(fn) {
301
+ checkRunsListener = fn;
302
+ }
303
+ function checkRunsChanged(projectRoot) {
304
+ try {
305
+ checkRunsListener?.(projectRoot);
306
+ } catch {
307
+ }
308
+ }
309
+ function setSplitChangedListener(fn) {
310
+ splitListener = fn;
311
+ }
312
+ function splitsChanged(projectRoot) {
313
+ try {
314
+ splitListener?.(projectRoot);
315
+ } catch (err) {
316
+ console.warn("[TaskRecords] signal refresh failed:", err);
317
+ }
318
+ }
319
+ function stateOf(item) {
320
+ return {
321
+ status: item.status ?? null,
322
+ assignee: item.assignee ?? null,
323
+ assigneeType: item.assigneeType ?? null,
324
+ progressPercent: item.progressPercent ?? null,
325
+ blockedReason: item.blockedReason ?? null
326
+ };
327
+ }
328
+ function sharingRootOf(planUid) {
329
+ const plan = (0, import_plan_service.getPlan)(planUid);
330
+ if (!plan?.projectPath || !import_node_path.default.isAbsolute(plan.projectPath)) return null;
331
+ if (!isSharingTaskState(plan.projectPath)) return null;
332
+ if (!(0, import_plan_file_service.getLinkedPlanDir)(planUid, plan.projectPath)) return null;
333
+ return plan.projectPath;
334
+ }
335
+ function writeRecordFor(item, by, now = Date.now()) {
336
+ if (!(0, import_record.isRecordId)(item.planUid) || !(0, import_record.isRecordId)(item.uid)) return null;
337
+ const root = sharingRootOf(item.planUid);
338
+ if (!root) return null;
339
+ const home = (0, import_plans_home.plansHome)(root);
340
+ if (!home) return null;
341
+ const me = writerId();
342
+ const folder = itemFolder(root, home, item.planUid, item.uid);
343
+ const existing = readFolder(home, folder);
344
+ const mine = existing.filter((r) => r.writer === me);
345
+ let counter = Math.max(0, ...mine.map((r) => r.counter), ...folder.files.map((f) => f.startsWith(`${me}-`) ? parseInt(f.slice(me.length + 1), 10) || 0 : 0)) + 1;
346
+ while (import_node_fs.default.existsSync(import_node_path.default.join(folder.dir, (0, import_record.recordFileName)(me, counter)))) counter++;
347
+ const others = (0, import_record.seenOf)(existing.filter((r) => r.writer !== me));
348
+ const record = {
349
+ writer: me,
350
+ name: writerName(root),
351
+ counter,
352
+ seen: others,
353
+ at: now,
354
+ plan: item.planUid,
355
+ item: item.uid,
356
+ by,
357
+ state: stateOf(item)
358
+ };
359
+ const signature = (0, import_trust.signRecord)(root, home, record, (0, import_record.recordBytes)(record));
360
+ const file = (0, import_confined_fs.writeFileWithin)(home, import_node_path.default.join(folder.dir, (0, import_record.recordFileName)(me, counter)), (0, import_record.serializeRecord)(record, signature), "task record");
361
+ const ended = !!(0, import_heads.headOf)(item.uid)?.split;
362
+ (0, import_heads.setHead)(item.uid, me, counter, null);
363
+ if (ended) splitsChanged(root);
364
+ return file;
365
+ }
366
+ function keepMyState(itemUid, by) {
367
+ const item = (0, import_plan_item_service.getItem)(itemUid);
368
+ if (!item || item.kind !== "action") return { ok: false, status: 404, error: "no such task" };
369
+ if (!(0, import_heads.splitOf)(itemUid)) return { ok: false, status: 409, error: "Nobody set this task two ways at once, so there is nothing to settle." };
370
+ const file = writeRecordFor(item, by);
371
+ if (!file) return { ok: false, status: 409, error: "This project does not share task state, so no record can be written." };
372
+ return { ok: true, file: import_node_path.default.basename(file) };
373
+ }
374
+ function recordCheck(r, v) {
375
+ const person = r.by.authorType === "human" || r.by.authorType === "unverified" || r.by.author === r.name;
376
+ const as = (who) => person ? who : `${r.by.author} for ${who}`;
377
+ return v.verified ? { verified: true, claimed: as(r.name), how: v.how, who: v.who, author: as(v.who) } : { verified: false, claimed: as(r.name), why: v.why };
378
+ }
379
+ function recordAuthor(check) {
380
+ return { author: check.verified && check.author ? check.author : check.claimed, authorType: "record" };
381
+ }
382
+ const claimOf = (r, forged = false) => ({ name: r.name, status: r.state.status, at: r.at, ...forged ? { forged: true } : {} });
383
+ function readProjectRecords(projectRoot, onlyPlan, onApplied) {
384
+ const result = { read: 0, applied: [], split: [] };
385
+ if (!isSharingTaskState(projectRoot)) return result;
386
+ const me = writerId();
387
+ const home = (0, import_plans_home.plansHome)(projectRoot);
388
+ if (!home) return result;
389
+ (0, import_trust.readKeyIntroductions)(home, me);
390
+ let ctx = null;
391
+ let changed = false;
392
+ for (const f of itemFolders(projectRoot, onlyPlan)) {
393
+ const item = (0, import_plan_item_service.getItem)(f.item);
394
+ if (!item || item.planUid !== f.plan || item.kind !== "action") continue;
395
+ if ((0, import_plan_service.getPlan)(f.plan)?.projectPath !== projectRoot) continue;
396
+ const { records, clashing } = (0, import_record.distinctRecords)(readFolder(home, f));
397
+ result.read += records.length;
398
+ const read = (0, import_record.readItem)(records);
399
+ const known = (0, import_heads.headOf)(item.uid);
400
+ const claims = clashing.length ? clashing.flatMap((c) => [claimOf(records.find((r) => r.writer === c.writer && r.counter === c.counter), true), claimOf(c, true)]) : read.kind === "split" ? read.heads.map((h) => claimOf(h)) : null;
401
+ if (claims) {
402
+ const split = JSON.stringify(claims);
403
+ if (known?.split !== split) {
404
+ (0, import_heads.setHead)(item.uid, known?.writer ?? "", known?.counter ?? 0, split);
405
+ changed = true;
406
+ }
407
+ result.split.push(item.uid);
408
+ continue;
409
+ }
410
+ if (read.kind !== "settled") continue;
411
+ const { head } = read;
412
+ if (known && known.writer === head.writer && known.counter === head.counter && !known.split) continue;
413
+ if (known?.split) changed = true;
414
+ if (head.writer === me) {
415
+ (0, import_heads.setHead)(item.uid, head.writer, head.counter, null);
416
+ continue;
417
+ }
418
+ ctx ??= (0, import_trust.checkContext)(projectRoot);
419
+ const check = recordCheck(head, (0, import_trust.verifyTaskRecord)(head, signedOf(head), ctx));
420
+ (0, import_heads.setHead)(item.uid, head.writer, head.counter, null, check);
421
+ const s = head.state;
422
+ const applied = (0, import_plan_item_service.applyRecordedState)(item.uid, {
423
+ status: s.status ?? "pending",
424
+ assignee: s.assignee,
425
+ assigneeType: s.assigneeType,
426
+ progressPercent: s.progressPercent,
427
+ blockedReason: s.blockedReason
428
+ }, recordAuthor(check));
429
+ if (applied) {
430
+ result.applied.push(item.uid);
431
+ onApplied?.(applied);
432
+ }
433
+ }
434
+ if (isSharingMaterialReads(projectRoot) && (0, import_material_reads.readTeammateReads)(projectRoot, home, me, onlyPlan) > 0) changed = true;
435
+ if ((0, import_test_runs.readTeammateRuns)(projectRoot, home, me) > 0) runsChanged(projectRoot);
436
+ if ((0, import_check_runs.readTeammateCheckRuns)(projectRoot, home, me) > 0) checkRunsChanged(projectRoot);
437
+ if (changed) splitsChanged(projectRoot);
438
+ return result;
439
+ }
440
+ function trustTeammateKey(writer, fingerprint, trust, by) {
441
+ const key = (0, import_trust.decideKey)(writer, fingerprint, trust, by);
442
+ if (!key) return null;
443
+ (0, import_material_reads.forgetReadsBy)(writer);
444
+ (0, import_teammate_runs.forgetTeammateRuns)({ writer });
445
+ (0, import_check_runs2.forgetTeammateCheckRuns)({ writer });
446
+ const me = writerId();
447
+ for (const v of (0, import_database.getDb)().exec("SELECT project_root FROM shared_task_state WHERE enabled = 1")[0]?.values ?? []) {
448
+ const root = String(v[0]);
449
+ const home = (0, import_plans_home.plansHome)(root);
450
+ if (home && isSharingMaterialReads(root) && (0, import_material_reads.readTeammateReads)(root, home, me) > 0) splitsChanged(root);
451
+ if (home && (0, import_test_runs.readTeammateRuns)(root, home, me) > 0) runsChanged(root);
452
+ if (home && (0, import_check_runs.readTeammateCheckRuns)(root, home, me) > 0) checkRunsChanged(root);
453
+ }
454
+ const rechecked = [];
455
+ for (const h of (0, import_heads.headsBy)(writer)) {
456
+ const item = (0, import_plan_item_service.getItem)(h.itemUid);
457
+ const root = item ? (0, import_plan_service.getPlan)(item.planUid)?.projectPath : null;
458
+ const home = root ? (0, import_plans_home.plansHome)(root) : null;
459
+ if (!item || !root || !home || !(0, import_record.isRecordId)(item.planUid) || !(0, import_record.isRecordId)(item.uid)) continue;
460
+ const folder = { plan: item.planUid, item: item.uid, dir: import_node_path.default.join(home, RECORDS_DIR, item.planUid, item.uid) };
461
+ const r = readOne(home, folder, (0, import_record.recordFileName)(writer, h.counter));
462
+ if (!r) continue;
463
+ (0, import_heads.setHeadCheck)(item.uid, recordCheck(r, (0, import_trust.verifyTaskRecord)(r, signedOf(r), (0, import_trust.checkContext)(root))));
464
+ rechecked.push(item.uid);
465
+ }
466
+ return { key, rechecked };
467
+ }
468
+ const watchers = /* @__PURE__ */ new Map();
469
+ const watcherReady = /* @__PURE__ */ new Map();
470
+ let appliedListener;
471
+ function setRecordAppliedListener(fn) {
472
+ appliedListener = fn;
473
+ }
474
+ function readAndTell(projectRoot, onlyPlan) {
475
+ return readProjectRecords(projectRoot, onlyPlan, appliedListener);
476
+ }
477
+ function startRecordWatcher(projectRoot) {
478
+ if (watchers.has(projectRoot)) return watcherReady.get(projectRoot) ?? Promise.resolve();
479
+ if (!isSharingTaskState(projectRoot)) return Promise.resolve();
480
+ const home = (0, import_plans_home.plansHome)(projectRoot);
481
+ if (!home) return Promise.resolve();
482
+ const dir = import_node_path.default.join(home, RECORDS_DIR);
483
+ const reads = import_node_path.default.join(home, import_material_reads.READS_DIR);
484
+ const runs = import_node_path.default.join(home, import_test_runs.RUNS_DIR);
485
+ try {
486
+ for (const d of [dir, reads, runs]) import_node_fs.default.mkdirSync(d, { recursive: true });
487
+ } catch {
488
+ return Promise.resolve();
489
+ }
490
+ let timer = null;
491
+ const watcher = import_chokidar.default.watch([dir, reads, runs], {
492
+ ignoreInitial: true,
493
+ persistent: true,
494
+ depth: 3,
495
+ followSymlinks: false,
496
+ awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 50 }
497
+ });
498
+ watcher.on("all", (event, file) => {
499
+ if (event !== "add" && event !== "change" || !file?.endsWith(".yaml")) return;
500
+ if (timer) clearTimeout(timer);
501
+ timer = setTimeout(() => {
502
+ timer = null;
503
+ try {
504
+ readAndTell(projectRoot);
505
+ } catch (err) {
506
+ console.warn("[TaskRecords] read failed:", err);
507
+ }
508
+ }, 150);
509
+ });
510
+ watcher.on("error", (err) => console.warn("[TaskRecords] watcher error:", err));
511
+ watchers.set(projectRoot, watcher);
512
+ const ready = new Promise((resolve) => {
513
+ watcher.once("ready", () => resolve());
514
+ setTimeout(resolve, 5e3).unref?.();
515
+ });
516
+ watcherReady.set(projectRoot, ready);
517
+ return ready;
518
+ }
519
+ function stopRecordWatcher(projectRoot) {
520
+ const w = watchers.get(projectRoot);
521
+ if (!w) return;
522
+ watchers.delete(projectRoot);
523
+ watcherReady.delete(projectRoot);
524
+ void w.close();
525
+ }
526
+ // Annotate the CommonJS export names for ESM import in node:
527
+ 0 && (module.exports = {
528
+ RECORDS_DIR,
529
+ getSharedTaskState,
530
+ isSharingMaterialReads,
531
+ isSharingTaskState,
532
+ keepMyState,
533
+ readAndTell,
534
+ readProjectRecords,
535
+ setCheckRunsChangedListener,
536
+ setRecordAppliedListener,
537
+ setRunsChangedListener,
538
+ setSharedMaterialReads,
539
+ setSharedTaskState,
540
+ setSplitChangedListener,
541
+ shareMaterialRead,
542
+ startRecordWatcher,
543
+ stopRecordWatcher,
544
+ trustTeammateKey,
545
+ writeRecordFor,
546
+ writerId,
547
+ writerName
548
+ });