tracegrove 0.0.0-stage → 0.3.1

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 (703) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +61 -2
  3. package/dist/adapters/browser/capabilities.d.ts +45 -0
  4. package/dist/adapters/browser/capabilities.js +14 -0
  5. package/dist/adapters/browser/capabilities.js.map +1 -0
  6. package/dist/adapters/browser/driver.d.ts +45 -0
  7. package/dist/adapters/browser/driver.js +295 -0
  8. package/dist/adapters/browser/driver.js.map +1 -0
  9. package/dist/adapters/browser/session.d.ts +21 -0
  10. package/dist/adapters/browser/session.js +87 -0
  11. package/dist/adapters/browser/session.js.map +1 -0
  12. package/dist/adapters/http/capabilities.d.ts +2 -0
  13. package/dist/adapters/http/capabilities.js +21 -0
  14. package/dist/adapters/http/capabilities.js.map +1 -0
  15. package/dist/adapters/http/driver.d.ts +55 -0
  16. package/dist/adapters/http/driver.js +125 -0
  17. package/dist/adapters/http/driver.js.map +1 -0
  18. package/dist/adapters/job/capabilities.d.ts +45 -0
  19. package/dist/adapters/job/capabilities.js +8 -0
  20. package/dist/adapters/job/capabilities.js.map +1 -0
  21. package/dist/adapters/job/driver.d.ts +26 -0
  22. package/dist/adapters/job/driver.js +110 -0
  23. package/dist/adapters/job/driver.js.map +1 -0
  24. package/dist/adapters/job/types.d.ts +9 -0
  25. package/dist/adapters/job/types.js +2 -0
  26. package/dist/adapters/job/types.js.map +1 -0
  27. package/dist/adapters/mcp/capabilities.d.ts +46 -0
  28. package/dist/adapters/mcp/capabilities.js +17 -0
  29. package/dist/adapters/mcp/capabilities.js.map +1 -0
  30. package/dist/adapters/mcp/driver.d.ts +10 -0
  31. package/dist/adapters/mcp/driver.js +83 -0
  32. package/dist/adapters/mcp/driver.js.map +1 -0
  33. package/dist/adapters/poll.d.ts +12 -0
  34. package/dist/adapters/poll.js +31 -0
  35. package/dist/adapters/poll.js.map +1 -0
  36. package/dist/authoring/activity.d.ts +17 -0
  37. package/dist/authoring/activity.js +18 -0
  38. package/dist/authoring/activity.js.map +1 -0
  39. package/dist/authoring/agent.d.ts +70 -0
  40. package/dist/authoring/agent.js +268 -0
  41. package/dist/authoring/agent.js.map +1 -0
  42. package/dist/authoring/appLaunch.d.ts +7 -0
  43. package/dist/authoring/appLaunch.js +32 -0
  44. package/dist/authoring/appLaunch.js.map +1 -0
  45. package/dist/authoring/appLocation.d.ts +2 -0
  46. package/dist/authoring/appLocation.js +5 -0
  47. package/dist/authoring/appLocation.js.map +1 -0
  48. package/dist/authoring/browser.d.ts +15 -0
  49. package/dist/authoring/browser.js +20 -0
  50. package/dist/authoring/browser.js.map +1 -0
  51. package/dist/authoring/compile.d.ts +47 -0
  52. package/dist/authoring/compile.js +508 -0
  53. package/dist/authoring/compile.js.map +1 -0
  54. package/dist/authoring/discover.d.ts +43 -0
  55. package/dist/authoring/discover.js +149 -0
  56. package/dist/authoring/discover.js.map +1 -0
  57. package/dist/authoring/environmentTemplates.d.ts +3 -0
  58. package/dist/authoring/environmentTemplates.js +24 -0
  59. package/dist/authoring/environmentTemplates.js.map +1 -0
  60. package/dist/authoring/heal.d.ts +108 -0
  61. package/dist/authoring/heal.js +723 -0
  62. package/dist/authoring/heal.js.map +1 -0
  63. package/dist/authoring/index.d.ts +14 -0
  64. package/dist/authoring/index.js +15 -0
  65. package/dist/authoring/index.js.map +1 -0
  66. package/dist/authoring/init.d.ts +21 -0
  67. package/dist/authoring/init.js +141 -0
  68. package/dist/authoring/init.js.map +1 -0
  69. package/dist/authoring/localSettings.d.ts +33 -0
  70. package/dist/authoring/localSettings.js +31 -0
  71. package/dist/authoring/localSettings.js.map +1 -0
  72. package/dist/authoring/media.d.ts +10 -0
  73. package/dist/authoring/media.js +37 -0
  74. package/dist/authoring/media.js.map +1 -0
  75. package/dist/authoring/module.d.ts +2 -0
  76. package/dist/authoring/module.js +38 -0
  77. package/dist/authoring/module.js.map +1 -0
  78. package/dist/authoring/run.d.ts +74 -0
  79. package/dist/authoring/run.js +242 -0
  80. package/dist/authoring/run.js.map +1 -0
  81. package/dist/authoring/runSource.d.ts +6 -0
  82. package/dist/authoring/runSource.js +24 -0
  83. package/dist/authoring/runSource.js.map +1 -0
  84. package/dist/authoring/savedRun.d.ts +13 -0
  85. package/dist/authoring/savedRun.js +94 -0
  86. package/dist/authoring/savedRun.js.map +1 -0
  87. package/dist/authoring/schema.d.ts +574 -0
  88. package/dist/authoring/schema.js +147 -0
  89. package/dist/authoring/schema.js.map +1 -0
  90. package/dist/authoring/snapshotSource.d.ts +13 -0
  91. package/dist/authoring/snapshotSource.js +41 -0
  92. package/dist/authoring/snapshotSource.js.map +1 -0
  93. package/dist/authoring/sourceSelection.d.ts +34 -0
  94. package/dist/authoring/sourceSelection.js +13 -0
  95. package/dist/authoring/sourceSelection.js.map +1 -0
  96. package/dist/authoring/sources.d.ts +5 -0
  97. package/dist/authoring/sources.js +65 -0
  98. package/dist/authoring/sources.js.map +1 -0
  99. package/dist/authoring/status.d.ts +48 -0
  100. package/dist/authoring/status.js +100 -0
  101. package/dist/authoring/status.js.map +1 -0
  102. package/dist/authoring/typed.d.ts +6 -0
  103. package/dist/authoring/typed.js +5 -0
  104. package/dist/authoring/typed.js.map +1 -0
  105. package/dist/authoring/ui.d.ts +10 -0
  106. package/dist/authoring/ui.js +486 -0
  107. package/dist/authoring/ui.js.map +1 -0
  108. package/dist/authoring/uiPage.d.ts +1 -0
  109. package/dist/authoring/uiPage.js +358 -0
  110. package/dist/authoring/uiPage.js.map +1 -0
  111. package/dist/authoring/uiSourceControls.d.ts +2 -0
  112. package/dist/authoring/uiSourceControls.js +41 -0
  113. package/dist/authoring/uiSourceControls.js.map +1 -0
  114. package/dist/authoring/verificationSource.d.ts +41 -0
  115. package/dist/authoring/verificationSource.js +46 -0
  116. package/dist/authoring/verificationSource.js.map +1 -0
  117. package/dist/authoring/workspace.d.ts +33 -0
  118. package/dist/authoring/workspace.js +58 -0
  119. package/dist/authoring/workspace.js.map +1 -0
  120. package/dist/cli/arguments.d.ts +288 -0
  121. package/dist/cli/arguments.js +121 -0
  122. package/dist/cli/arguments.js.map +1 -0
  123. package/dist/cli/cleanup.d.ts +18 -0
  124. package/dist/cli/cleanup.js +40 -0
  125. package/dist/cli/cleanup.js.map +1 -0
  126. package/dist/cli/doctor.d.ts +51 -0
  127. package/dist/cli/doctor.js +118 -0
  128. package/dist/cli/doctor.js.map +1 -0
  129. package/dist/cli/errors.d.ts +2 -0
  130. package/dist/cli/errors.js +84 -0
  131. package/dist/cli/errors.js.map +1 -0
  132. package/dist/cli/jsonFile.d.ts +2 -0
  133. package/dist/cli/jsonFile.js +15 -0
  134. package/dist/cli/jsonFile.js.map +1 -0
  135. package/dist/cli/main.d.ts +2 -0
  136. package/dist/cli/main.js +603 -0
  137. package/dist/cli/main.js.map +1 -0
  138. package/dist/cli/render.d.ts +22 -0
  139. package/dist/cli/render.js +150 -0
  140. package/dist/cli/render.js.map +1 -0
  141. package/dist/cli/samples/catalog.d.ts +10 -0
  142. package/dist/cli/samples/catalog.js +3 -0
  143. package/dist/cli/samples/catalog.js.map +1 -0
  144. package/dist/cli/samples/write.d.ts +5 -0
  145. package/dist/cli/samples/write.js +64 -0
  146. package/dist/cli/samples/write.js.map +1 -0
  147. package/dist/cli/source.d.ts +41 -0
  148. package/dist/cli/source.js +59 -0
  149. package/dist/cli/source.js.map +1 -0
  150. package/dist/core/activationDecision.d.ts +153 -0
  151. package/dist/core/activationDecision.js +34 -0
  152. package/dist/core/activationDecision.js.map +1 -0
  153. package/dist/core/artifacts.d.ts +18 -0
  154. package/dist/core/artifacts.js +79 -0
  155. package/dist/core/artifacts.js.map +1 -0
  156. package/dist/core/atomicFiles.d.ts +9 -0
  157. package/dist/core/atomicFiles.js +76 -0
  158. package/dist/core/atomicFiles.js.map +1 -0
  159. package/dist/core/boundedFile.d.ts +2 -0
  160. package/dist/core/boundedFile.js +28 -0
  161. package/dist/core/boundedFile.js.map +1 -0
  162. package/dist/core/bundle.d.ts +77 -0
  163. package/dist/core/bundle.js +375 -0
  164. package/dist/core/bundle.js.map +1 -0
  165. package/dist/core/bundleArchive.d.ts +10 -0
  166. package/dist/core/bundleArchive.js +47 -0
  167. package/dist/core/bundleArchive.js.map +1 -0
  168. package/dist/core/bundleEvidence.d.ts +12 -0
  169. package/dist/core/bundleEvidence.js +169 -0
  170. package/dist/core/bundleEvidence.js.map +1 -0
  171. package/dist/core/bundleExport.d.ts +12 -0
  172. package/dist/core/bundleExport.js +36 -0
  173. package/dist/core/bundleExport.js.map +1 -0
  174. package/dist/core/bundleFiles.d.ts +5 -0
  175. package/dist/core/bundleFiles.js +47 -0
  176. package/dist/core/bundleFiles.js.map +1 -0
  177. package/dist/core/bundlePaths.d.ts +2 -0
  178. package/dist/core/bundlePaths.js +7 -0
  179. package/dist/core/bundlePaths.js.map +1 -0
  180. package/dist/core/bundleSnapshot.d.ts +26 -0
  181. package/dist/core/bundleSnapshot.js +71 -0
  182. package/dist/core/bundleSnapshot.js.map +1 -0
  183. package/dist/core/capabilityBoundary.d.ts +1452 -0
  184. package/dist/core/capabilityBoundary.js +361 -0
  185. package/dist/core/capabilityBoundary.js.map +1 -0
  186. package/dist/core/capabilityLifecycle.d.ts +366 -0
  187. package/dist/core/capabilityLifecycle.js +79 -0
  188. package/dist/core/capabilityLifecycle.js.map +1 -0
  189. package/dist/core/cleanup.d.ts +35 -0
  190. package/dist/core/cleanup.js +71 -0
  191. package/dist/core/cleanup.js.map +1 -0
  192. package/dist/core/cleanupActions.d.ts +5 -0
  193. package/dist/core/cleanupActions.js +15 -0
  194. package/dist/core/cleanupActions.js.map +1 -0
  195. package/dist/core/cleanupAttestation.d.ts +23 -0
  196. package/dist/core/cleanupAttestation.js +57 -0
  197. package/dist/core/cleanupAttestation.js.map +1 -0
  198. package/dist/core/clock.d.ts +4 -0
  199. package/dist/core/clock.js +14 -0
  200. package/dist/core/clock.js.map +1 -0
  201. package/dist/core/compiler.d.ts +19 -0
  202. package/dist/core/compiler.js +200 -0
  203. package/dist/core/compiler.js.map +1 -0
  204. package/dist/core/controller.d.ts +7 -0
  205. package/dist/core/controller.js +132 -0
  206. package/dist/core/controller.js.map +1 -0
  207. package/dist/core/coordination.d.ts +72 -0
  208. package/dist/core/coordination.js +118 -0
  209. package/dist/core/coordination.js.map +1 -0
  210. package/dist/core/corpus.d.ts +60 -0
  211. package/dist/core/corpus.js +216 -0
  212. package/dist/core/corpus.js.map +1 -0
  213. package/dist/core/deadline.d.ts +12 -0
  214. package/dist/core/deadline.js +38 -0
  215. package/dist/core/deadline.js.map +1 -0
  216. package/dist/core/deliveryJournal.d.ts +37 -0
  217. package/dist/core/deliveryJournal.js +85 -0
  218. package/dist/core/deliveryJournal.js.map +1 -0
  219. package/dist/core/environmentPreflight.d.ts +14 -0
  220. package/dist/core/environmentPreflight.js +179 -0
  221. package/dist/core/environmentPreflight.js.map +1 -0
  222. package/dist/core/errors.d.ts +22 -0
  223. package/dist/core/errors.js +29 -0
  224. package/dist/core/errors.js.map +1 -0
  225. package/dist/core/events.d.ts +14 -0
  226. package/dist/core/events.js +37 -0
  227. package/dist/core/events.js.map +1 -0
  228. package/dist/core/executionInspection.d.ts +90 -0
  229. package/dist/core/executionInspection.js +31 -0
  230. package/dist/core/executionInspection.js.map +1 -0
  231. package/dist/core/executionOwnership.d.ts +72 -0
  232. package/dist/core/executionOwnership.js +82 -0
  233. package/dist/core/executionOwnership.js.map +1 -0
  234. package/dist/core/executionPreparation.d.ts +362 -0
  235. package/dist/core/executionPreparation.js +93 -0
  236. package/dist/core/executionPreparation.js.map +1 -0
  237. package/dist/core/executionReadback.d.ts +15 -0
  238. package/dist/core/executionReadback.js +21 -0
  239. package/dist/core/executionReadback.js.map +1 -0
  240. package/dist/core/executor.d.ts +46 -0
  241. package/dist/core/executor.js +616 -0
  242. package/dist/core/executor.js.map +1 -0
  243. package/dist/core/frozenBundle.d.ts +314 -0
  244. package/dist/core/frozenBundle.js +24 -0
  245. package/dist/core/frozenBundle.js.map +1 -0
  246. package/dist/core/fsDurability.d.ts +2 -0
  247. package/dist/core/fsDurability.js +12 -0
  248. package/dist/core/fsDurability.js.map +1 -0
  249. package/dist/core/generators.d.ts +4 -0
  250. package/dist/core/generators.js +71 -0
  251. package/dist/core/generators.js.map +1 -0
  252. package/dist/core/gitSnapshot.d.ts +63 -0
  253. package/dist/core/gitSnapshot.js +55 -0
  254. package/dist/core/gitSnapshot.js.map +1 -0
  255. package/dist/core/gitSources.d.ts +29 -0
  256. package/dist/core/gitSources.js +97 -0
  257. package/dist/core/gitSources.js.map +1 -0
  258. package/dist/core/ledger.d.ts +38 -0
  259. package/dist/core/ledger.js +169 -0
  260. package/dist/core/ledger.js.map +1 -0
  261. package/dist/core/ledgerInspection.d.ts +18 -0
  262. package/dist/core/ledgerInspection.js +66 -0
  263. package/dist/core/ledgerInspection.js.map +1 -0
  264. package/dist/core/ledgerRecords.d.ts +23 -0
  265. package/dist/core/ledgerRecords.js +29 -0
  266. package/dist/core/ledgerRecords.js.map +1 -0
  267. package/dist/core/localActivationState.d.ts +260 -0
  268. package/dist/core/localActivationState.js +49 -0
  269. package/dist/core/localActivationState.js.map +1 -0
  270. package/dist/core/localPromotionState.d.ts +387 -0
  271. package/dist/core/localPromotionState.js +22 -0
  272. package/dist/core/localPromotionState.js.map +1 -0
  273. package/dist/core/localQualificationResults.d.ts +39 -0
  274. package/dist/core/localQualificationResults.js +160 -0
  275. package/dist/core/localQualificationResults.js.map +1 -0
  276. package/dist/core/localReviewStore.d.ts +28 -0
  277. package/dist/core/localReviewStore.js +167 -0
  278. package/dist/core/localReviewStore.js.map +1 -0
  279. package/dist/core/localScenarioActivation.d.ts +6 -0
  280. package/dist/core/localScenarioActivation.js +70 -0
  281. package/dist/core/localScenarioActivation.js.map +1 -0
  282. package/dist/core/localScenarioOwner.d.ts +20 -0
  283. package/dist/core/localScenarioOwner.js +2 -0
  284. package/dist/core/localScenarioOwner.js.map +1 -0
  285. package/dist/core/localScenarioPromotion.d.ts +9 -0
  286. package/dist/core/localScenarioPromotion.js +49 -0
  287. package/dist/core/localScenarioPromotion.js.map +1 -0
  288. package/dist/core/localScenarioState.d.ts +2297 -0
  289. package/dist/core/localScenarioState.js +117 -0
  290. package/dist/core/localScenarioState.js.map +1 -0
  291. package/dist/core/localScenarioStore.d.ts +838 -0
  292. package/dist/core/localScenarioStore.js +218 -0
  293. package/dist/core/localScenarioStore.js.map +1 -0
  294. package/dist/core/localScenarioStructure.d.ts +4 -0
  295. package/dist/core/localScenarioStructure.js +52 -0
  296. package/dist/core/localScenarioStructure.js.map +1 -0
  297. package/dist/core/localStructureState.d.ts +2 -0
  298. package/dist/core/localStructureState.js +22 -0
  299. package/dist/core/localStructureState.js.map +1 -0
  300. package/dist/core/lookup.d.ts +662 -0
  301. package/dist/core/lookup.js +55 -0
  302. package/dist/core/lookup.js.map +1 -0
  303. package/dist/core/ownership.d.ts +3 -0
  304. package/dist/core/ownership.js +24 -0
  305. package/dist/core/ownership.js.map +1 -0
  306. package/dist/core/planInspection.d.ts +108 -0
  307. package/dist/core/planInspection.js +44 -0
  308. package/dist/core/planInspection.js.map +1 -0
  309. package/dist/core/planner.d.ts +14 -0
  310. package/dist/core/planner.js +261 -0
  311. package/dist/core/planner.js.map +1 -0
  312. package/dist/core/qualification.d.ts +26 -0
  313. package/dist/core/qualification.js +58 -0
  314. package/dist/core/qualification.js.map +1 -0
  315. package/dist/core/qualificationBundle.d.ts +6 -0
  316. package/dist/core/qualificationBundle.js +51 -0
  317. package/dist/core/qualificationBundle.js.map +1 -0
  318. package/dist/core/qualificationExecution.d.ts +879 -0
  319. package/dist/core/qualificationExecution.js +54 -0
  320. package/dist/core/qualificationExecution.js.map +1 -0
  321. package/dist/core/recoveryStatus.d.ts +6 -0
  322. package/dist/core/recoveryStatus.js +123 -0
  323. package/dist/core/recoveryStatus.js.map +1 -0
  324. package/dist/core/reducer.d.ts +56 -0
  325. package/dist/core/reducer.js +355 -0
  326. package/dist/core/reducer.js.map +1 -0
  327. package/dist/core/replayAssessment.d.ts +15 -0
  328. package/dist/core/replayAssessment.js +78 -0
  329. package/dist/core/replayAssessment.js.map +1 -0
  330. package/dist/core/replayEvidence.d.ts +7 -0
  331. package/dist/core/replayEvidence.js +58 -0
  332. package/dist/core/replayEvidence.js.map +1 -0
  333. package/dist/core/repositorySelectionEvidence.d.ts +3 -0
  334. package/dist/core/repositorySelectionEvidence.js +58 -0
  335. package/dist/core/repositorySelectionEvidence.js.map +1 -0
  336. package/dist/core/rerun.d.ts +3 -0
  337. package/dist/core/rerun.js +24 -0
  338. package/dist/core/rerun.js.map +1 -0
  339. package/dist/core/resultSink.d.ts +52 -0
  340. package/dist/core/resultSink.js +120 -0
  341. package/dist/core/resultSink.js.map +1 -0
  342. package/dist/core/review.d.ts +22 -0
  343. package/dist/core/review.js +65 -0
  344. package/dist/core/review.js.map +1 -0
  345. package/dist/core/runnerCapabilities.d.ts +22 -0
  346. package/dist/core/runnerCapabilities.js +44 -0
  347. package/dist/core/runnerCapabilities.js.map +1 -0
  348. package/dist/core/scenario.d.ts +32 -0
  349. package/dist/core/scenario.js +119 -0
  350. package/dist/core/scenario.js.map +1 -0
  351. package/dist/core/scenarioActivation.d.ts +16 -0
  352. package/dist/core/scenarioActivation.js +47 -0
  353. package/dist/core/scenarioActivation.js.map +1 -0
  354. package/dist/core/scenarioStructure.d.ts +400 -0
  355. package/dist/core/scenarioStructure.js +72 -0
  356. package/dist/core/scenarioStructure.js.map +1 -0
  357. package/dist/core/snapshotEvidence.d.ts +3 -0
  358. package/dist/core/snapshotEvidence.js +37 -0
  359. package/dist/core/snapshotEvidence.js.map +1 -0
  360. package/dist/core/snapshotRepository.d.ts +48 -0
  361. package/dist/core/snapshotRepository.js +47 -0
  362. package/dist/core/snapshotRepository.js.map +1 -0
  363. package/dist/core/source-analysis.d.ts +18 -0
  364. package/dist/core/source-analysis.js +99 -0
  365. package/dist/core/source-analysis.js.map +1 -0
  366. package/dist/core/source-citation.d.ts +53 -0
  367. package/dist/core/source-citation.js +59 -0
  368. package/dist/core/source-citation.js.map +1 -0
  369. package/dist/core/sourcePromotion.d.ts +929 -0
  370. package/dist/core/sourcePromotion.js +92 -0
  371. package/dist/core/sourcePromotion.js.map +1 -0
  372. package/dist/core/sourceReviewEvidence.d.ts +271 -0
  373. package/dist/core/sourceReviewEvidence.js +24 -0
  374. package/dist/core/sourceReviewEvidence.js.map +1 -0
  375. package/dist/core/targetObservation.d.ts +3 -0
  376. package/dist/core/targetObservation.js +26 -0
  377. package/dist/core/targetObservation.js.map +1 -0
  378. package/dist/hosts/launchTemplates.d.ts +2 -0
  379. package/dist/hosts/launchTemplates.js +5 -0
  380. package/dist/hosts/launchTemplates.js.map +1 -0
  381. package/dist/hosts/local.d.ts +17 -0
  382. package/dist/hosts/local.js +311 -0
  383. package/dist/hosts/local.js.map +1 -0
  384. package/dist/hosts/localSupervisor.d.ts +1 -0
  385. package/dist/hosts/localSupervisor.js +115 -0
  386. package/dist/hosts/localSupervisor.js.map +1 -0
  387. package/dist/hosts/mock.d.ts +4 -0
  388. package/dist/hosts/mock.js +82 -0
  389. package/dist/hosts/mock.js.map +1 -0
  390. package/dist/hosts/pinnedArguments.d.ts +3 -0
  391. package/dist/hosts/pinnedArguments.js +39 -0
  392. package/dist/hosts/pinnedArguments.js.map +1 -0
  393. package/dist/hosts/runtime.d.ts +5 -0
  394. package/dist/hosts/runtime.js +60 -0
  395. package/dist/hosts/runtime.js.map +1 -0
  396. package/dist/hosts/sourceIdentity.d.ts +54 -0
  397. package/dist/hosts/sourceIdentity.js +27 -0
  398. package/dist/hosts/sourceIdentity.js.map +1 -0
  399. package/dist/hosts/types.d.ts +39 -0
  400. package/dist/hosts/types.js +2 -0
  401. package/dist/hosts/types.js.map +1 -0
  402. package/dist/index.d.ts +56 -0
  403. package/dist/index.js +52 -0
  404. package/dist/index.js.map +1 -0
  405. package/dist/integrations/awr/attachment.d.ts +34 -0
  406. package/dist/integrations/awr/attachment.js +120 -0
  407. package/dist/integrations/awr/attachment.js.map +1 -0
  408. package/dist/integrations/awr/attachmentContracts.d.ts +273 -0
  409. package/dist/integrations/awr/attachmentContracts.js +39 -0
  410. package/dist/integrations/awr/attachmentContracts.js.map +1 -0
  411. package/dist/integrations/awr/attachmentHttp.d.ts +9 -0
  412. package/dist/integrations/awr/attachmentHttp.js +19 -0
  413. package/dist/integrations/awr/attachmentHttp.js.map +1 -0
  414. package/dist/integrations/awr/cli.d.ts +7 -0
  415. package/dist/integrations/awr/cli.js +43 -0
  416. package/dist/integrations/awr/cli.js.map +1 -0
  417. package/dist/integrations/awr/contracts.d.ts +54 -0
  418. package/dist/integrations/awr/contracts.js +33 -0
  419. package/dist/integrations/awr/contracts.js.map +1 -0
  420. package/dist/integrations/awr/http.d.ts +8 -0
  421. package/dist/integrations/awr/http.js +23 -0
  422. package/dist/integrations/awr/http.js.map +1 -0
  423. package/dist/integrations/awr/index.d.ts +7 -0
  424. package/dist/integrations/awr/index.js +8 -0
  425. package/dist/integrations/awr/index.js.map +1 -0
  426. package/dist/integrations/awr/jsonHttp.d.ts +15 -0
  427. package/dist/integrations/awr/jsonHttp.js +69 -0
  428. package/dist/integrations/awr/jsonHttp.js.map +1 -0
  429. package/dist/integrations/awr/outbox.d.ts +28 -0
  430. package/dist/integrations/awr/outbox.js +88 -0
  431. package/dist/integrations/awr/outbox.js.map +1 -0
  432. package/dist/integrations/awr/projection.d.ts +4 -0
  433. package/dist/integrations/awr/projection.js +54 -0
  434. package/dist/integrations/awr/projection.js.map +1 -0
  435. package/dist/protocol/canonical.d.ts +41 -0
  436. package/dist/protocol/canonical.js +114 -0
  437. package/dist/protocol/canonical.js.map +1 -0
  438. package/dist/protocol/index.d.ts +9620 -0
  439. package/dist/protocol/index.js +185 -0
  440. package/dist/protocol/index.js.map +1 -0
  441. package/dist/protocol/primitives.d.ts +63 -0
  442. package/dist/protocol/primitives.js +46 -0
  443. package/dist/protocol/primitives.js.map +1 -0
  444. package/dist/protocol/schemas/browser.d.ts +153 -0
  445. package/dist/protocol/schemas/browser.js +29 -0
  446. package/dist/protocol/schemas/browser.js.map +1 -0
  447. package/dist/protocol/schemas/capability.d.ts +2126 -0
  448. package/dist/protocol/schemas/capability.js +165 -0
  449. package/dist/protocol/schemas/capability.js.map +1 -0
  450. package/dist/protocol/schemas/capabilityLifecycle.d.ts +509 -0
  451. package/dist/protocol/schemas/capabilityLifecycle.js +47 -0
  452. package/dist/protocol/schemas/capabilityLifecycle.js.map +1 -0
  453. package/dist/protocol/schemas/cleanup.d.ts +109 -0
  454. package/dist/protocol/schemas/cleanup.js +59 -0
  455. package/dist/protocol/schemas/cleanup.js.map +1 -0
  456. package/dist/protocol/schemas/cli.d.ts +121 -0
  457. package/dist/protocol/schemas/cli.js +24 -0
  458. package/dist/protocol/schemas/cli.js.map +1 -0
  459. package/dist/protocol/schemas/config.d.ts +59 -0
  460. package/dist/protocol/schemas/config.js +32 -0
  461. package/dist/protocol/schemas/config.js.map +1 -0
  462. package/dist/protocol/schemas/corpus.d.ts +36 -0
  463. package/dist/protocol/schemas/corpus.js +10 -0
  464. package/dist/protocol/schemas/corpus.js.map +1 -0
  465. package/dist/protocol/schemas/definitions.d.ts +3409 -0
  466. package/dist/protocol/schemas/definitions.js +431 -0
  467. package/dist/protocol/schemas/definitions.js.map +1 -0
  468. package/dist/protocol/schemas/evidenceProjection.d.ts +146 -0
  469. package/dist/protocol/schemas/evidenceProjection.js +18 -0
  470. package/dist/protocol/schemas/evidenceProjection.js.map +1 -0
  471. package/dist/protocol/schemas/execution.d.ts +3179 -0
  472. package/dist/protocol/schemas/execution.js +500 -0
  473. package/dist/protocol/schemas/execution.js.map +1 -0
  474. package/dist/protocol/schemas/gitSources.d.ts +330 -0
  475. package/dist/protocol/schemas/gitSources.js +32 -0
  476. package/dist/protocol/schemas/gitSources.js.map +1 -0
  477. package/dist/protocol/schemas/mcp.d.ts +24 -0
  478. package/dist/protocol/schemas/mcp.js +16 -0
  479. package/dist/protocol/schemas/mcp.js.map +1 -0
  480. package/dist/protocol/schemas/nativeJob.d.ts +106 -0
  481. package/dist/protocol/schemas/nativeJob.js +16 -0
  482. package/dist/protocol/schemas/nativeJob.js.map +1 -0
  483. package/dist/protocol/schemas/portableEnvironment.d.ts +1256 -0
  484. package/dist/protocol/schemas/portableEnvironment.js +108 -0
  485. package/dist/protocol/schemas/portableEnvironment.js.map +1 -0
  486. package/dist/protocol/schemas/promotion.d.ts +132 -0
  487. package/dist/protocol/schemas/promotion.js +9 -0
  488. package/dist/protocol/schemas/promotion.js.map +1 -0
  489. package/dist/protocol/schemas/protocol.d.ts +146 -0
  490. package/dist/protocol/schemas/protocol.js +25 -0
  491. package/dist/protocol/schemas/protocol.js.map +1 -0
  492. package/dist/protocol/schemas/recoveryStatus.d.ts +88 -0
  493. package/dist/protocol/schemas/recoveryStatus.js +20 -0
  494. package/dist/protocol/schemas/recoveryStatus.js.map +1 -0
  495. package/dist/protocol/schemas/resultSink.d.ts +80 -0
  496. package/dist/protocol/schemas/resultSink.js +14 -0
  497. package/dist/protocol/schemas/resultSink.js.map +1 -0
  498. package/dist/protocol/schemas/review.d.ts +248 -0
  499. package/dist/protocol/schemas/review.js +45 -0
  500. package/dist/protocol/schemas/review.js.map +1 -0
  501. package/dist/protocol/schemas/scenario.d.ts +810 -0
  502. package/dist/protocol/schemas/scenario.js +53 -0
  503. package/dist/protocol/schemas/scenario.js.map +1 -0
  504. package/dist/protocol/schemas/source.d.ts +300 -0
  505. package/dist/protocol/schemas/source.js +25 -0
  506. package/dist/protocol/schemas/source.js.map +1 -0
  507. package/dist/source/git.d.ts +36 -0
  508. package/dist/source/git.js +159 -0
  509. package/dist/source/git.js.map +1 -0
  510. package/dist/source/gitObjectProof.d.ts +12 -0
  511. package/dist/source/gitObjectProof.js +115 -0
  512. package/dist/source/gitObjectProof.js.map +1 -0
  513. package/dist/source/snapshotPaths.d.ts +2 -0
  514. package/dist/source/snapshotPaths.js +24 -0
  515. package/dist/source/snapshotPaths.js.map +1 -0
  516. package/dist/source/snapshotTree.d.ts +15 -0
  517. package/dist/source/snapshotTree.js +79 -0
  518. package/dist/source/snapshotTree.js.map +1 -0
  519. package/docs/agent-guide.md +21 -0
  520. package/docs/browser-driver.md +146 -0
  521. package/docs/getting-started.md +13 -0
  522. package/docs/git-object-proof.md +100 -0
  523. package/docs/local-execution-recovery.md +55 -0
  524. package/docs/mcp-driver.md +87 -0
  525. package/docs/native-jobs.md +96 -0
  526. package/docs/result-sink.md +87 -0
  527. package/docs/verified-bundles.md +175 -0
  528. package/package.json +98 -4
  529. package/samples/django-notes/manage.py +8 -0
  530. package/samples/django-notes/notes/__init__.py +0 -0
  531. package/samples/django-notes/notes/auth.py +14 -0
  532. package/samples/django-notes/notes/migrations/0001_initial.py +19 -0
  533. package/samples/django-notes/notes/migrations/__init__.py +0 -0
  534. package/samples/django-notes/notes/models.py +13 -0
  535. package/samples/django-notes/notes/views.py +33 -0
  536. package/samples/django-notes/notesite/__init__.py +0 -0
  537. package/samples/django-notes/notesite/settings.py +17 -0
  538. package/samples/django-notes/notesite/urls.py +9 -0
  539. package/samples/django-notes/requirements.txt +1 -0
  540. package/samples/django-notes/tracegrove/notes/crud.flow.yaml +27 -0
  541. package/samples/django-notes/tracegrove.config.yaml +7 -0
  542. package/samples/fastapi-notes/app/__init__.py +0 -0
  543. package/samples/fastapi-notes/app/main.py +69 -0
  544. package/samples/fastapi-notes/requirements.txt +2 -0
  545. package/samples/fastapi-notes/tracegrove/notes/crud.flow.yaml +27 -0
  546. package/samples/fastapi-notes/tracegrove.config.yaml +8 -0
  547. package/samples/notes-api/app/app.mjs +67 -0
  548. package/samples/notes-api/app/http.mjs +16 -0
  549. package/samples/notes-api/tracegrove/fixtures/existing-note.fixture.yaml +12 -0
  550. package/samples/notes-api/tracegrove/notes/create-read-delete.flow.yaml +35 -0
  551. package/samples/notes-api/tracegrove/notes/list.flow.yaml +25 -0
  552. package/samples/notes-api/tracegrove.config.yaml +15 -0
  553. package/samples/notes-api/verification/actions/notes.registry.yaml +6 -0
  554. package/samples/notes-api/verification/auth/host-issued-owner.yaml +6 -0
  555. package/samples/notes-api/verification/cases/notes.contract.yaml +51 -0
  556. package/samples/notes-api/verification/cases/notes.create.yaml +123 -0
  557. package/samples/notes-api/verification/cases/notes.suite.yaml +5 -0
  558. package/samples/notes-api/verification/components/notes-api-stub.profile.yaml +8 -0
  559. package/samples/notes-api/verification/components/notes-api.profile.yaml +15 -0
  560. package/samples/notes-api/verification/environments/local-notes.yaml +11 -0
  561. package/samples/notes-api/verification/environments/mock-notes.yaml +11 -0
  562. package/samples/notes-api/verification/fidelity/full-live-sandbox.yaml +7 -0
  563. package/samples/notes-api/verification/fidelity/mock-contract.yaml +6 -0
  564. package/samples/notes-api/verification/fixtures/existing-note.payload.yaml +15 -0
  565. package/samples/notes-api/verification/fixtures/existing-note.plan.yaml +9 -0
  566. package/samples/notes-api/verification/fixtures/existing-note.recipe.yaml +29 -0
  567. package/samples/notes-api/verification/hosts/local-process.yaml +27 -0
  568. package/samples/notes-api/verification/hosts/mock-loopback.yaml +14 -0
  569. package/samples/notes-api/verification/mocks/notes.responses.yaml +5 -0
  570. package/samples/notes-api/verification/personas/owner.yaml +16 -0
  571. package/samples/notes-api/verification/policies/no-authoring-inference.yaml +10 -0
  572. package/samples/notes-api/verification/runners/http.yaml +5 -0
  573. package/samples/notes-api/verification/surfaces/http-api.binding.yaml +11 -0
  574. package/samples/notes-api/verification/surfaces/http-api.pack.yaml +7 -0
  575. package/samples/notes-api/verification/workflow.yaml +27 -0
  576. package/samples/notes-browser/tracegrove/notes/browser.flow.yaml +19 -0
  577. package/samples/notes-browser/verification/cases/notes.browser.yaml +63 -0
  578. package/samples/notes-browser/verification/cases/notes.suite.yaml +4 -0
  579. package/samples/notes-browser/verification/runners/http.yaml +5 -0
  580. package/samples/notes-browser/verification/surfaces/http-api.binding.yaml +11 -0
  581. package/samples/notes-browser/verification/surfaces/http-api.pack.yaml +7 -0
  582. package/samples/notes-django/README.md +21 -0
  583. package/samples/notes-django/app/django_app.py +119 -0
  584. package/samples/notes-django/app/requirements.lock +4 -0
  585. package/samples/notes-mcp/app/mcp.mjs +47 -0
  586. package/samples/notes-mcp/tracegrove/notes.flow.yaml +20 -0
  587. package/samples/notes-mcp/tracegrove.config.yaml +13 -0
  588. package/samples/report-jobs/README.md +30 -0
  589. package/samples/report-jobs/app/jobs-api.mjs +65 -0
  590. package/samples/report-jobs/app/native-bridge.mjs +30 -0
  591. package/samples/report-jobs/app/store.mjs +74 -0
  592. package/samples/report-jobs/app/worker.mjs +22 -0
  593. package/samples/report-jobs/tracegrove/fixtures/failed-job.fixture.yaml +12 -0
  594. package/samples/report-jobs/tracegrove/fixtures/held-job.fixture.yaml +12 -0
  595. package/samples/report-jobs/tracegrove/fixtures/success-job.fixture.yaml +12 -0
  596. package/samples/report-jobs/tracegrove/reports/cancellation.flow.yaml +15 -0
  597. package/samples/report-jobs/tracegrove/reports/completion.flow.yaml +31 -0
  598. package/samples/report-jobs/tracegrove/reports/failure.flow.yaml +12 -0
  599. package/samples/report-jobs/tracegrove.config.yaml +10 -0
  600. package/samples/report-native/README.md +11 -0
  601. package/samples/report-native/tracegrove/cancellation.flow.yaml +11 -0
  602. package/samples/report-native/tracegrove/completion.flow.yaml +22 -0
  603. package/samples/report-native/tracegrove/failure.flow.yaml +7 -0
  604. package/samples/report-native/tracegrove.config.yaml +11 -0
  605. package/schema/tracegrove_cli-error_v1.json +156 -0
  606. package/schema/tracegrove_config_v1.json +233 -0
  607. package/schema/tracegrove_fixture_v1.json +297 -0
  608. package/schema/tracegrove_flow_v1.json +960 -0
  609. package/schema/tracegrove_recovery-status_v1.json +234 -0
  610. package/schema/tracegrove_run-video_v1.json +25 -0
  611. package/schema/workflow_action-registry_v1.json +303 -0
  612. package/schema/workflow_auth-recipe_v1.json +146 -0
  613. package/schema/workflow_boundary-observation_v1.json +515 -0
  614. package/schema/workflow_browser-command_v1.json +292 -0
  615. package/schema/workflow_browser-locator_v1.json +74 -0
  616. package/schema/workflow_browser-network-observation_v1.json +48 -0
  617. package/schema/workflow_browser-observation_v1.json +53 -0
  618. package/schema/workflow_budget-reservation_v1.json +150 -0
  619. package/schema/workflow_campaign-result_v1.json +382 -0
  620. package/schema/workflow_capability-artifact-manifest_v1.json +529 -0
  621. package/schema/workflow_capability-descriptor_v1.json +351 -0
  622. package/schema/workflow_capability-lifecycle-checkpoint_v1.json +510 -0
  623. package/schema/workflow_capability-observation_v1.json +1707 -0
  624. package/schema/workflow_capability-operation_v1.json +3212 -0
  625. package/schema/workflow_capability-replay-plan_v1.json +1247 -0
  626. package/schema/workflow_capability-retry-policy_v1.json +39 -0
  627. package/schema/workflow_capability-retry-state_v1.json +242 -0
  628. package/schema/workflow_case_v1.json +4222 -0
  629. package/schema/workflow_change-model_v1.json +614 -0
  630. package/schema/workflow_cleanup-expectation_v1.json +108 -0
  631. package/schema/workflow_cleanup-followup_v1.json +145 -0
  632. package/schema/workflow_component-profile_v1.json +219 -0
  633. package/schema/workflow_config_v1.json +180 -0
  634. package/schema/workflow_corpus_v1.json +172 -0
  635. package/schema/workflow_cost-observation_v1.json +366 -0
  636. package/schema/workflow_credential-lease_v1.json +222 -0
  637. package/schema/workflow_effective-config_v1.json +214 -0
  638. package/schema/workflow_environment-plan_v1.json +445 -0
  639. package/schema/workflow_environment_v1.json +1827 -0
  640. package/schema/workflow_evidence-projection_v1.json +636 -0
  641. package/schema/workflow_execution_v1.json +4086 -0
  642. package/schema/workflow_fidelity-plan_v1.json +512 -0
  643. package/schema/workflow_fidelity-profile_v1.json +396 -0
  644. package/schema/workflow_fixture-manifest_v1.json +918 -0
  645. package/schema/workflow_fixture-plan_v1.json +594 -0
  646. package/schema/workflow_git-source-request_v1.json +124 -0
  647. package/schema/workflow_git-source-resolution_v1.json +660 -0
  648. package/schema/workflow_git-source-snapshot_v1.json +287 -0
  649. package/schema/workflow_host-lease_v1.json +321 -0
  650. package/schema/workflow_host-observation_v1.json +282 -0
  651. package/schema/workflow_host-plan_v1.json +719 -0
  652. package/schema/workflow_identity-attestation_v1.json +412 -0
  653. package/schema/workflow_intelligence-policy_v1.json +153 -0
  654. package/schema/workflow_logical-payload_v1.json +206 -0
  655. package/schema/workflow_mcp-tool-call_v1.json +70 -0
  656. package/schema/workflow_mcp-tool-observation_v1.json +125 -0
  657. package/schema/workflow_mock-responses_v1.json +185 -0
  658. package/schema/workflow_native-job-action_v1.json +123 -0
  659. package/schema/workflow_native-job-observation_v1.json +138 -0
  660. package/schema/workflow_native-job-ready_v1.json +31 -0
  661. package/schema/workflow_native-job-request_v1.json +155 -0
  662. package/schema/workflow_native-job-response_v1.json +125 -0
  663. package/schema/workflow_ownership_v1.json +116 -0
  664. package/schema/workflow_persona_v1.json +499 -0
  665. package/schema/workflow_plan-edit-projection_v1.json +152 -0
  666. package/schema/workflow_plan-review_v1.json +246 -0
  667. package/schema/workflow_portable-environment-intent_v1.json +499 -0
  668. package/schema/workflow_portable-environment-profile_v1.json +1429 -0
  669. package/schema/workflow_portable-preflight_v1.json +2281 -0
  670. package/schema/workflow_qualification-admission_v1.json +467 -0
  671. package/schema/workflow_qualification-intent_v1.json +98 -0
  672. package/schema/workflow_qualification-policy_v1.json +109 -0
  673. package/schema/workflow_qualification-round_v1.json +226 -0
  674. package/schema/workflow_replay-assessment_v1.json +197 -0
  675. package/schema/workflow_replay-finding_v1.json +147 -0
  676. package/schema/workflow_request_v1.json +1567 -0
  677. package/schema/workflow_result-ingest_v1.json +343 -0
  678. package/schema/workflow_revisions_v1.json +334 -0
  679. package/schema/workflow_routing-decision_v1.json +482 -0
  680. package/schema/workflow_runner-capabilities_v1.json +316 -0
  681. package/schema/workflow_runner-profile_v1.json +119 -0
  682. package/schema/workflow_runner-protocol_v1_host.json +382 -0
  683. package/schema/workflow_runner-protocol_v1_plugin.json +491 -0
  684. package/schema/workflow_scenario-activation-intent_v1.json +346 -0
  685. package/schema/workflow_scenario-activation_v1.json +562 -0
  686. package/schema/workflow_scenario-projection_v1.json +221 -0
  687. package/schema/workflow_scenario-promotion_v1.json +455 -0
  688. package/schema/workflow_scenario-replay-assessment_v1.json +696 -0
  689. package/schema/workflow_scenario-revision-token_v1.json +115 -0
  690. package/schema/workflow_scenario-structure_v1.json +368 -0
  691. package/schema/workflow_scenario_v1.json +401 -0
  692. package/schema/workflow_scoped-resource_v1.json +550 -0
  693. package/schema/workflow_seed-recipe_v1.json +724 -0
  694. package/schema/workflow_selection_v1.json +1108 -0
  695. package/schema/workflow_signed-cleanup-followup_v1.json +175 -0
  696. package/schema/workflow_source-plan_v1.json +756 -0
  697. package/schema/workflow_source-selection_v1.json +456 -0
  698. package/schema/workflow_source-validation_v1.json +366 -0
  699. package/schema/workflow_step-event_v1.json +228 -0
  700. package/schema/workflow_stream-transcript_v1.json +1030 -0
  701. package/schema/workflow_suite_v1.json +64 -0
  702. package/schema/workflow_surface-binding_v1.json +411 -0
  703. package/schema/workflow_surface-pack_v1.json +159 -0
@@ -0,0 +1,115 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { GitSourceSnapshot, GIT_COMMIT_PROOF_LIMITS, GIT_SNAPSHOT_LIMITS, digestOfBytes, digestOfValue, sameDigest, verifySelfDigest } from "../protocol/index.js";
3
+ import { Conflict } from "../core/errors.js";
4
+ import { assertSnapshotPaths } from "./snapshotPaths.js";
5
+ export function gitObjectId(type, bytes, algorithm) {
6
+ return createHash(algorithm).update(`${type} ${bytes.byteLength}\0`).update(bytes).digest('hex');
7
+ }
8
+ function decode(value, bound) {
9
+ const bytes = Buffer.from(value, 'base64');
10
+ if (bytes.length > bound || bytes.toString('base64') !== value)
11
+ throw new Conflict('Git object proof has noncanonical or oversized bytes');
12
+ return bytes;
13
+ }
14
+ function verify(input, actual) {
15
+ const snapshot = GitSourceSnapshot.parse(input);
16
+ if (!verifySelfDigest(snapshot) || !snapshot.commitProof)
17
+ throw new Conflict('Git commit proof is missing or its snapshot seal changed');
18
+ if (snapshot.files.reduce((sum, file) => sum + file.bytes, 0) > GIT_SNAPSHOT_LIMITS.totalBytes)
19
+ throw new Conflict('Git proof snapshot exceeds the total file byte bound');
20
+ const proof = snapshot.commitProof;
21
+ const algorithm = snapshot.commit.length === 40 ? 'sha1' : 'sha256';
22
+ const oidBytes = algorithm === 'sha1' ? 20 : 32;
23
+ const commit = decode(proof.commitBase64, GIT_COMMIT_PROOF_LIMITS.commitBytes);
24
+ const observedCommit = gitObjectId('commit', commit, algorithm);
25
+ if (observedCommit !== snapshot.commit)
26
+ throw new Conflict('Git commit object disagrees with selected snapshot commit');
27
+ const root = /^tree ([a-f0-9]{40}|[a-f0-9]{64})\n/.exec(commit.toString('utf8'))?.[1];
28
+ if (!root || root.length !== snapshot.commit.length)
29
+ throw new Conflict('Git commit proof has no valid root tree');
30
+ const trees = new Map();
31
+ let total = 0;
32
+ for (const entry of proof.trees) {
33
+ const bytes = decode(entry.base64, GIT_COMMIT_PROOF_LIMITS.treeBytes);
34
+ total += bytes.length;
35
+ if (total > GIT_COMMIT_PROOF_LIMITS.totalTreeBytes || trees.has(entry.objectId) ||
36
+ gitObjectId('tree', bytes, algorithm) !== entry.objectId)
37
+ throw new Conflict('Git tree object proof is duplicated, oversized or changed');
38
+ trees.set(entry.objectId, bytes);
39
+ }
40
+ assertSnapshotPaths(snapshot.files.map(file => file.path));
41
+ const declared = new Map(snapshot.files.map(file => [file.path, file]));
42
+ if (actual && actual.length !== declared.size)
43
+ throw new Conflict('Git proof needs the complete actual snapshot file closure');
44
+ const files = actual ? new Map(actual.map(file => {
45
+ const path = file.path;
46
+ const mode = file.mode;
47
+ const source = file.bytes;
48
+ const expected = declared.get(path);
49
+ if (!expected || mode !== expected.mode || !(source instanceof Uint8Array) || source.byteLength !== expected.bytes)
50
+ throw new Conflict('Actual snapshot bytes disagree with the declared file closure');
51
+ return [path, { path, mode, bytes: Buffer.from(source) }];
52
+ })) : null;
53
+ if (files && (files.size !== actual.length || files.size !== declared.size))
54
+ throw new Conflict('Git proof needs the complete actual snapshot file closure');
55
+ const visited = new Set();
56
+ const paths = new Set();
57
+ const pending = [{ id: root, prefix: '' }];
58
+ let nodes = 0;
59
+ while (pending.length) {
60
+ const selected = pending.pop();
61
+ const bytes = trees.get(selected.id);
62
+ if (!bytes)
63
+ throw new Conflict('Git tree object closure is incomplete');
64
+ if (!bytes.length)
65
+ throw new Conflict('Git snapshot cannot materialize empty Git directories');
66
+ visited.add(selected.id);
67
+ let offset = 0;
68
+ const names = new Set();
69
+ while (offset < bytes.length) {
70
+ if (++nodes > GIT_COMMIT_PROOF_LIMITS.nodes)
71
+ throw new Conflict('Git object proof exceeds the complete traversal bound');
72
+ const space = bytes.indexOf(32, offset);
73
+ const nul = bytes.indexOf(0, space + 1);
74
+ if (space < offset || nul <= space + 1 || nul + 1 + oidBytes > bytes.length)
75
+ throw new Conflict('Git tree object record is truncated');
76
+ const mode = bytes.subarray(offset, space).toString('ascii');
77
+ const name = new TextDecoder('utf-8', { fatal: true }).decode(bytes.subarray(space + 1, nul));
78
+ if (names.has(name) || name.includes('/') || name === '.' || name === '..' || !name)
79
+ throw new Conflict('Git tree object has an ambiguous path');
80
+ names.add(name);
81
+ const path = selected.prefix ? `${selected.prefix}/${name}` : name;
82
+ assertSnapshotPaths([path]);
83
+ const id = bytes.subarray(nul + 1, nul + 1 + oidBytes).toString('hex');
84
+ offset = nul + 1 + oidBytes;
85
+ if (mode === '40000') {
86
+ pending.push({ id, prefix: path });
87
+ continue;
88
+ }
89
+ const entry = declared.get(path);
90
+ if (!['100644', '100755'].includes(mode) || !entry || entry.mode !== mode || entry.objectId !== id || paths.has(path))
91
+ throw new Conflict('Git object tree differs from the declared snapshot files');
92
+ paths.add(path);
93
+ if (files) {
94
+ const file = files.get(path);
95
+ if (!file || file.mode !== entry.mode || file.bytes.length !== entry.bytes || !sameDigest(digestOfBytes(file.bytes), entry.digest) ||
96
+ gitObjectId('blob', file.bytes, algorithm) !== id)
97
+ throw new Conflict('Actual snapshot bytes disagree with the Git commit tree');
98
+ }
99
+ }
100
+ }
101
+ if (paths.size !== declared.size || visited.size !== trees.size)
102
+ throw new Conflict('Git object proof has omitted files or unrelated trees');
103
+ return { algorithm, commit: observedCommit, tree: root, proofDigest: digestOfValue(proof) };
104
+ }
105
+ /** Structural object/manifest links only: cannot certify SHA-256 file bytes without reading them. */
106
+ export function verifyGitSnapshotProofMetadata(snapshot) {
107
+ return { verification: 'object_links_only', binding: verify(snapshot) };
108
+ }
109
+ /** Hashes every actual file through its Git blob identity and the full tree/commit object closure. */
110
+ export function verifyGitSnapshotCommit(snapshot, files) {
111
+ if (!Array.isArray(files))
112
+ throw new Conflict('actual Git source files are required');
113
+ return { ...verify(snapshot, files), verification: 'actual_file_bytes' };
114
+ }
115
+ //# sourceMappingURL=gitObjectProof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitObjectProof.js","sourceRoot":"","sources":["../../src/source/gitObjectProof.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ /** Shared Git/transport path rules; prevent aliases before any filesystem write. */
2
+ export declare function assertSnapshotPaths(paths: string[]): void;
@@ -0,0 +1,24 @@
1
+ import { RepositoryPath } from "../protocol/primitives.js";
2
+ import { Conflict } from "../core/errors.js";
3
+ /** Shared Git/transport path rules; prevent aliases before any filesystem write. */
4
+ export function assertSnapshotPaths(paths) {
5
+ const seen = new Set();
6
+ const spellings = new Map();
7
+ for (const raw of paths) {
8
+ const path = RepositoryPath.parse(raw);
9
+ const canonical = path.normalize('NFC').toLowerCase();
10
+ const parts = path.split('/');
11
+ if (seen.has(canonical) || parts.some(part => /^(?:\.git|con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(part) || /[. ]$/.test(part) || /[<>"|?*]/.test(part))) {
12
+ throw new Conflict('Git snapshot path is not portable or is duplicated');
13
+ }
14
+ seen.add(canonical);
15
+ for (let length = 1; length <= parts.length; length++) {
16
+ const prefix = parts.slice(0, length).join('/');
17
+ const key = prefix.normalize('NFC').toLowerCase();
18
+ if (spellings.has(key) && spellings.get(key) !== prefix)
19
+ throw new Conflict('Git snapshot contains aliased directory names');
20
+ spellings.set(key, prefix);
21
+ }
22
+ }
23
+ }
24
+ //# sourceMappingURL=snapshotPaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshotPaths.js","sourceRoot":"","sources":["../../src/source/snapshotPaths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,oFAAoF;AACpF,MAAM,UAAU,mBAAmB,CAAC,KAAe;IACjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAAC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5E,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,uDAAuD,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACjK,MAAM,IAAI,QAAQ,CAAC,oDAAoD,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACpB,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;YACtD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAAC,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YACnG,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,MAAM;gBAAE,MAAM,IAAI,QAAQ,CAAC,+CAA+C,CAAC,CAAC;YAC7H,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { GitSourceSnapshot, type GitCommitObservation } from '../protocol/schemas/gitSources.ts';
2
+ export type SnapshotFile = {
3
+ path: string;
4
+ mode: '100644' | '100755';
5
+ bytes: Buffer;
6
+ };
7
+ export declare function readGitSnapshotManifest(path: string): GitSourceSnapshot;
8
+ /** Read every pinned regular file, ignoring untracked inputs that will never enter the launch copy. */
9
+ export declare function readGitSnapshotTree(input: unknown, sourceRoot: string): SnapshotFile[];
10
+ export declare function readGitSnapshotSource(input: unknown, sourceRoot: string): {
11
+ files: SnapshotFile[];
12
+ gitSource: GitCommitObservation | null;
13
+ };
14
+ /** Exclusively create a private tree; a failed write removes only this owned directory. */
15
+ export declare function writeGitSnapshotTree(files: SnapshotFile[], destination: string): void;
@@ -0,0 +1,79 @@
1
+ import { lstatSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { GitSourceSnapshot, GIT_SNAPSHOT_LIMITS } from "../protocol/schemas/gitSources.js";
4
+ import { digestOfBytes, sameDigest, verifySelfDigest } from "../protocol/canonical.js";
5
+ import { Conflict } from "../core/errors.js";
6
+ import { readBoundedFile } from "../core/boundedFile.js";
7
+ import { assertSnapshotPaths } from "./snapshotPaths.js";
8
+ import { verifyGitSnapshotCommit, verifyGitSnapshotProofMetadata } from "./gitObjectProof.js";
9
+ export function readGitSnapshotManifest(path) {
10
+ let snapshot;
11
+ try {
12
+ snapshot = GitSourceSnapshot.parse(JSON.parse(readBoundedFile(path, 32 * 1024 * 1024).toString('utf8')));
13
+ }
14
+ catch {
15
+ throw new Conflict('Choose a bounded, regular source snapshot manifest with valid metadata');
16
+ }
17
+ if (!verifySelfDigest(snapshot))
18
+ throw new Conflict('Git snapshot manifest digest mismatch');
19
+ if (snapshot.commitProof)
20
+ verifyGitSnapshotProofMetadata(snapshot);
21
+ return snapshot;
22
+ }
23
+ /** Read every pinned regular file, ignoring untracked inputs that will never enter the launch copy. */
24
+ export function readGitSnapshotTree(input, sourceRoot) {
25
+ return readGitSnapshotSource(input, sourceRoot).files;
26
+ }
27
+ export function readGitSnapshotSource(input, sourceRoot) {
28
+ const snapshot = GitSourceSnapshot.parse(input);
29
+ if (!verifySelfDigest(snapshot))
30
+ throw new Conflict('Git snapshot manifest digest mismatch');
31
+ assertSnapshotPaths(snapshot.files.map(file => file.path));
32
+ if (snapshot.files.reduce((sum, file) => sum + file.bytes, 0) > GIT_SNAPSHOT_LIMITS.totalBytes)
33
+ throw new Conflict('Git snapshot exceeds the total byte bound');
34
+ const root = resolve(sourceRoot);
35
+ const checked = new Set();
36
+ const directory = (path) => {
37
+ if (checked.has(path))
38
+ return;
39
+ const stat = lstatSync(path);
40
+ if (stat.isSymbolicLink() || !stat.isDirectory())
41
+ throw new Conflict('Git snapshot refuses linked or non-directory parents');
42
+ checked.add(path);
43
+ };
44
+ directory(root);
45
+ const files = snapshot.files.map(file => {
46
+ let parent = root;
47
+ for (const segment of file.path.split('/').slice(0, -1)) {
48
+ parent = join(parent, segment);
49
+ directory(parent);
50
+ }
51
+ const bytes = readBoundedFile(join(root, file.path), file.bytes, file.bytes);
52
+ if (!sameDigest(digestOfBytes(bytes), file.digest))
53
+ throw new Conflict('Git snapshot file digest mismatch');
54
+ return { path: file.path, mode: file.mode, bytes };
55
+ });
56
+ return { files, gitSource: snapshot.commitProof ? verifyGitSnapshotCommit(snapshot, files) : null };
57
+ }
58
+ /** Exclusively create a private tree; a failed write removes only this owned directory. */
59
+ export function writeGitSnapshotTree(files, destination) {
60
+ if (!files.length || files.length > GIT_SNAPSHOT_LIMITS.files || files.some(file => file.bytes.length > GIT_SNAPSHOT_LIMITS.fileBytes) ||
61
+ files.reduce((sum, file) => sum + file.bytes.length, 0) > GIT_SNAPSHOT_LIMITS.totalBytes)
62
+ throw new Conflict('Git snapshot tree exceeds complete-coverage bounds');
63
+ assertSnapshotPaths(files.map(file => file.path));
64
+ mkdirSync(destination, { mode: 0o700 });
65
+ try {
66
+ for (const file of files) {
67
+ const path = join(destination, file.path);
68
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
69
+ writeFileSync(path, file.bytes, { flag: 'wx', mode: file.mode === '100755' ? 0o700 : 0o600 });
70
+ if (!readBoundedFile(path, file.bytes.length, file.bytes.length).equals(file.bytes))
71
+ throw new Conflict('snapshot bytes changed while writing');
72
+ }
73
+ }
74
+ catch (error) {
75
+ rmSync(destination, { recursive: true, force: true });
76
+ throw error;
77
+ }
78
+ }
79
+ //# sourceMappingURL=snapshotTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshotTree.js","sourceRoot":"","sources":["../../src/source/snapshotTree.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ # Agent and CI command guide
2
+
3
+ Use the installed binary through `npx --no-install tracegrove` so CI never fetches an unrelated package. Pass `--json` and check both exit status and report fields; do not classify a run from prose alone.
4
+
5
+ | Command | Effect | Result |
6
+ | --- | --- | --- |
7
+ | `status --json` | Reads the current project and run state | `tracegrove.status/v1` and ordered `next` commands |
8
+ | `discover --json` | Compares discovered routes and authored flows | Coverage suggestions, no app launch |
9
+ | `check --json` | Compiles authoring files | `ok` and located issues; may evaluate trusted TypeScript authoring modules |
10
+ | `doctor --dir . --json` | Checks the native plan without app launch | `tracegrove.doctor/v1`, `checks`, `errors`, `blocked`, `execution: not_started` |
11
+ | `test --json` | Starts the selected app and executes scenarios | `tracegrove.run-summary/v1`, `outcome`, `cases`, `blockers`, `runDir`, `bundleVerified` |
12
+ | `verify-bundle --bundle <dir> --json` | Checks existing evidence | `ok`, `problems`, `outcome`, `receipts`; no app launch |
13
+ | `draft --intent '<goal>'` | Starts a coding agent to edit drafts | Review changed files and compile/run afterward |
14
+ | `heal --dry-run` | Runs and diagnoses the suite | Findings without retained agent edits |
15
+ | `heal` | May retain bounded setup/flow edits | `tracegrove.heal/v1`; inspect saved diff and backups |
16
+
17
+ Exit codes: 0 clean/passed; 1 assertion failure; 2 blocked/inconclusive; 3 infrastructure failure; 4 cancellation. A top-level JSON error uses `tracegrove.cli-error/v1`, with a public class, bounded reason codes and recovery actions. Normal reports and artifacts may contain application data; protect them with your usual workspace access controls. `--json=false` selects prose errors, while `--jsonl` keeps its event stream.
18
+
19
+ Agent drafting uses the configured Claude Code or Codex CLI and its existing permissions. Tracegrove's prompt is not a filesystem sandbox. The default models are explicit in the adapter, and one Claude model-alias retry is recorded when used. A requested `maxBudgetUsd` is supported by the Claude adapter; the Codex adapter blocks it rather than ignoring a spending limit. Commit or stash work before drafting or healing, review proposed changes, and preserve the original failed run. A passing compiled flow is not proof of intended behavior.
20
+
21
+ The same short flows compile into the strict `workflow.*/v1` corpus. The browser, native jobs, MCP, evidence and recovery guides are shipped in this package. General portable profiles are reference-only; they cannot be passed to the present CLI as an executable target.
@@ -0,0 +1,146 @@
1
+ # Local browser driver
2
+
3
+ `BrowserDriver` runs real Chromium in a fresh, nonpersistent context. It does
4
+ not connect to an existing browser profile. Install its pinned browser before
5
+ running browser tests or using the driver in a project with Tracegrove installed:
6
+
7
+ ```sh
8
+ npx --no-install playwright install chromium
9
+ ```
10
+
11
+ Linux CI uses `playwright install --with-deps chromium` to install the browser
12
+ and its system libraries.
13
+
14
+ Run the packaged browser sample through the same low-level CLI as an API case,
15
+ from a directory where Tracegrove is installed:
16
+
17
+ ```sh
18
+ npx --no-install tracegrove sample-config --sample notes-browser --output "$PWD/notes-browser"
19
+ npx --no-install tracegrove plan --config "$PWD/notes-browser/verification/workflow.yaml" --output "$PWD/notes-browser-request.json"
20
+ npx --no-install tracegrove run --request "$PWD/notes-browser-request.json"
21
+ ```
22
+
23
+ Use fresh output paths: sample generation refuses to overwrite a project. The
24
+ run prints its execution ID and bundle path. Pass that path to
25
+ `npx --no-install tracegrove verify-bundle --bundle <path>` for independent verification.
26
+ The sample shares its real app, personas, fixture recipes, and cleanup with
27
+ `notes-api`; only its browser runner, binding, and case differ.
28
+
29
+ The exported `BrowserCommand`, `BrowserLocator`, and `BrowserObservation` Zod
30
+ schemas also have generated JSON Schemas. Commands navigate, click, fill, or
31
+ read visible text. Locators use exact roles, labels, or test IDs. Arbitrary
32
+ scripts and selectors are not accepted. Observations contain browser facts;
33
+ the driver does not decide whether a scenario passes.
34
+
35
+ Each operation has a deadline. Cancellation or a failed mutating operation closes the
36
+ context and browser before returning. Calls on one driver are serialized by
37
+ rejecting concurrent operations. Closing is idempotent. A closure acknowledgement
38
+ does not prove cleanup of an operating-system process tree after controller death.
39
+
40
+ Page requests must stay on the admitted origin. Chromium's CDP Fetch interception
41
+ checks every redirect hop while retaining native response streaming. Service
42
+ workers and WebSockets are disabled, and extra pages are closed. This is page
43
+ request filtering, not an operating system network sandbox; arbitrary application
44
+ code, workers, and popups require a host network boundary for full confinement.
45
+
46
+ `collectVideo()` closes the browser, flushes the WebM recording, and reads at
47
+ most 32 MiB from a regular file without following a final symlink. `dispose()`
48
+ removes the private temporary recording directory. Recordings and DOM text are
49
+ raw and may contain application data; callers must apply their evidence access
50
+ and retention policy before storing or sharing them. This driver does not issue
51
+ credentials or copy an owner's authenticated session.
52
+
53
+ The real-browser tests submit a local form, check an independent server receipt,
54
+ read the resulting DOM, and inspect the flushed recording. Separate tests cover
55
+ cross-origin paths, page requests and redirects, cancellation, timeout, invalid
56
+ commands, and expired startup.
57
+
58
+ The core runner profile accepts `adapter: browser`. A typed `ui.navigate` step
59
+ has a path; `ui.action` carries a click or fill command; `ui.observe` carries a
60
+ semantic target, predicate, and poll interval. DOM predicates address
61
+ `browser.text` or `browser.url` through the `browser.observation/1` oracle.
62
+ HTTP steps and fixtures can run in the same case for independent readback.
63
+
64
+ Each poll counts against `maxBrowserActions`. Case method and resource-prefix
65
+ rules filter page requests; read-only cases allow only GET and HEAD. Persona
66
+ viewport, locale, timezone, and reduced motion are passed to the browser. Pointer
67
+ activation uses clicks, keyboard activation uses focus with Enter or Space for toggles, and touch
68
+ activation uses taps. Host-issued bearer credentials are added only to admitted
69
+ page requests, never expanded into filled values or recorded commands.
70
+ Network events record methods, paths, and response statuses without request
71
+ headers or query strings. Recording more than 512 network events invalidates
72
+ collection. Required traces and declared redaction policies remain blocked.
73
+
74
+ Before closing a successful session, collection completes a layout-aware
75
+ screenshot, then requests another capture and waits for a frame presented after
76
+ the first capture through Playwright’s public screencast callback. Only then
77
+ does it stop and flush the encoder. A fresh frame delivered during the first
78
+ capture can still contain older pixels. This uses the cleanup deadline, not an
79
+ arbitrary recording delay. Collection failures name their capture, frame, or
80
+ flush phase without exposing page text or Playwright diagnostics.
81
+ The controller seals the recording bytes into the portable bundle and records
82
+ browser duration and artifact bytes. Verification reproduces the frozen runner
83
+ capabilities, independently reduces browser assertions, and checks video hashes
84
+ and byte counts. A required recording cannot be satisfied by an event log alone.
85
+
86
+ The integrated native tests cover pointer, keyboard, and 375px simulated touch,
87
+ combining an authenticated UI, DOM observation,
88
+ independent API assertions, fixture cleanup, video capture, and portable bundle
89
+ verification. A decoded-frame test checks the recorded terminal visual state.
90
+ This proves local behavior. Hosted admission, staging personas, and
91
+ controller-death browser cleanup remain open; no production qualification is claimed.
92
+
93
+ ## Short flows and Grove
94
+
95
+ The packaged sample also includes a short browser flow. From the same installed directory:
96
+
97
+ ```sh
98
+ npx --no-install tracegrove test --config "$PWD/notes-browser/tracegrove.config.yaml" --grep notes.browser
99
+ npx --no-install tracegrove ui --dir "$PWD/notes-browser"
100
+ ```
101
+
102
+ Open the printed loopback address and select the browser scenario. Its step
103
+ panel shows expected and observed text plus native recording controls. The
104
+ player supports keyboard playback and byte-range seeking, and preserves its
105
+ position when changing steps. Each media request verifies one immutable bundle
106
+ snapshot and binds the digest to that run and scenario. Corrupt, unbound, or
107
+ symlinked recordings are refused.
108
+
109
+ Browser commands reuse the core command and locator schemas:
110
+
111
+ ```yaml
112
+ title: Show the seeded note
113
+ given: { existing: existing-note }
114
+ browser:
115
+ allowPaths: [/ui, /notes]
116
+ allowMethods: [GET, HEAD]
117
+ steps:
118
+ - browser: { kind: navigate, path: /ui }
119
+ expect: { status: 200 }
120
+ - browser: { kind: click, target: { by: role, role: button, name: Refresh } }
121
+ - browser: { kind: read, target: { by: testId, name: notes } }
122
+ expect: { text: Existing note }
123
+ ```
124
+
125
+ `fill` accepts a semantic `target` and string `value`. Browser reads require
126
+ `expect.text` and poll until it holds. Click/fill steps assert completion; add a
127
+ DOM read or independent API readback to establish the effect. Browser steps use
128
+ the default persona, and browser flows require a recording. Set `maxActions`
129
+ and `maxArtifactBytes` inside the flow's `browser` block to tune their budgets.
130
+ Its allowed paths and methods combine with those derived from HTTP steps and
131
+ fixtures into the flow's effect envelope.
132
+
133
+ Persona configuration accepts optional `viewport`, `inputMode`, `locale`,
134
+ `timezone`, and `reducedMotion` fields alongside `subject`. Simulated touch
135
+ does not qualify a physical mobile device. Required traces, executable
136
+ redaction policies, and non-browser native surfaces remain unsupported.
137
+
138
+ Read-only observation timeouts preserve the browser for final evidence collection.
139
+ Browser polling retains its last completed observation at the deadline so an
140
+ unmet expectation keeps its observed value and remains an assertion failure.
141
+ Cancellation and actual browser errors still propagate; failed mutating actions
142
+ close the browser to revoke late effects.
143
+
144
+ Capture failures remain infrastructure failures with no accepted video. The sealed `browser.failed` event includes a bounded driver `cause` and `phase` (`capture`, `frame`, or `flush`) when available; unknown exceptions expose neither their message nor arbitrary fields.
145
+
146
+ Recordings use the persona viewport at native size, rounded up to even dimensions for VP9 (at most one padding pixel per edge), instead of scaling mobile content into a desktop canvas. Fresh-frame and encoder-flush checks remain required.
@@ -0,0 +1,13 @@
1
+ # Test an existing app
2
+
3
+ Start with the [npm README](https://www.npmjs.com/package/tracegrove) and its synthetic Notes sample. In your own repository, install `tracegrove@0.3.1` as a development dependency, then run `npx --no-install tracegrove init`. Review the generated config and flow before running them.
4
+
5
+ `tracegrove.config.yaml` names a `project`, an `app` adapter (`node`, `fastapi`, or `django`), its entry point and health route, source paths to digest, and test personas. Put flows at `tracegrove/<area>/<behavior>.flow.yaml`; their case IDs use `<area>.<behavior>`. A flow contains named steps with methods, paths, expected statuses and optional independent read requests (`observe: true`). Put reusable fixtures at `tracegrove/fixtures/<name>.fixture.yaml`. Steps can `save` a response value and refer to it later as `{name}`; inspect the generated starter flow or packaged Notes sample for a complete example. `npx --no-install tracegrove check --json` compiles these files without starting the app. `doctor --dir . --json` checks the selected native plan; it can probe an interpreter version but does not run your app.
6
+
7
+ The local adapter assigns a loopback port and owned data directory. Your app must consume the injected port and `TRACEGROVE_DATA_DIR` and recognize the per-run synthetic `TRACEGROVE_TOKENS` in test mode. Keep the test token path disabled in production. The Django adapter invokes migration before start: verify that Django's configured database lives in the injected data directory. Do not point a test run at a shared or production database.
8
+
9
+ Run `npx --no-install tracegrove test --json`. A passing JSON summary names `runDir`, `executionId`, per-case outcomes, and `bundleVerified`. The run folder contains readable summaries, JUnit and `bundle/`. Run `npx --no-install tracegrove verify-bundle --bundle <runDir>/bundle --json` to independently check the stored files and verdict. Verification does not rerun your app or establish who produced an unsigned bundle.
10
+
11
+ If a prerequisite blocks, read `blockers[]` and the suggested recovery before retrying. A nonzero assertion result is a finding about the app or test, not a setup failure. For a single interrupt, wait for the owned cleanup and inspect its receipts. Keep the run folder until you have exported any evidence you need. `recovery-status` reads an existing checkpoint but cannot clear ownership or restart work.
12
+
13
+ Browser tests need the pinned Playwright Chromium installed through your environment's approved dependency path. The browser and native job guides are in this npm package. External staging, a general cloud runner and arbitrary shell launchers are not available through the current CLI.
@@ -0,0 +1,100 @@
1
+ # Git object checks for pinned snapshots
2
+
3
+ New `materializeGitSnapshot` outputs include the raw commit/tree object proof and each
4
+ file's Git blob identity. The resolver reads immutable Git objects with its existing
5
+ restricted environment; materialization verifies the complete proof before creating
6
+ an output directory. No fetch, checkout, helper, signature verification or application
7
+ execution is added.
8
+
9
+ `verifyGitSnapshotCommit(snapshot, files)` independently hashes every actual file as a
10
+ Git blob, checks paths and modes against the complete raw tree closure, and hashes that
11
+ tree/commit chain against the selected commit. Both SHA-1 and SHA-256 object formats
12
+ are supported. Its observation has `verification: actual_file_bytes` and binds the
13
+ computed commit, root tree, object algorithm and proof digest. It needs captured bytes
14
+ and proof objects and captures each supplied file buffer once before both hash checks,
15
+ so it continues to work after the Git store and source directory
16
+ are unavailable.
17
+
18
+ ```ts
19
+ const files = readGitSnapshotTree(snapshot, sourceRoot);
20
+ const observed = verifyGitSnapshotCommit(snapshot, files);
21
+ ```
22
+
23
+ `verifyGitSnapshotProofMetadata(snapshot)` checks object/manifest links without reading
24
+ source files. Its distinct `verification: object_links_only` result is not a runtime
25
+ observation. A resealed manifest could pair a new SHA-256 file checksum with an old Git
26
+ blob ID; metadata alone cannot prove that association. Actual-file verification rejects
27
+ it even when the new checksums and manifest seal agree.
28
+
29
+ ## Launch and saved evidence
30
+
31
+ Snapshot reads now verify object proofs when present. The trusted supervisor copies the
32
+ pinned files into its owned tree and verifies the private copy again before launching
33
+ the application. It sends the computed Git observation over its existing IPC channel.
34
+ The parent refuses missing/mismatched observations for proof-bearing snapshots, and
35
+ the sealed identity attestation records the observed fields. The application cannot
36
+ establish this observation through its health response.
37
+
38
+ Saved-bundle verification checks the proof's metadata, snapshot ref, component file
39
+ closure and recorded Git observation after the private launch directory is removed.
40
+ It does not regain the full source bytes from that observation. Authenticating the host
41
+ and its runtime file measurements remains the issuer's job. Existing proof-less snapshots
42
+ remain component-only and receive no Git observation. Repository binding is a separate,
43
+ explicit option described below; remote ownership and dependency-install provenance are
44
+ not inferred from Git object hashes.
45
+
46
+ ## Bind a repository role
47
+
48
+ Materialization also saves a sealed `resolution.json` next to `snapshot.json`. To connect
49
+ the selected resolver head to a repository role:
50
+
51
+ ```sh
52
+ tracegrove test --config ./head/source/tracegrove.config.yaml \
53
+ --source-snapshot ./head/snapshot.json --source-repository-role application
54
+ ```
55
+
56
+ The same flags work with `compile`. Compilation verifies the complete source tree,
57
+ checks the sealed resolution sidecar against the snapshot, and emits `SourceSelection`,
58
+ the original `RevisionMatrix`, and snapshot documents in the normal frozen corpus. The
59
+ planner binds that selection to the request and every cell. Existing component-only
60
+ snapshot runs do not change unless a repository role is provided. Old snapshots can
61
+ be rematerialized to obtain a sidecar; no network access is required.
62
+
63
+ The descriptor uses `urn:tracegrove:git-object:<algorithm>:<commit>` and origin
64
+ `snapshot_bundle`. It identifies the actual Git object, not ownership of a GitHub URL.
65
+ `requestedRef` in the target is the immutable commit; `requestedExpression` in source
66
+ selection retains the resolver's original expression. Both Git SHA-1 and SHA-256 work.
67
+ `dirty: false` describes the supervisor's complete private pinned copy, not the checkout.
68
+
69
+ Lockfile identity v1 hashes a sorted manifest of complete pinned path, mode and SHA-256
70
+ digest for `package-lock.json`, `npm-shrinkwrap.json`, `pnpm-lock.yaml`, `yarn.lock`,
71
+ `bun.lock`, `bun.lockb`, `uv.lock`, `poetry.lock`, `Pipfile.lock`, `Cargo.lock`, `Gemfile.lock`,
72
+ `composer.lock` and `go.sum` at any depth. No recognized lockfile produces an explicit
73
+ empty-manifest digest. This identifies pinned lockfiles; it does not establish which
74
+ dependencies were installed.
75
+
76
+ Repository observation is derived only after the supervisor's `actual_file_bytes`
77
+ observation matches the proof. Planning, execution preflight, saved-bundle checks and
78
+ revision assessment share the frozen source-closure checks. They reject different
79
+ roles, remote URLs, lockfile identities, missing closure documents and source plans
80
+ whose reviewed matrix differs. Base snapshots and multi-repository resolution sidecars
81
+ cannot use this single-head binding; companion repositories are never silently dropped.
82
+ They remain available for component-only runs until a complete multi-host binding exists.
83
+
84
+ Two independent native campaigns can now meet a revision-level local qualification
85
+ policy and activate through the durable scenario store. The tests simulate issuer and
86
+ physical-lease authority explicitly. This does not establish hosted issuer trust, live
87
+ staging coverage, remote repository ownership, or a reviewed-source promotion by itself.
88
+
89
+ Proofs fail on missing or duplicate trees, unrelated objects, malformed/canonicalization
90
+ errors, changed file/object/mode bindings, incomplete actual file coverage and unsupported
91
+ tree entries. Symlinks, submodules, empty Git directories and nonportable paths cannot
92
+ be silently omitted. Prototype bounds are 1 MiB per commit, 4 MiB per tree, 8 MiB total
93
+ tree bytes, 8,192 distinct trees and 20,000 traversal entries, in addition to the existing
94
+ 10,000-file/32 MiB snapshot bound. Unsupported coverage blocks instead of truncating it.
95
+
96
+ Tests use real SHA-1/SHA-256 repositories, binary files and reused subtrees; remove the
97
+ Git/source paths before pure verification; and exercise resealed forged commits, trees,
98
+ files and runtime attestations. Native pinned launches and independent bundle reads
99
+ verify the observation path. These are local integrity/runtime facts, not hosted issuer
100
+ authentication, author identity, a signed release or remote repository ownership.
@@ -0,0 +1,55 @@
1
+ # Local acquisition recovery gate
2
+
3
+ The executable local path records ownership in the existing fsynced, single-writer ProjectionLedger. Each new execution initializes `ownership:<executionId>` with its scope, immutable request digest, campaign, attempt and generation. Host and fixture reservations precede workspace acquisition/host startup or application-API create. Observed physical IDs are acknowledged before readback/steps, and cleanup moves through pending to removed only after the existing trusted host stop or registered deletion plus absence readback confirms it. Internal typed host and fixture acknowledgements remain separate: a fixture named `host.process` or `host.workspace` cannot borrow a successful host acknowledgement from the legacy public display-key arrays.
4
+
5
+ No credentials or fixture request/cleanup arguments are added to this inventory. Physical resource IDs and native workspace/process identities remain private operational metadata in the existing private ledger. The owner must protect that directory.
6
+
7
+ After controller interruption, redelivery of the same frozen idempotency key checks the prior inventory before admitting a new attempt. Reserved, observed or cleanup-pending entries block with `ownership_reconciliation_required`. Legacy interrupted attempts without inventory block with `ownership_inventory_missing`. Wrong request/scope/attempt/generation cannot discharge the inventory. Cleanly recorded removed inventory permits a fresh attempt through the existing admission path; an empty initialized inventory means no acquisition was reserved. Existing finalized redelivery returns its existing result without replaying effects.
8
+
9
+ This is deliberately a recovery gate, not an automatic janitor. A controller crash after a real acquisition but before its acknowledgement leaves a durable reservation even if the native supervisor subsequently cleans up. No cleanup acknowledgement is invented from supervisor exit, workspace disappearance, an old PID or elapsed lease time. There is no automatic cross-process takeover/deletion or credential reconstruction, and no operator command to discharge unresolved inventory in this slice. Such cases remain blocked pending a separately reviewed reconciliation path with independent ownership and cleanup evidence. Do not edit ledger records to bypass the gate.
10
+
11
+ The actual local supervisor still handles ordinary controller disconnect and cleanup. A persistence failure must not prevent best-effort cleanup of resources already known in memory; it does prevent a successful durable completion acknowledgement. A process/power loss during the ledger write inherits the ledger's existing uncertain-write and corrupt-tail behavior.
12
+
13
+ Tests exercise real native acquisition and application-API fixture create in subprocesses, kill the controller before the executor receives their acknowledgements, reopen the actual persisted ledger, and prove redelivery performs no second acquisition. Other tests exercise native/sample cleanup, reservation/acknowledgement ordering, invalid cleanup transitions and foreign binding rejection. They do not qualify a remote provider, shared-resource fencing, distributed leases, machine power-loss recovery, or a durable supervisor-to-controller cleanup journal. Atomic artifact publication is a separate milestone.
14
+
15
+ ## Read-only recovery inspection
16
+
17
+ ```sh
18
+ tracegrove recovery-status --state-dir <owned-state> --execution <execution-id> --json
19
+ ```
20
+
21
+ This command reads an existing checkpoint without opening `LocalLedger` for writing. It creates
22
+ no directories, locks or credentials, does not contact a controller, and never probes or kills a
23
+ PID. It does not append interrupted/finalized transitions, delete resources, discharge ownership,
24
+ sync a commit, resume a run or admit an acquisition. The existing execution path remains the
25
+ authority for all recovery and admission decisions.
26
+
27
+ The strict `tracegrove.recovery-status/v1` report includes a journal sequence/content digest,
28
+ lock presence (not process liveness), recorded phase, counts by resource kind/state, bounded
29
+ evidence status, static recovery guidance and an optional verified **historical** outcome.
30
+ It omits raw journal records, resource keys, physical IDs, PIDs, paths, controller tokens,
31
+ cleanup arguments and candidate diagnostics. The checkpoint digest identifies selected local
32
+ bytes; it is not a signature or an admission token. The local process scope and filesystem owner
33
+ must already be authorized to inspect the private state directory.
34
+
35
+ The journal uses the same schema/sequence/version parser as the existing writer. Inspection is
36
+ bounded to 16 MiB and 100,000 records; oversized, nonregular, linked, malformed or partial inputs
37
+ fail closed. The directory identity, journal bytes and lock fingerprint are checked before and
38
+ after capture and again after evidence inspection. Concurrent changes return an explicit changed
39
+ checkpoint rather than a ready result. This is a checkpoint observation, not a promise that a
40
+ live writer cannot change state after the command returns or confinement against hostile parent
41
+ replacement during filesystem operations.
42
+
43
+ Ownership counts describe the journal's recorded states, not newly observed absence. The
44
+ committed-bundle path reuses the executor's exact ledger/request/selection/scope/attempt/generation/
45
+ receipt binding checks and full bounded bundle reduction. Exit 0 means either matching finalized
46
+ historical evidence or a recorded interrupted commit available for normal readback; exit 2 means
47
+ another state or unavailable/invalid evidence. Every report says `actionAuthority: none`,
48
+ `execution: not_started_by_inspection` and `verificationVerdict: not_evaluated`. Unknown cleanup
49
+ remains unresolved even when a workspace disappeared or a controller exited. A stale lock does
50
+ not itself record interruption; only normal trusted writer reconciliation can do that.
51
+
52
+ Automatic janitor/discharge, durable supervisor acknowledgements and provider recovery remain
53
+ separate gates. The supervisor's current `host.cleaned` message is ephemeral IPC. Adding cleanup
54
+ authority requires bound ownership/cleanup evidence admitted by the existing exclusive ledger
55
+ writer; this status command provides neither that evidence nor a new journal.