cloving 1.0.1 → 1.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 (309) hide show
  1. package/README.md +251 -20
  2. package/assets/watch-fonts/fira-code-OFL.md +93 -0
  3. package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
  4. package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
  5. package/assets/watch-fonts/heebo-OFL.md +93 -0
  6. package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
  7. package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
  8. package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
  9. package/assets/watch-fonts/manifest.json +112 -0
  10. package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
  11. package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
  12. package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
  13. package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
  14. package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
  15. package/dist/src/authority/commands.d.ts +1 -0
  16. package/dist/src/authority/commands.js +33 -4
  17. package/dist/src/authority/dispatch-decision.d.ts +1 -0
  18. package/dist/src/authority/dispatch-decision.js +7 -4
  19. package/dist/src/authority/events.js +2 -2
  20. package/dist/src/authority/handoff-chain.d.ts +24 -0
  21. package/dist/src/authority/handoff-chain.js +46 -0
  22. package/dist/src/authority/reconciliation.d.ts +3 -0
  23. package/dist/src/authority/reconciliation.js +21 -5
  24. package/dist/src/authority/transitions.d.ts +1 -1
  25. package/dist/src/authority/transitions.js +5 -0
  26. package/dist/src/broker/actor/authority-queries.d.ts +4 -0
  27. package/dist/src/broker/actor/authority-queries.js +51 -2
  28. package/dist/src/broker/actor/authority-session.d.ts +2 -0
  29. package/dist/src/broker/actor/authority-session.js +3 -4
  30. package/dist/src/broker/actor/delivery-intents.d.ts +1 -0
  31. package/dist/src/broker/actor/effect-delivery.js +9 -0
  32. package/dist/src/broker/authority-admission.js +13 -5
  33. package/dist/src/chats/analysis-batches.d.ts +42 -0
  34. package/dist/src/chats/analysis-batches.js +97 -0
  35. package/dist/src/chats/analysis-checkpoint.d.ts +29 -0
  36. package/dist/src/chats/analysis-checkpoint.js +31 -0
  37. package/dist/src/chats/analysis-contract.d.ts +80 -0
  38. package/dist/src/chats/analysis-contract.js +16 -0
  39. package/dist/src/chats/analysis-data.d.ts +3 -0
  40. package/dist/src/chats/analysis-data.js +85 -0
  41. package/dist/src/chats/analysis-input.d.ts +18 -0
  42. package/dist/src/chats/analysis-input.js +97 -0
  43. package/dist/src/chats/analysis-links.d.ts +2 -0
  44. package/dist/src/chats/analysis-links.js +25 -0
  45. package/dist/src/chats/analysis-merge.d.ts +16 -0
  46. package/dist/src/chats/analysis-merge.js +134 -0
  47. package/dist/src/chats/analysis-prompt.d.ts +18 -0
  48. package/dist/src/chats/analysis-prompt.js +42 -0
  49. package/dist/src/chats/analysis-proposal.d.ts +4 -0
  50. package/dist/src/chats/analysis-proposal.js +41 -0
  51. package/dist/src/chats/analysis-provenance.d.ts +4 -0
  52. package/dist/src/chats/analysis-provenance.js +99 -0
  53. package/dist/src/chats/analysis-shape.d.ts +4 -0
  54. package/dist/src/chats/analysis-shape.js +235 -0
  55. package/dist/src/chats/analysis.d.ts +3 -0
  56. package/dist/src/chats/analysis.js +42 -0
  57. package/dist/src/chats/corpus-input.d.ts +5 -0
  58. package/dist/src/chats/corpus-input.js +288 -0
  59. package/dist/src/chats/destination.js +3 -1
  60. package/dist/src/chats/import.d.ts +8 -6
  61. package/dist/src/chats/import.js +195 -23
  62. package/dist/src/chats/input-file.d.ts +3 -0
  63. package/dist/src/chats/input-file.js +32 -0
  64. package/dist/src/chats/normalize.d.ts +11 -2
  65. package/dist/src/chats/normalize.js +18 -2
  66. package/dist/src/chats/previous-import.d.ts +5 -0
  67. package/dist/src/chats/previous-import.js +34 -0
  68. package/dist/src/chats/reader.d.ts +7 -1
  69. package/dist/src/chats/reader.js +46 -15
  70. package/dist/src/chats/redact-import.d.ts +14 -0
  71. package/dist/src/chats/redact-import.js +141 -0
  72. package/dist/src/chats/redaction.d.ts +41 -0
  73. package/dist/src/chats/redaction.js +161 -0
  74. package/dist/src/chats/reference-mapping.d.ts +16 -0
  75. package/dist/src/chats/reference-mapping.js +153 -0
  76. package/dist/src/chats/revision-input.d.ts +3 -0
  77. package/dist/src/chats/revision-input.js +180 -0
  78. package/dist/src/chats/revision.d.ts +48 -0
  79. package/dist/src/chats/revision.js +94 -0
  80. package/dist/src/chats/selection.d.ts +25 -0
  81. package/dist/src/chats/selection.js +109 -0
  82. package/dist/src/chats/source.d.ts +23 -0
  83. package/dist/src/chats/source.js +135 -0
  84. package/dist/src/chats/structure.d.ts +57 -0
  85. package/dist/src/chats/structure.js +216 -0
  86. package/dist/src/chats/workflow-generation-projection.d.ts +8 -0
  87. package/dist/src/chats/workflow-generation-projection.js +75 -0
  88. package/dist/src/chats/workflow-generation-source.d.ts +25 -0
  89. package/dist/src/chats/workflow-generation-source.js +124 -0
  90. package/dist/src/chats/workflow-generation-text.d.ts +23 -0
  91. package/dist/src/chats/workflow-generation-text.js +74 -0
  92. package/dist/src/chats/workflow-generation.d.ts +69 -0
  93. package/dist/src/chats/workflow-generation.js +142 -0
  94. package/dist/src/cli/arguments.d.ts +8 -0
  95. package/dist/src/cli/arguments.js +94 -13
  96. package/dist/src/cli/client.d.ts +1 -0
  97. package/dist/src/cli/client.js +38 -1
  98. package/dist/src/cli/commands.d.ts +3 -0
  99. package/dist/src/cli/commands.js +29 -11
  100. package/dist/src/cli/main.d.ts +2 -1
  101. package/dist/src/cli/main.js +61 -14
  102. package/dist/src/cli/render.d.ts +3 -0
  103. package/dist/src/cli/render.js +122 -7
  104. package/dist/src/cli/usage-render.d.ts +3 -0
  105. package/dist/src/cli/usage-render.js +28 -0
  106. package/dist/src/cli/usage.d.ts +3 -2
  107. package/dist/src/cli/usage.js +42 -7
  108. package/dist/src/cli/watch-actions.d.ts +10 -0
  109. package/dist/src/cli/watch-actions.js +58 -0
  110. package/dist/src/cli/watch-board-view.d.ts +44 -1
  111. package/dist/src/cli/watch-board-view.js +137 -18
  112. package/dist/src/cli/watch-board.d.ts +7 -1
  113. package/dist/src/cli/watch-board.js +48 -11
  114. package/dist/src/cli/watch-card-client.d.ts +1 -0
  115. package/dist/src/cli/watch-card-client.js +44 -0
  116. package/dist/src/cli/watch-card-forms.d.ts +2 -0
  117. package/dist/src/cli/watch-card-forms.js +33 -0
  118. package/dist/src/cli/watch-card-reply.d.ts +5 -0
  119. package/dist/src/cli/watch-card-reply.js +34 -0
  120. package/dist/src/cli/watch-card-view.d.ts +40 -0
  121. package/dist/src/cli/watch-card-view.js +86 -0
  122. package/dist/src/cli/watch-client.d.ts +1 -0
  123. package/dist/src/cli/watch-client.js +122 -0
  124. package/dist/src/cli/watch-model.d.ts +10 -4
  125. package/dist/src/cli/watch-model.js +61 -67
  126. package/dist/src/cli/watch-page.d.ts +1 -1
  127. package/dist/src/cli/watch-page.js +89 -86
  128. package/dist/src/cli/watch-phases.js +3 -3
  129. package/dist/src/cli/watch-pr-board.d.ts +3 -0
  130. package/dist/src/cli/watch-pr-board.js +26 -0
  131. package/dist/src/cli/watch-pr-command.d.ts +18 -0
  132. package/dist/src/cli/watch-pr-command.js +74 -0
  133. package/dist/src/cli/watch-pr-identity.d.ts +32 -0
  134. package/dist/src/cli/watch-pr-identity.js +87 -0
  135. package/dist/src/cli/watch-pr-observer.d.ts +20 -0
  136. package/dist/src/cli/watch-pr-observer.js +150 -0
  137. package/dist/src/cli/watch-pr-settings.d.ts +8 -0
  138. package/dist/src/cli/watch-pr-settings.js +47 -0
  139. package/dist/src/cli/watch-pull-request.d.ts +10 -0
  140. package/dist/src/cli/watch-pull-request.js +130 -0
  141. package/dist/src/cli/watch-reads.d.ts +7 -1
  142. package/dist/src/cli/watch-reads.js +44 -18
  143. package/dist/src/cli/watch-render.d.ts +29 -2
  144. package/dist/src/cli/watch-render.js +11 -3
  145. package/dist/src/cli/watch-run-input.d.ts +14 -0
  146. package/dist/src/cli/watch-run-input.js +49 -0
  147. package/dist/src/cli/watch-server.d.ts +3 -0
  148. package/dist/src/cli/watch-server.js +77 -8
  149. package/dist/src/cli/watch-start-view.d.ts +18 -0
  150. package/dist/src/cli/watch-start-view.js +77 -0
  151. package/dist/src/cli/watch-turn.d.ts +1 -0
  152. package/dist/src/cli/watch-turn.js +8 -3
  153. package/dist/src/cli/watch-usage.d.ts +6 -0
  154. package/dist/src/cli/watch-usage.js +65 -0
  155. package/dist/src/cli/watch-view.d.ts +22 -0
  156. package/dist/src/cli/watch-view.js +111 -19
  157. package/dist/src/cli.js +48 -6
  158. package/dist/src/daemon/analysis-launch.d.ts +5 -0
  159. package/dist/src/daemon/analysis-launch.js +81 -0
  160. package/dist/src/daemon/analysis-token.d.ts +6 -0
  161. package/dist/src/daemon/analysis-token.js +88 -0
  162. package/dist/src/daemon/analysis-worker.d.ts +20 -0
  163. package/dist/src/daemon/analysis-worker.js +271 -0
  164. package/dist/src/daemon/chats-batch-binding.d.ts +23 -0
  165. package/dist/src/daemon/chats-batch-binding.js +99 -0
  166. package/dist/src/daemon/chats-capture.d.ts +18 -0
  167. package/dist/src/daemon/chats-capture.js +194 -0
  168. package/dist/src/daemon/chats-checkpoints.d.ts +41 -0
  169. package/dist/src/daemon/chats-checkpoints.js +186 -0
  170. package/dist/src/daemon/chats-files.d.ts +42 -0
  171. package/dist/src/daemon/chats-files.js +252 -0
  172. package/dist/src/daemon/chats-follow-up.d.ts +38 -0
  173. package/dist/src/daemon/chats-follow-up.js +180 -0
  174. package/dist/src/daemon/chats-question.d.ts +15 -0
  175. package/dist/src/daemon/chats-question.js +93 -0
  176. package/dist/src/daemon/chats-worker.d.ts +13 -0
  177. package/dist/src/daemon/chats-worker.js +201 -0
  178. package/dist/src/daemon/claude-turn.d.ts +11 -0
  179. package/dist/src/daemon/claude-turn.js +96 -15
  180. package/dist/src/daemon/claude-worker.d.ts +2 -1
  181. package/dist/src/daemon/claude-worker.js +92 -45
  182. package/dist/src/daemon/codex-stream.js +16 -0
  183. package/dist/src/daemon/daemon.d.ts +8 -1
  184. package/dist/src/daemon/daemon.js +51 -14
  185. package/dist/src/daemon/delivery-router.js +6 -0
  186. package/dist/src/daemon/github-calls.d.ts +4 -0
  187. package/dist/src/daemon/github-calls.js +16 -7
  188. package/dist/src/daemon/github-ci.d.ts +6 -0
  189. package/dist/src/daemon/github-ci.js +170 -0
  190. package/dist/src/daemon/github-merge-call.d.ts +14 -0
  191. package/dist/src/daemon/github-merge-call.js +73 -0
  192. package/dist/src/daemon/github-merge.d.ts +3 -5
  193. package/dist/src/daemon/github-merge.js +52 -95
  194. package/dist/src/daemon/github-methods.d.ts +28 -0
  195. package/dist/src/daemon/github-methods.js +84 -16
  196. package/dist/src/daemon/github-operation.d.ts +2 -0
  197. package/dist/src/daemon/github-retry.d.ts +6 -0
  198. package/dist/src/daemon/github-retry.js +49 -0
  199. package/dist/src/daemon/github-ticket-status.d.ts +3 -0
  200. package/dist/src/daemon/github-ticket-status.js +294 -0
  201. package/dist/src/daemon/github-worker.js +2 -1
  202. package/dist/src/daemon/handoff-worker.d.ts +10 -0
  203. package/dist/src/daemon/handoff-worker.js +232 -0
  204. package/dist/src/daemon/issue-queue.d.ts +2 -0
  205. package/dist/src/daemon/issue-queue.js +186 -43
  206. package/dist/src/daemon/notify-journal.d.ts +18 -0
  207. package/dist/src/daemon/notify-journal.js +108 -0
  208. package/dist/src/daemon/notify-message.js +2 -1
  209. package/dist/src/daemon/notify.js +176 -37
  210. package/dist/src/daemon/operation-journal.d.ts +1 -0
  211. package/dist/src/daemon/operation-journal.js +4 -2
  212. package/dist/src/daemon/retrying-turn.d.ts +12 -0
  213. package/dist/src/daemon/retrying-turn.js +231 -0
  214. package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
  215. package/dist/src/daemon/ticket-dependency-waits.js +60 -0
  216. package/dist/src/daemon/ticket-registration.d.ts +8 -4
  217. package/dist/src/daemon/ticket-registration.js +76 -22
  218. package/dist/src/daemon/ticket-source.d.ts +4 -1
  219. package/dist/src/daemon/ticket-source.js +8 -2
  220. package/dist/src/decision-visibility.d.ts +2 -0
  221. package/dist/src/decision-visibility.js +10 -0
  222. package/dist/src/execution-pin.d.ts +4 -0
  223. package/dist/src/execution-pin.js +23 -2
  224. package/dist/src/host/start-delivery.d.ts +2 -1
  225. package/dist/src/host/start-delivery.js +1 -1
  226. package/dist/src/host/step-bridge-host.d.ts +1 -0
  227. package/dist/src/host/step-bridge-host.js +16 -0
  228. package/dist/src/host/world-reconciliation.d.ts +3 -0
  229. package/dist/src/host/world-reconciliation.js +9 -0
  230. package/dist/src/host/world-runs.js +14 -1
  231. package/dist/src/issue-identity.d.ts +6 -0
  232. package/dist/src/issue-identity.js +23 -0
  233. package/dist/src/service/queue-runs.d.ts +3 -0
  234. package/dist/src/service/queue-runs.js +39 -0
  235. package/dist/src/service/registry.d.ts +8 -2
  236. package/dist/src/service/registry.js +20 -8
  237. package/dist/src/service/replies.d.ts +2 -0
  238. package/dist/src/service/run-handlers.js +54 -30
  239. package/dist/src/service/service.d.ts +3 -0
  240. package/dist/src/service/service.js +3 -1
  241. package/dist/src/service/submission-handler.d.ts +1 -0
  242. package/dist/src/service/submission-handler.js +92 -13
  243. package/dist/src/service/worker-totals.d.ts +3 -0
  244. package/dist/src/service/worker-totals.js +52 -0
  245. package/dist/src/step-bridge.d.ts +9 -0
  246. package/dist/src/steps/handoff.d.ts +2 -0
  247. package/dist/src/steps/handoff.js +13 -0
  248. package/dist/src/ticket-dependencies.d.ts +1 -0
  249. package/dist/src/ticket-dependencies.js +15 -0
  250. package/dist/src/ticket-status.d.ts +8 -0
  251. package/dist/src/ticket-status.js +48 -0
  252. package/dist/src/token-prices.d.ts +21 -0
  253. package/dist/src/token-prices.js +108 -0
  254. package/dist/src/worker-usage.d.ts +31 -0
  255. package/dist/src/worker-usage.js +44 -0
  256. package/dist/src/workflow-admission.d.ts +1 -0
  257. package/dist/src/workflow-candidate.d.ts +29 -0
  258. package/dist/src/workflow-candidate.js +60 -0
  259. package/dist/src/workflow-contracts.d.ts +4 -0
  260. package/dist/src/workflow-contracts.js +32 -5
  261. package/dist/src/workflow-declaration.d.ts +12 -1
  262. package/dist/src/workflow-declaration.js +71 -13
  263. package/dist/src/workflow-discovery.d.ts +18 -0
  264. package/dist/src/workflow-discovery.js +33 -0
  265. package/dist/src/workflow-refusals.d.ts +6 -0
  266. package/dist/src/workflow-refusals.js +39 -0
  267. package/dist/src/workflows.d.ts +3 -1
  268. package/dist/src/workflows.js +2 -0
  269. package/dist/tools/admit-workflow.d.ts +13 -0
  270. package/dist/tools/admit-workflow.js +94 -0
  271. package/dist/tools/self-host-processes.js +7 -2
  272. package/dist/tools/self-host-project.d.ts +17 -0
  273. package/dist/tools/self-host-project.js +177 -0
  274. package/dist/tools/self-host-workflows.d.ts +1 -1
  275. package/dist/tools/self-host-workflows.js +2 -2
  276. package/dist/tools/self-host.js +30 -84
  277. package/dist/tools/self-update-host.d.ts +7 -0
  278. package/dist/tools/self-update-host.js +48 -1
  279. package/dist/tools/self-update.d.ts +1 -0
  280. package/dist/tools/self-update.js +85 -13
  281. package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
  282. package/dist/tools/workflow-bundle-dependencies.js +93 -0
  283. package/dist/tools/workflow-bundles.d.ts +20 -0
  284. package/dist/tools/workflow-bundles.js +173 -0
  285. package/dist/tools/workflow-candidate-counts.d.ts +8 -0
  286. package/dist/tools/workflow-candidate-counts.js +251 -0
  287. package/dist/tools/workflow-candidate-program.d.ts +11 -0
  288. package/dist/tools/workflow-candidate-program.js +78 -0
  289. package/dist/tools/workflow-candidate-source.d.ts +6 -0
  290. package/dist/tools/workflow-candidate-source.js +107 -0
  291. package/dist/tools/workflow-candidate-syntax.d.ts +15 -0
  292. package/dist/tools/workflow-candidate-syntax.js +219 -0
  293. package/dist/tools/workflow-folder-capture.d.ts +17 -0
  294. package/dist/tools/workflow-folder-capture.js +216 -0
  295. package/dist/tools/workflow-folders.d.ts +33 -0
  296. package/dist/tools/workflow-folders.js +150 -0
  297. package/dist/tools/workflow-source-effects.d.ts +10 -0
  298. package/dist/tools/workflow-source-effects.js +213 -0
  299. package/dist/workflows/analyze-chats.d.ts +15 -0
  300. package/dist/workflows/analyze-chats.declaration.json +22 -0
  301. package/dist/workflows/analyze-chats.js +250 -0
  302. package/dist/workflows/develop-prd.js +71 -3
  303. package/dist/workflows/develop-ticket.d.ts +1 -7
  304. package/dist/workflows/develop-ticket.js +47 -141
  305. package/dist/workflows/issue-labels.d.ts +3 -1
  306. package/dist/workflows/issue-labels.js +34 -0
  307. package/dist/workflows/ticket-prompts.d.ts +35 -0
  308. package/dist/workflows/ticket-prompts.js +143 -0
  309. package/package.json +25 -5
@@ -0,0 +1,235 @@
1
+ import { forbiddenAnalysisField } from "./analysis-data.js";
2
+ export function analysisObject(value) {
3
+ return value !== null && typeof value === "object" && !Array.isArray(value);
4
+ }
5
+ function text(value) {
6
+ return typeof value === "string" && value.trim() !== "";
7
+ }
8
+ function label(value, values) {
9
+ return typeof value === "string" && values.includes(value);
10
+ }
11
+ function fields(value, expected) {
12
+ return Object.keys(value).every((key) => expected.includes(key) || forbiddenAnalysisField(key));
13
+ }
14
+ const itemFields = ["id", "description"];
15
+ const claimFields = [
16
+ ...itemFields,
17
+ "kind",
18
+ "sourceRefs",
19
+ "counterevidenceRefs",
20
+ ];
21
+ const kinds = [
22
+ "explicit-human-instruction",
23
+ "observed-repetition",
24
+ "assistant-claim",
25
+ "exception",
26
+ "rejected-approach",
27
+ "uncertain-inference",
28
+ ];
29
+ const activities = [
30
+ "work",
31
+ "routine-repair",
32
+ "accidental-interruption",
33
+ "tool-imposed-confirmation",
34
+ ];
35
+ const decisions = [
36
+ "design-decision",
37
+ "configured-action-approval",
38
+ "factual-input",
39
+ ];
40
+ const collections = [
41
+ "inputs",
42
+ "stages",
43
+ "branches",
44
+ "loops",
45
+ "artifacts",
46
+ "stoppingConditions",
47
+ "gates",
48
+ "nonGates",
49
+ ];
50
+ function references(value) {
51
+ if (!Array.isArray(value))
52
+ return false;
53
+ return value.every((ref) => analysisObject(ref) &&
54
+ fields(ref, ["recordIndex", "sourceId"]) &&
55
+ Number.isSafeInteger(ref["recordIndex"]) &&
56
+ Number(ref["recordIndex"]) >= 0 &&
57
+ text(ref["sourceId"]));
58
+ }
59
+ function missingSources(value) {
60
+ return value === undefined || (Array.isArray(value) && value.length === 0);
61
+ }
62
+ function questionChoices(value) {
63
+ if (!Array.isArray(value) || value.length < 2 || value.length > 4)
64
+ return false;
65
+ const ids = new Set();
66
+ return value.every((choice) => {
67
+ if (!analysisObject(choice) ||
68
+ !fields(choice, itemFields) ||
69
+ !text(choice["id"]) ||
70
+ !text(choice["description"]) ||
71
+ ids.has(choice["id"]))
72
+ return false;
73
+ ids.add(choice["id"]);
74
+ return true;
75
+ });
76
+ }
77
+ function inspectQuestionShape(candidate, codes) {
78
+ if (!Object.hasOwn(candidate, "openQuestion"))
79
+ return true;
80
+ const question = candidate["openQuestion"];
81
+ if (!analysisObject(question)) {
82
+ codes.add("invalid-question");
83
+ return false;
84
+ }
85
+ if (!fields(question, ["claimId", "description", "sourceRefs", "choices"]) ||
86
+ !text(question["claimId"]) ||
87
+ !text(question["description"]) ||
88
+ !questionChoices(question["choices"]))
89
+ codes.add("invalid-question");
90
+ const sources = question["sourceRefs"];
91
+ if (missingSources(sources)) {
92
+ codes.add("missing-source");
93
+ return false;
94
+ }
95
+ if (!references(sources))
96
+ codes.add("invalid-question");
97
+ return !codes.has("invalid-question");
98
+ }
99
+ function inspectClaim(value, codes) {
100
+ if (!label(value["kind"], kinds))
101
+ codes.add("unknown-kind");
102
+ const source = value["sourceRefs"];
103
+ if (missingSources(source))
104
+ codes.add("missing-source");
105
+ else if (!references(source))
106
+ codes.add("invalid-shape");
107
+ if (!references(value["counterevidenceRefs"]))
108
+ codes.add("invalid-shape");
109
+ }
110
+ function inspectLoop(value, codes) {
111
+ const limit = value["maxIterations"];
112
+ if (typeof limit !== "number" || !Number.isSafeInteger(limit) || limit <= 0)
113
+ codes.add("invalid-loop-limit");
114
+ const stageIds = value["stageIds"];
115
+ return (fields(value, [
116
+ ...claimFields,
117
+ "stageIds",
118
+ "maxIterations",
119
+ "exitCondition",
120
+ "exhaustedStoppingConditionId",
121
+ ]) &&
122
+ Array.isArray(stageIds) &&
123
+ stageIds.length > 0 &&
124
+ stageIds.every(text) &&
125
+ new Set(stageIds).size === stageIds.length &&
126
+ text(value["exitCondition"]) &&
127
+ text(value["exhaustedStoppingConditionId"]));
128
+ }
129
+ function claimShape(value, context) {
130
+ const { collection, codes } = context;
131
+ inspectClaim(value, codes);
132
+ switch (collection) {
133
+ case "stages":
134
+ return (fields(value, [...claimFields, "activity"]) &&
135
+ label(value["activity"], activities));
136
+ case "gates":
137
+ if (!label(value["type"], decisions))
138
+ codes.add("unknown-decision-type");
139
+ return (fields(value, [...claimFields, "stageId", "type"]) &&
140
+ text(value["stageId"]));
141
+ case "loops":
142
+ return inspectLoop(value, codes);
143
+ default:
144
+ return false;
145
+ }
146
+ }
147
+ function itemShape(value, context) {
148
+ const { collection } = context;
149
+ if (["stages", "gates", "loops"].includes(collection))
150
+ return claimShape(value, context);
151
+ switch (collection) {
152
+ case "branches":
153
+ return (fields(value, [
154
+ ...itemFields,
155
+ "sourceStageId",
156
+ "condition",
157
+ "targetStageId",
158
+ ]) &&
159
+ ["sourceStageId", "condition", "targetStageId"].every((key) => text(value[key])));
160
+ case "nonGates":
161
+ return (fields(value, [...itemFields, "stageId", "reason"]) &&
162
+ text(value["stageId"]) &&
163
+ label(value["reason"], activities.slice(1)));
164
+ default:
165
+ return fields(value, itemFields);
166
+ }
167
+ }
168
+ function inspectItem(value, context) {
169
+ const { ids, collection, codes } = context;
170
+ if (!analysisObject(value)) {
171
+ codes.add("invalid-shape");
172
+ return;
173
+ }
174
+ const id = value["id"];
175
+ if (!text(id)) {
176
+ codes.add("invalid-shape");
177
+ return;
178
+ }
179
+ if (!text(value["description"]) || ids.has(id))
180
+ codes.add("invalid-shape");
181
+ ids.add(id);
182
+ if (!itemShape(value, { collection, codes }))
183
+ codes.add("invalid-shape");
184
+ }
185
+ function inspectItems(process, codes) {
186
+ const id = process["id"];
187
+ if (!text(id)) {
188
+ codes.add("invalid-shape");
189
+ return;
190
+ }
191
+ const ids = new Set([id]);
192
+ for (const collection of collections) {
193
+ const items = process[collection];
194
+ if (!Array.isArray(items)) {
195
+ codes.add("invalid-shape");
196
+ continue;
197
+ }
198
+ for (const item of items) {
199
+ inspectItem(item, { ids, collection, codes });
200
+ }
201
+ }
202
+ }
203
+ export function inspectAnalysisBatchShape(value, codes) {
204
+ if (!analysisObject(value)) {
205
+ codes.add("invalid-shape");
206
+ return false;
207
+ }
208
+ if (value["schemaVersion"] !== 1)
209
+ codes.add("unknown-version");
210
+ if (!fields(value, ["schemaVersion", "process", "openQuestion"]))
211
+ codes.add("invalid-shape");
212
+ const validQuestion = inspectQuestionShape(value, codes);
213
+ const process = value["process"];
214
+ if (!analysisObject(process)) {
215
+ codes.add("invalid-shape");
216
+ return false;
217
+ }
218
+ if (!fields(process, ["id", "name", "scope", ...collections]) ||
219
+ !["id", "name", "scope"].every((key) => text(process[key])))
220
+ codes.add("invalid-shape");
221
+ inspectItems(process, codes);
222
+ return (validQuestion &&
223
+ !codes.has("invalid-shape") &&
224
+ !codes.has("unknown-version"));
225
+ }
226
+ export function inspectAnalysisShape(value, codes) {
227
+ if (!inspectAnalysisBatchShape(value, codes))
228
+ return false;
229
+ if (value.process.stages.length === 0 ||
230
+ value.process.stoppingConditions.length === 0) {
231
+ codes.add("invalid-shape");
232
+ return false;
233
+ }
234
+ return true;
235
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./analysis-contract.ts";
2
+ import { type AnalysisEvidence, type AnalysisValidation } from "./analysis-contract.ts";
3
+ export declare function validateAnalysis(candidate: unknown, evidence: AnalysisEvidence): AnalysisValidation;
@@ -0,0 +1,42 @@
1
+ export * from "./analysis-contract.js";
2
+ import { analysisCodes, } from "./analysis-contract.js";
3
+ import { inspectAnalysisShape } from "./analysis-shape.js";
4
+ import { inspectAnalysisLinks } from "./analysis-links.js";
5
+ import { inspectAnalysisData } from "./analysis-data.js";
6
+ import { matchingAnalysisEvidence, inspectAnalysisSupport, inspectAnalysisQuestion, } from "./analysis-provenance.js";
7
+ export function validateAnalysis(candidate, evidence) {
8
+ const codes = new Set(inspectAnalysisData(candidate));
9
+ if (codes.has("not-plain-data"))
10
+ return { accepted: false, codes: ["not-plain-data"] };
11
+ if (!inspectAnalysisShape(candidate, codes))
12
+ return {
13
+ accepted: false,
14
+ codes: analysisCodes.filter((code) => codes.has(code)),
15
+ };
16
+ for (const code of inspectAnalysisLinks(candidate.process))
17
+ codes.add(code);
18
+ if (matchingAnalysisEvidence(evidence)) {
19
+ for (const code of inspectAnalysisSupport(candidate.process, evidence))
20
+ codes.add(code);
21
+ for (const code of inspectAnalysisQuestion(candidate, evidence))
22
+ codes.add(code);
23
+ }
24
+ else
25
+ codes.add("invalid-shape");
26
+ if (codes.size > 0)
27
+ return {
28
+ accepted: false,
29
+ codes: analysisCodes.filter((code) => codes.has(code)),
30
+ };
31
+ return {
32
+ accepted: true,
33
+ result: {
34
+ ...candidate,
35
+ limitations: {
36
+ historyCompleteness: "unknown",
37
+ independentObservations: "not-established",
38
+ conflictGroups: evidence.structure.conflictGroups,
39
+ },
40
+ },
41
+ };
42
+ }
@@ -0,0 +1,5 @@
1
+ import { type MessageRecord } from "./normalize.ts";
2
+ export declare function parseCorpusRecord(line: string): MessageRecord;
3
+ export declare function parseCorpus(text: string): readonly MessageRecord[];
4
+ export declare function validateCoverage(text: string, importId: string): void;
5
+ export declare function withinRoot(root: string | undefined, path: unknown): boolean;
@@ -0,0 +1,288 @@
1
+ import { parsePreservedJson } from "./normalize.js";
2
+ function object(value) {
3
+ return value !== null && typeof value === "object" && !Array.isArray(value);
4
+ }
5
+ function keys(value, fields) {
6
+ const { required, optional = [] } = fields;
7
+ return (required.every((key) => Object.hasOwn(value, key)) &&
8
+ Object.keys(value).every((key) => required.includes(key) || optional.includes(key)));
9
+ }
10
+ function natural(value) {
11
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
12
+ }
13
+ function optionalText(value) {
14
+ return value === null || typeof value === "string";
15
+ }
16
+ function block(value) {
17
+ if (!object(value) || !natural(value["position"]))
18
+ return false;
19
+ if (value["type"] === "text")
20
+ return (keys(value, { required: ["type", "position", "text"] }) &&
21
+ typeof value["text"] === "string");
22
+ if (value["type"] === "tool_use")
23
+ return (keys(value, { required: ["type", "position", "id", "name", "input"] }) &&
24
+ typeof value["id"] === "string" &&
25
+ typeof value["name"] === "string");
26
+ if (value["type"] !== "tool_result")
27
+ return false;
28
+ return toolResult(value);
29
+ }
30
+ function toolResult(value) {
31
+ return (keys(value, {
32
+ required: ["type", "position", "tool_use_id", "content"],
33
+ optional: ["is_error"],
34
+ }) &&
35
+ typeof value["tool_use_id"] === "string" &&
36
+ (!Object.hasOwn(value, "is_error") ||
37
+ typeof value["is_error"] === "boolean"));
38
+ }
39
+ function identityFields(value) {
40
+ return ((value["uuid"] === null ||
41
+ (typeof value["uuid"] === "string" && value["uuid"] !== "")) &&
42
+ (value["isSidechain"] === null ||
43
+ typeof value["isSidechain"] === "boolean") &&
44
+ (!Object.hasOwn(value, "parentUuid") ||
45
+ value["parentUuid"] === null ||
46
+ (typeof value["parentUuid"] === "string" && value["parentUuid"] !== "")));
47
+ }
48
+ function versionFields(value) {
49
+ const required = [
50
+ "schemaVersion",
51
+ "sourceId",
52
+ "role",
53
+ "timestamp",
54
+ "sessionId",
55
+ "text",
56
+ "blocks",
57
+ ];
58
+ const version = value["schemaVersion"];
59
+ if (version !== 1 && version !== 2)
60
+ return false;
61
+ const fields = version === 1
62
+ ? { required }
63
+ : {
64
+ required: [...required, "uuid", "isSidechain"],
65
+ optional: ["parentUuid"],
66
+ };
67
+ return keys(value, fields) && (version === 1 || identityFields(value));
68
+ }
69
+ function messageFields(value) {
70
+ return (versionFields(value) &&
71
+ typeof value["sourceId"] === "string" &&
72
+ value["sourceId"] !== "" &&
73
+ ["user", "assistant"].includes(String(value["role"])) &&
74
+ optionalText(value["timestamp"]) &&
75
+ optionalText(value["sessionId"]) &&
76
+ typeof value["text"] === "string");
77
+ }
78
+ function message(value) {
79
+ if (!object(value) || !messageFields(value))
80
+ return false;
81
+ if (!Array.isArray(value["blocks"]) || !value["blocks"].every(block))
82
+ return false;
83
+ let position = -1;
84
+ for (const item of value["blocks"]) {
85
+ const next = item["position"];
86
+ if (!natural(next) || next <= position)
87
+ return false;
88
+ position = next;
89
+ }
90
+ return true;
91
+ }
92
+ export function parseCorpusRecord(line) {
93
+ const value = parsePreservedJson(line);
94
+ if (!message(value))
95
+ throw new Error("invalid-import");
96
+ return value;
97
+ }
98
+ export function parseCorpus(text) {
99
+ const lines = text.split("\n");
100
+ if (lines.at(-1) === "")
101
+ lines.pop();
102
+ return lines.map(parseCorpusRecord);
103
+ }
104
+ function coverageFile(value) {
105
+ if (!object(value) ||
106
+ typeof value["path"] !== "string" ||
107
+ typeof value["reason"] !== "string")
108
+ return false;
109
+ if (!["included", "unreadable", "unsupported", "too-large"].includes(String(value["status"])))
110
+ return false;
111
+ if (!optionalText(value["digest"]) || !natural(value["recordCount"]))
112
+ return false;
113
+ if (!coverageSize(value))
114
+ return false;
115
+ const omissions = value["omissions"];
116
+ return (object(omissions) &&
117
+ natural(omissions["metadataRecords"]) &&
118
+ natural(omissions["thinkingBlocks"]));
119
+ }
120
+ export function validateCoverage(text, importId) {
121
+ const value = JSON.parse(text);
122
+ if (!object(value) || value["importId"] !== importId)
123
+ throw new Error("invalid-import");
124
+ if (value["schemaVersion"] === 2 && scanCoverage(value))
125
+ return;
126
+ if (value["schemaVersion"] === 1 &&
127
+ Array.isArray(value["files"]) &&
128
+ value["files"].every(coverageFile))
129
+ return;
130
+ throw new Error("invalid-import");
131
+ }
132
+ function scanCoverage(value) {
133
+ const roots = value["roots"];
134
+ const exclusions = value["exclusions"];
135
+ const limits = value["limits"];
136
+ const entries = value["entries"];
137
+ return (keys(value, {
138
+ required: [
139
+ "schemaVersion",
140
+ "importId",
141
+ "roots",
142
+ "exclusions",
143
+ "limits",
144
+ "entries",
145
+ ],
146
+ }) &&
147
+ Array.isArray(roots) &&
148
+ roots.length > 0 &&
149
+ roots.every(absolutePath) &&
150
+ Array.isArray(exclusions) &&
151
+ exclusions.every((name) => typeof name === "string" &&
152
+ name !== "" &&
153
+ name !== "." &&
154
+ name !== ".." &&
155
+ !["/", "\\", "\0", "*", "?", "[", "]"].some((character) => name.includes(character))) &&
156
+ coverageLimits(limits) &&
157
+ Array.isArray(entries) &&
158
+ entries.every((entry) => scanCoverageEntry(entry, roots)));
159
+ }
160
+ function coverageLimits(value) {
161
+ return (object(value) &&
162
+ keys(value, {
163
+ required: ["depth", "files", "sourceBytes", "corpusBytes"],
164
+ }) &&
165
+ value["depth"] === 4 &&
166
+ value["files"] === 100 &&
167
+ value["sourceBytes"] === 10_485_760 &&
168
+ value["corpusBytes"] === 52_428_800);
169
+ }
170
+ function scanCoverageEntry(value, roots) {
171
+ if (!object(value) || !coverageFile({ ...value, status: "included" }))
172
+ return false;
173
+ if (!keys(value, {
174
+ required: [
175
+ "kind",
176
+ "path",
177
+ "selection",
178
+ "status",
179
+ "reason",
180
+ "digest",
181
+ "recordCount",
182
+ "omissions",
183
+ ],
184
+ optional: ["byteSize"],
185
+ }))
186
+ return false;
187
+ const selection = value["selection"];
188
+ if (!coverageSelection(selection, roots.length))
189
+ return false;
190
+ if (!["file", "subtree"].includes(String(value["kind"])))
191
+ return false;
192
+ if (selection["kind"] === "file" && value["kind"] !== "file")
193
+ return false;
194
+ if (selection.kind === "root" &&
195
+ !withinRoot(roots[selection.index], value["path"]))
196
+ return false;
197
+ return scanStatus(value, selection["kind"]);
198
+ }
199
+ function coverageSelection(value, rootCount) {
200
+ if (!object(value) ||
201
+ !keys(value, { required: ["kind", "index"] }) ||
202
+ !natural(value["index"]))
203
+ return false;
204
+ return (value["kind"] === "file" ||
205
+ (value["kind"] === "root" && value["index"] < rootCount));
206
+ }
207
+ function scanStatus(value, selection) {
208
+ const status = value["status"];
209
+ const reason = value["reason"];
210
+ if (status === "included")
211
+ return (value["kind"] === "file" &&
212
+ reason === "supported" &&
213
+ typeof value["digest"] === "string");
214
+ if (status === "unreadable")
215
+ return reason === "source-unreadable" && emptyCoverageEntry(value);
216
+ if (["too-large", "excluded", "pending"].includes(String(status)))
217
+ return scanOmission(value, selection);
218
+ return scanRefusal(value);
219
+ }
220
+ function scanRefusal(value) {
221
+ if (value["status"] !== "unsupported" || value["recordCount"] !== 0)
222
+ return false;
223
+ const contentReasons = [
224
+ "invalid-utf8",
225
+ "empty-file",
226
+ "invalid-json",
227
+ "unsupported-record",
228
+ "unsupported-message",
229
+ "unsupported-block",
230
+ ];
231
+ if (contentReasons.includes(String(value["reason"])))
232
+ return value["kind"] === "file" && typeof value["digest"] === "string";
233
+ const reasons = value["kind"] === "subtree"
234
+ ? [
235
+ "symbolic-link",
236
+ "nonregular-file",
237
+ "outside-root",
238
+ "repository-root",
239
+ "source-changed",
240
+ "non-directory-root",
241
+ ]
242
+ : [
243
+ "symbolic-link",
244
+ "nonregular-file",
245
+ "outside-root",
246
+ "source-changed",
247
+ "unsupported-extension",
248
+ "file-too-large",
249
+ ];
250
+ return reasons.includes(String(value["reason"])) && emptyCoverageEntry(value);
251
+ }
252
+ function absolutePath(value) {
253
+ return (typeof value === "string" &&
254
+ value.startsWith("/") &&
255
+ !value.includes("\0") &&
256
+ value.split("/").every((part) => part !== "." && part !== ".."));
257
+ }
258
+ export function withinRoot(root, path) {
259
+ if (root === undefined || !absolutePath(path))
260
+ return false;
261
+ const parent = root.split("/").filter(Boolean);
262
+ const child = path.split("/").filter(Boolean);
263
+ return parent.every((part, index) => part === child[index]);
264
+ }
265
+ function scanOmission(value, selection) {
266
+ if (!emptyCoverageEntry(value))
267
+ return false;
268
+ if (value["status"] === "too-large")
269
+ return selection === "file" && value["reason"] === "file-too-large";
270
+ if (selection !== "root")
271
+ return false;
272
+ if (value["status"] === "excluded")
273
+ return (value["kind"] === "subtree" && value["reason"] === "project-excluded");
274
+ return (value["reason"] ===
275
+ (value["kind"] === "subtree" ? "depth-limit" : "file-limit"));
276
+ }
277
+ function emptyCoverageEntry(value) {
278
+ const omissions = value["omissions"];
279
+ return (value["digest"] === null &&
280
+ value["recordCount"] === 0 &&
281
+ object(omissions) &&
282
+ omissions["metadataRecords"] === 0 &&
283
+ omissions["thinkingBlocks"] === 0);
284
+ }
285
+ function coverageSize(value) {
286
+ return (!Object.hasOwn(value, "byteSize") ||
287
+ (natural(value["byteSize"]) && value["byteSize"] <= 10_485_760));
288
+ }
@@ -56,7 +56,7 @@ async function privateDirectory(path) {
56
56
  }
57
57
  export async function importDirectory(runtime, importId) {
58
58
  if (process.platform !== "darwin")
59
- throw new Error("destination-refused");
59
+ throw new Error("platform-unsupported");
60
60
  let chats;
61
61
  try {
62
62
  chats = await canonical(join(resolve(runtime), "chats"));
@@ -73,6 +73,8 @@ export async function importDirectory(runtime, importId) {
73
73
  return directory;
74
74
  }
75
75
  export async function validateDestination(directory) {
76
+ if (process.platform !== "darwin")
77
+ throw new Error("platform-unsupported");
76
78
  if ((await realpath(directory)) !== directory)
77
79
  throw new Error("destination-refused");
78
80
  await outsideRepository(directory);
@@ -1,13 +1,15 @@
1
- export interface ImportRequest {
2
- readonly paths: readonly string[];
3
- readonly workingDirectory: string;
1
+ import { type StructureCounts } from "./structure.ts";
2
+ import { type SelectionRequest } from "./selection.ts";
3
+ export interface ImportRequest extends SelectionRequest {
4
4
  readonly runtimeDirectory: string | undefined;
5
+ readonly previousImportId?: string;
5
6
  }
6
- export interface ImportSummary {
7
- readonly code: "import-complete" | "import-partial" | "runtime-directory-unknown" | "destination-refused" | "output-failed";
7
+ export interface ImportSummary extends StructureCounts {
8
+ readonly code: "import-complete" | "import-partial" | "runtime-directory-unknown" | "platform-unsupported" | "destination-refused" | "output-failed" | "previous-import-refused";
8
9
  readonly importId: string | null;
9
10
  readonly included: number;
10
11
  readonly refused: number;
11
- readonly records: number;
12
+ readonly excluded?: number;
13
+ readonly pending?: number;
12
14
  }
13
15
  export declare function importChats(request: ImportRequest): Promise<ImportSummary>;