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,29 @@
1
+ schemaVersion: workflow.seed-recipe/v1
2
+ ref: { id: example.recipe.existing-note, revision: "1" }
3
+ intent: One pre-existing note owned by the persona that the case must leave intact.
4
+ modelCatalogRef: null
5
+ actionRegistryRef: { $file: ../actions/notes.registry.yaml }
6
+ entities:
7
+ - entityKey: existing_note
8
+ modelId: note
9
+ actionId: notes.create/v1
10
+ dependsOn: []
11
+ traits: []
12
+ values:
13
+ title: { kind: literal, value: Existing note }
14
+ body: { kind: generator, generatorId: words, args: { count: 6 } }
15
+ outputNames: [noteId]
16
+ readback:
17
+ actionId: notes.read/v1
18
+ predicate:
19
+ kind: all
20
+ predicates:
21
+ - { kind: status_equals, value: 200 }
22
+ - { kind: json_path_equals, path: body.note.title, value: Existing note }
23
+ cleanup:
24
+ actionId: notes.delete/v1
25
+ absenceReadback: { actionId: notes.read/v1, expectStatus: 404 }
26
+ relationBindings: []
27
+ cleanupStrategy: reverse_dependency_order
28
+ lifecyclePolicy: application_api
29
+ generation: { logicalSeed: notes-existing-note-1, generatorVersion: "1", locale: en-US, timezone: UTC, logicalClock: "2026-10-10T00:00:00Z" }
@@ -0,0 +1,27 @@
1
+ schemaVersion: workflow.host-plan/v1
2
+ ref: { id: example.host.local-process, revision: "1" }
3
+ placement: local
4
+ adapter: local_process
5
+ launch:
6
+ componentId: notes-api
7
+ command: node
8
+ args: [app/app.mjs]
9
+ cwd: ..
10
+ env: { NOTES_BUILD: sample }
11
+ portEnv: PORT
12
+ dataDirEnv: NOTES_DIR
13
+ credentialsEnv: NOTES_TOKENS
14
+ readiness: { path: /health, timeoutMs: 5000 }
15
+ identitySourceFiles: [app/app.mjs, app/http.mjs]
16
+ issuedCredentials:
17
+ - { name: owner_token, subject: alice }
18
+ - { name: intruder_token, subject: bob }
19
+ mockResponsesRef: null
20
+ transportPolicy: in_process
21
+ isolationPolicy: fresh_directory_and_port
22
+ networkRules: [loopback_only]
23
+ requestedResources: { cpu: 1, memoryMb: 128, diskMb: 16 }
24
+ requiredCapabilities: [shell, network_origin:loopback, confirmed_cancel, artifact_delivery]
25
+ captureRequirements: []
26
+ sessionLifetimeMs: 120000
27
+ cleanupReserveMs: 10000
@@ -0,0 +1,14 @@
1
+ schemaVersion: workflow.host-plan/v1
2
+ ref: { id: example.host.mock-loopback, revision: "1" }
3
+ placement: local
4
+ adapter: mock_loopback
5
+ launch: null
6
+ mockResponsesRef: { $file: ../mocks/notes.responses.yaml }
7
+ transportPolicy: in_process
8
+ isolationPolicy: fresh_directory_and_port
9
+ networkRules: [loopback_only]
10
+ requestedResources: { cpu: 1, memoryMb: 64, diskMb: 1 }
11
+ requiredCapabilities: [network_origin:loopback, confirmed_cancel, artifact_delivery]
12
+ captureRequirements: []
13
+ sessionLifetimeMs: 60000
14
+ cleanupReserveMs: 5000
@@ -0,0 +1,5 @@
1
+ schemaVersion: workflow.mock-responses/v1
2
+ ref: { id: example.mock.notes, revision: "1" }
3
+ routes:
4
+ - { method: POST, path: /notes, status: 201, body: { note: { id: 00000000-0000-4000-8000-000000000001, title: Stub note, body: stub } }, requireBearer: true }
5
+ - { method: GET, path: "/notes/{id}", status: 200, body: { note: { id: 00000000-0000-4000-8000-000000000001, title: Stub note, body: stub } }, requireBearer: true }
@@ -0,0 +1,16 @@
1
+ schemaVersion: workflow.persona/v1
2
+ ref: { id: example.persona.owner, revision: "1" }
3
+ traits: [new_user]
4
+ accountBindingRef: null
5
+ roleScopes: [notes.owner]
6
+ stateRecipeRef: null
7
+ dataVolumeRecipeRef: null
8
+ entitlementRef: null
9
+ connectorStateRef: null
10
+ authRecipeRef: { $file: ../auth/host-issued-owner.yaml }
11
+ locale: en-US
12
+ timezone: UTC
13
+ viewport: { width: 1280, height: 800 }
14
+ inputMode: keyboard
15
+ reducedMotion: true
16
+ cleanupPolicyRef: null
@@ -0,0 +1,10 @@
1
+ schemaVersion: workflow.intelligence-policy/v1
2
+ ref: { id: example.policy.no-authoring-inference, revision: "1" }
3
+ stages:
4
+ analysis: { allowed: false, maxCalls: 0, maxTokens: 0, costCeilingCents: 0 }
5
+ drafting: { allowed: false, maxCalls: 0, maxTokens: 0, costCeilingCents: 0 }
6
+ discovery: { allowed: false, maxCalls: 0, maxTokens: 0, costCeilingCents: 0 }
7
+ diagnosis: { allowed: false, maxCalls: 0, maxTokens: 0, costCeilingCents: 0 }
8
+ evaluation: { allowed: false, maxCalls: 0, maxTokens: 0, costCeilingCents: 0 }
9
+ benchmark: { allowed: false, maxCalls: 0, maxTokens: 0, costCeilingCents: 0 }
10
+ replayInference: none
@@ -0,0 +1,5 @@
1
+ schemaVersion: workflow.runner-profile/v1
2
+ ref: { id: tracegrove.runner.http, revision: "1" }
3
+ adapter: http
4
+ maxStepsPerCase: 50
5
+ cancellation: confirmed
@@ -0,0 +1,11 @@
1
+ schemaVersion: workflow.surface-binding/v1
2
+ ref: { id: example.surface.notes-http, revision: "1" }
3
+ kind: http_api
4
+ packRef: { $file: ./http-api.pack.yaml }
5
+ driverProfileRef: null
6
+ componentProfileRef: { $file: ../components/notes-api.profile.yaml }
7
+ interaction: protocol
8
+ configurationSchemaRef: null
9
+ configurationRef: null
10
+ variantPolicyRef: null
11
+ requiredCapabilities: [http.request, observe]
@@ -0,0 +1,7 @@
1
+ schemaVersion: workflow.surface-pack/v1
2
+ ref: { id: tracegrove.pack.http-api, revision: "1" }
3
+ kind: http_api
4
+ protocol: http
5
+ stepKinds: [http.request, observe]
6
+ oracles: [http.observation/1, step.result/1]
7
+ captureFormats: [application/json]
@@ -0,0 +1,27 @@
1
+ schemaVersion: workflow.config/v1
2
+ project: notes
3
+ suiteRef: ./cases/notes.suite.yaml
4
+ defaultProfile: native-real
5
+ outputDir: ./verification-output
6
+ sourceSetRef: null
7
+ executionHostRef: ./hosts/local-process.yaml
8
+ intelligencePolicyRef: ./policies/no-authoring-inference.yaml
9
+ profiles:
10
+ native-real:
11
+ class: isolated_candidate
12
+ environmentPlanRef: ./environments/local-notes.yaml
13
+ hostPlanRef: null
14
+ personaRef: ./personas/owner.yaml
15
+ fixturePlanRef: null
16
+ fidelityProfileRef: ./fidelity/full-live-sandbox.yaml
17
+ runnerRef: ./runners/http.yaml
18
+ budget: { deadlineMs: 60000, costCeilingCents: 0 }
19
+ offline-contract:
20
+ class: isolated_candidate
21
+ environmentPlanRef: ./environments/mock-notes.yaml
22
+ hostPlanRef: ./hosts/mock-loopback.yaml
23
+ personaRef: ./personas/owner.yaml
24
+ fixturePlanRef: null
25
+ fidelityProfileRef: ./fidelity/mock-contract.yaml
26
+ runnerRef: ./runners/http.yaml
27
+ budget: { deadlineMs: 20000, costCeilingCents: 0 }
@@ -0,0 +1,19 @@
1
+ title: A seeded note appears in the authenticated browser
2
+ tags: [browser, smoke]
3
+ given: { existing: existing-note }
4
+ browser:
5
+ allowPaths: [/ui, /notes]
6
+ allowMethods: [GET, HEAD]
7
+ steps:
8
+ - name: open notes
9
+ browser: { kind: navigate, path: /ui }
10
+ expect: { status: 200 }
11
+ - name: refresh notes
12
+ browser: { kind: click, target: { by: role, role: button, name: Refresh } }
13
+ - name: note is visible
14
+ browser: { kind: read, target: { by: testId, name: notes } }
15
+ expect: { text: Existing note }
16
+ - name: independent API readback
17
+ GET: /notes/{existing.noteId}
18
+ observe: true
19
+ expect: { status: 200, json: { note.title: Existing note } }
@@ -0,0 +1,63 @@
1
+ schemaVersion: workflow.case/v1
2
+ ref: { id: example.notes.browser, revision: "1" }
3
+ purpose: Read a seeded note through the authenticated browser and confirm its state through an independent API readback.
4
+ workflowId: notes.browser
5
+ requirementRefs: []
6
+ sourceRefs: []
7
+ sourceAnalysisRef: null
8
+ risk: standard
9
+ surface: hybrid
10
+ surfaceBindingRef: { $file: ../surfaces/http-api.binding.yaml }
11
+ proofClaim: The locally launched application displays a seeded note through its authenticated UI, agrees with an independent API readback, and records the browser interaction. This establishes local application behavior only.
12
+ environmentClasses: [isolated_candidate]
13
+ requiredCapabilities: [ui.navigate, ui.action, ui.observe, observe, fixture.http]
14
+ requiredBoundaries:
15
+ - { boundaryId: application, mode: real }
16
+ - { boundaryId: storage, mode: real }
17
+ dependencyCases: []
18
+ personaRef: { $file: ../personas/owner.yaml }
19
+ datasetRef: null
20
+ fixturePlanRef: { $file: ../fixtures/existing-note.plan.yaml }
21
+ navigationRef: null
22
+ preconditions: []
23
+ steps:
24
+ - { id: navigate, kind: ui.navigate, path: /ui, timeoutMs: 5000, inputs: {}, retry: { attempts: 1 } }
25
+ - id: refresh
26
+ kind: ui.action
27
+ timeoutMs: 5000
28
+ inputs: {}
29
+ retry: { attempts: 1 }
30
+ command: { kind: click, target: { by: role, role: button, name: Refresh } }
31
+ - id: read_dom
32
+ kind: ui.observe
33
+ timeoutMs: 5000
34
+ inputs: {}
35
+ retry: { attempts: 1 }
36
+ target: { by: testId, name: notes }
37
+ predicate: { kind: json_path_equals, path: browser.text, value: Existing note }
38
+ pollIntervalMs: 50
39
+ - id: read_api
40
+ kind: observe
41
+ timeoutMs: 5000
42
+ inputs: { existingId: { kind: fixture, entityKey: existing_note, outputName: noteId } }
43
+ retry: { attempts: 1 }
44
+ readback: { kind: http, method: GET, path: "/notes/{existingId}", auth: { kind: persona } }
45
+ predicate: { kind: json_path_equals, path: body.note.title, value: Existing note }
46
+ pollIntervalMs: 50
47
+ captures: []
48
+ assertions:
49
+ - { id: a.browser, stepId: read_dom, required: true, environmentClasses: [isolated_candidate], oracle: { name: browser.observation, version: "1" }, predicate: { kind: json_path_equals, path: browser.text, value: Existing note }, coverageTags: [notes.ui] }
50
+ - { id: a.readback, stepId: read_api, required: true, environmentClasses: [isolated_candidate], oracle: { name: http.observation, version: "1" }, predicate: { kind: all, predicates: [ { kind: status_equals, value: 200 }, { kind: json_path_equals, path: body.note.title, value: Existing note } ] }, coverageTags: [notes.read] }
51
+ effects:
52
+ mode: read_only
53
+ allowedHosts: ["launch://notes-api"]
54
+ allowedMethods: [GET, HEAD]
55
+ allowedResourcePrefixes: [/ui, /notes]
56
+ maxCreates: 1
57
+ maxMessages: 0
58
+ maxJobs: 0
59
+ cleanupRecipeRef: null
60
+ limits: { deadlineMs: 30000, maxProviderRequests: 0, maxTokens: 0, costCeilingCents: 0, maxBrowserActions: 50, maxArtifactBytes: 2097152, diagnosticRetries: 0, concurrencyGroup: notes }
61
+ capture: { stepEvents: true, networkMetadata: true, trace: optional, video: required, redactionPolicyRef: null, retentionPolicyRef: null }
62
+ baselineRef: null
63
+ generation: null
@@ -0,0 +1,4 @@
1
+ schemaVersion: workflow.suite/v1
2
+ id: notes.browser.suite
3
+ cases:
4
+ - { caseRef: ./notes.browser.yaml, required: true, profiles: [native-real] }
@@ -0,0 +1,5 @@
1
+ schemaVersion: workflow.runner-profile/v1
2
+ ref: { id: tracegrove.runner.browser, revision: "1" }
3
+ adapter: browser
4
+ maxStepsPerCase: 50
5
+ cancellation: confirmed
@@ -0,0 +1,11 @@
1
+ schemaVersion: workflow.surface-binding/v1
2
+ ref: { id: example.surface.notes-browser, revision: "1" }
3
+ kind: web
4
+ packRef: { $file: ./http-api.pack.yaml }
5
+ driverProfileRef: null
6
+ componentProfileRef: { $file: ../components/notes-api.profile.yaml }
7
+ interaction: hybrid
8
+ configurationSchemaRef: null
9
+ configurationRef: null
10
+ variantPolicyRef: null
11
+ requiredCapabilities: [http.request, observe, ui.navigate, ui.action, ui.observe]
@@ -0,0 +1,7 @@
1
+ schemaVersion: workflow.surface-pack/v1
2
+ ref: { id: tracegrove.pack.browser, revision: "1" }
3
+ kind: web
4
+ protocol: playwright
5
+ stepKinds: [http.request, observe, ui.navigate, ui.action, ui.observe]
6
+ oracles: [http.observation/1, browser.observation/1, step.result/1]
7
+ captureFormats: [application/json, video/webm]
@@ -0,0 +1,21 @@
1
+ # Django notes sample
2
+
3
+ This local Django application uses real HTTP and file-backed persistence. It has no ORM models, database connection, OrgX SDK, provider account or authoring inference. The runner uses the same cases, fixtures, assertions and HTTP adapter as the Node notes sample.
4
+
5
+ Use Python 3.13 and the verifier's supported Node 22 runtime. From this generated sample directory:
6
+
7
+ ```sh
8
+ python3.13 -m venv .venv
9
+ .venv/bin/python -m pip install --require-hashes -r app/requirements.lock
10
+ workflow-verify doctor --config verification/workflow.yaml
11
+ workflow-verify plan --config verification/workflow.yaml --output request.json
12
+ workflow-verify run --request request.json --json
13
+ ```
14
+
15
+ The launch recipe issues temporary owner and intruder credentials, allocates a fresh loopback port and writes notes inside the attempt's owned workspace. The local supervisor terminates the application group and removes that workspace after confirmed cleanup. No application data is written into the sample's source directory.
16
+
17
+ The source identity binds `app/django_app.py` and `app/requirements.lock`. The launcher observes Python's executable version and digest separately. Startup refuses installed dependency versions that disagree with the lock. This establishes local behavior; it does not attest installed dependency bytes or prove a production deployment.
18
+
19
+ The lock pins Django 6.1.2, asgiref and sqlparse to the downloaded pure-Python wheel hashes. Install with `--require-hashes`; do not replace the lock with an unpinned install. These dependencies use BSD licenses and remain distributed separately from this sample's Apache-2.0 source. The [Django standalone-settings documentation](https://docs.djangoproject.com/en/6.1/topics/settings/#using-settings-without-setting-django-settings-module) describes the settings/setup path.
20
+
21
+ Export the completed execution with `workflow-verify export`, then use `workflow-verify verify-bundle` to check its saved evidence. Product assertions, successful cleanup and a verified local bundle each describe their own evidence; none enables hosted execution.
@@ -0,0 +1,119 @@
1
+ """Local Django notes API: real file persistence, no ORM or database connection."""
2
+ from dataclasses import asdict, dataclass
3
+ from datetime import datetime, timezone
4
+ from importlib.metadata import version
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ from uuid import UUID, uuid4
9
+ from wsgiref.simple_server import WSGIRequestHandler, make_server
10
+
11
+ import django
12
+ from django.conf import settings
13
+ from django.core.wsgi import get_wsgi_application
14
+ from django.http import HttpResponse, JsonResponse
15
+ from django.urls import re_path
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class Note:
20
+ id: str
21
+ title: str
22
+ body: str
23
+ ownerId: str
24
+ createdAt: str
25
+
26
+ @classmethod
27
+ def create(cls, payload: object, owner: str) -> "Note":
28
+ if not isinstance(payload, dict) or not all(isinstance(payload.get(key), str) for key in ("title", "body")):
29
+ raise ValueError("invalid_note")
30
+ return cls(str(uuid4()), payload["title"], payload["body"], owner, datetime.now(timezone.utc).isoformat())
31
+
32
+
33
+ class NoteStore:
34
+ def __init__(self, root: Path):
35
+ self.root = root
36
+ self.root.mkdir(parents=True, exist_ok=True)
37
+
38
+ def path(self, identifier: str) -> Path:
39
+ return self.root / f"{UUID(identifier)}.json"
40
+
41
+ def read(self, identifier: str) -> Note | None:
42
+ try:
43
+ return Note(**json.loads(self.path(identifier).read_text()))
44
+ except (ValueError, FileNotFoundError):
45
+ return None
46
+
47
+ def write(self, note: Note) -> None:
48
+ path = self.path(note.id)
49
+ temporary = path.with_suffix(".tmp")
50
+ temporary.write_text(json.dumps(asdict(note)))
51
+ temporary.replace(path)
52
+
53
+ def owned(self, owner: str) -> list[dict]:
54
+ return [asdict(note) for path in sorted(self.root.glob("*.json"))
55
+ if (note := self.read(path.stem)) is not None and note.ownerId == owner]
56
+
57
+
58
+ class NotesAPI:
59
+ def __init__(self, store: NoteStore, tokens: dict[str, str], build: str):
60
+ self.store, self.tokens, self.build = store, tokens, build
61
+
62
+ def health(self, request):
63
+ return JsonResponse({"ok": True, "build": self.build, "notes": len(list(self.store.root.glob("*.json")))})
64
+
65
+ def notes(self, request, identifier: str | None = None):
66
+ authorization = request.headers.get("Authorization", "")
67
+ owner = self.tokens.get(authorization[7:]) if authorization.startswith("Bearer ") else None
68
+ if not owner:
69
+ return JsonResponse({"error": "unauthorized"}, status=401)
70
+ if identifier is None:
71
+ if request.method == "GET":
72
+ return JsonResponse({"notes": self.store.owned(owner)})
73
+ if request.method == "POST":
74
+ try:
75
+ note = Note.create(json.loads(request.body or b"{}"), owner)
76
+ except (ValueError, UnicodeDecodeError):
77
+ return JsonResponse({"error": "invalid_note"}, status=400)
78
+ self.store.write(note)
79
+ return JsonResponse({"note": asdict(note)}, status=201)
80
+ return JsonResponse({"error": "method_not_allowed"}, status=405)
81
+ note = self.store.read(identifier)
82
+ if note is None:
83
+ return JsonResponse({"error": "not_found"}, status=404)
84
+ if note.ownerId != owner:
85
+ return JsonResponse({"error": "forbidden"}, status=403)
86
+ if request.method == "GET":
87
+ return JsonResponse({"note": asdict(note)})
88
+ if request.method == "DELETE":
89
+ self.store.path(identifier).unlink()
90
+ return HttpResponse(status=204)
91
+ return JsonResponse({"error": "method_not_allowed"}, status=405)
92
+
93
+
94
+ class QuietHandler(WSGIRequestHandler):
95
+ def log_message(self, format, *args):
96
+ pass
97
+
98
+
99
+ def check_dependencies() -> None:
100
+ # Fail readiness when the installed versions disagree with the pinned input.
101
+ for line in Path(__file__).with_name("requirements.lock").read_text().splitlines():
102
+ if line and not line.startswith("#"):
103
+ name, expected = line.split()[0].split("==")
104
+ if version(name) != expected:
105
+ raise RuntimeError("Install the dependencies from app/requirements.lock")
106
+
107
+
108
+ check_dependencies()
109
+ settings.configure(DEBUG=False, ROOT_URLCONF=__name__, ALLOWED_HOSTS=["127.0.0.1"],
110
+ INSTALLED_APPS=[], DATABASES={}, MIDDLEWARE=[], DATA_UPLOAD_MAX_MEMORY_SIZE=65536)
111
+ django.setup()
112
+ api = NotesAPI(NoteStore(Path(os.environ["NOTES_DIR"])), json.loads(os.environ["NOTES_TOKENS"]),
113
+ os.environ.get("NOTES_BUILD", "django-sample"))
114
+ urlpatterns = [re_path(r"^health$", api.health), re_path(r"^notes(?:/(?P<identifier>[^/]+))?$", api.notes)]
115
+
116
+ if __name__ == "__main__":
117
+ with make_server("127.0.0.1", int(os.environ.get("PORT", "0")), get_wsgi_application(), handler_class=QuietHandler) as server:
118
+ print(f"listening {server.server_port}", flush=True)
119
+ server.serve_forever()
@@ -0,0 +1,4 @@
1
+ # Pure-Python wheels downloaded from PyPI; installs require these exact hashes.
2
+ asgiref==3.12.1 --hash=sha256:fe386d1c2bff7259ea95929266d12a8cf9a8b5a1c2598402967d8792e7a7c094
3
+ Django==6.1.2 --hash=sha256:141efee6ec64d1db6db90683bf734c550102450f444fb099063b0be1bd27d991
4
+ sqlparse==0.6.0 --hash=sha256:b861c0288ce2fa56209a9a6412d2e066ac664b3873b89c26c9d8415e8e32996f
@@ -0,0 +1,47 @@
1
+ // Local native application: file-backed notes over MCP and independent HTTP readback.
2
+ // Implements the bounded JSON-response 2025-11-25 transport, not an MCP widget host.
3
+ import { createServer } from 'node:http';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { mkdirSync, writeFileSync, readFileSync, readdirSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { send, readBody } from './http.mjs';
8
+
9
+ const directory = process.env.NOTES_DIR;
10
+ if (!directory) throw new Error('NOTES_DIR is required');
11
+ mkdirSync(directory, { recursive: true });
12
+ const tokens = JSON.parse(process.env.NOTES_TOKENS ?? '{}');
13
+ const server = createServer(async (request, response) => {
14
+ try {
15
+ const path = new URL(request.url ?? '/', 'http://127.0.0.1').pathname;
16
+ if (request.method === 'GET' && path === '/health') return send(response, 200, { ok: true, notes: readdirSync(directory).length });
17
+ const token = String(request.headers.authorization ?? '').replace(/^Bearer /, '');
18
+ if (!Object.hasOwn(tokens, token)) return send(response, 401, { error: 'unauthorized' });
19
+ const ownerId = tokens[token];
20
+ const match = path.match(/^\/notes\/([0-9a-f-]{36})$/);
21
+ if (request.method === 'GET' && match) {
22
+ let note;
23
+ try { note = JSON.parse(readFileSync(join(directory, `${match[1]}.json`), 'utf8')); }
24
+ catch { return send(response, 404, { error: 'not_found' }); }
25
+ if (note.ownerId !== ownerId) return send(response, 403, { error: 'forbidden' });
26
+ return send(response, 200, { note });
27
+ }
28
+ if (path !== '/mcp') return send(response, 404, { error: 'not_found' });
29
+ if (request.method !== 'POST') return send(response, 405, { error: 'method_not_allowed' });
30
+ const message = await readBody(request);
31
+ if (message.jsonrpc !== '2.0' || typeof message.method !== 'string') return send(response, 400, { error: 'invalid_request' });
32
+ if (message.id === undefined) { response.writeHead(202); response.end(); return; }
33
+ const reply = result => send(response, 200, { jsonrpc: '2.0', id: message.id, result });
34
+ if (message.method === 'initialize') return reply({ protocolVersion: '2025-11-25', capabilities: { tools: {} }, serverInfo: { name: 'native-notes', version: '1.0.0' } });
35
+ if (message.method === 'tools/list') return reply({ tools: [{ name: 'notes.create', inputSchema: { type: 'object', properties: { title: { type: 'string' }, body: { type: 'string' } }, required: ['title', 'body'], additionalProperties: false } }] });
36
+ if (message.method === 'tools/call' && message.params?.name === 'notes.create') {
37
+ const input = message.params.arguments;
38
+ if (!input || typeof input.title !== 'string' || typeof input.body !== 'string') return reply({ isError: true, content: [{ type: 'text', text: 'Invalid note input' }] });
39
+ const note = { id: randomUUID(), title: input.title, body: input.body, ownerId };
40
+ writeFileSync(join(directory, `${note.id}.json`), JSON.stringify(note));
41
+ return reply({ content: [{ type: 'text', text: JSON.stringify({ note }) }], structuredContent: { note }, isError: false });
42
+ }
43
+ return send(response, 200, { jsonrpc: '2.0', id: message.id, error: { code: -32601, message: 'Unsupported method or tool' } });
44
+ } catch { send(response, 400, { error: 'invalid_request' }); }
45
+ });
46
+ server.listen(Number(process.env.PORT ?? 0), '127.0.0.1');
47
+ process.on('SIGTERM', () => server.close(() => process.exit(0)));
@@ -0,0 +1,20 @@
1
+ title: MCP creation is independently visible through the notes API
2
+ effects:
3
+ maxMcpCalls: 1
4
+ allowedMcpTools: [notes.create]
5
+ steps:
6
+ - name: create
7
+ mcp:
8
+ endpoint: /mcp
9
+ tool: notes.create
10
+ arguments: { title: Protocol proof, body: Saved by the native application }
11
+ expect:
12
+ json: { structuredContent.note.title: Protocol proof }
13
+ save: { noteId: structuredContent.note.id }
14
+ - GET: /notes/{noteId}
15
+ expect:
16
+ status: 200
17
+ json: { note.title: Protocol proof, note.ownerId: alice }
18
+ - GET: /notes/{noteId}
19
+ as: intruder
20
+ expect: 403
@@ -0,0 +1,13 @@
1
+ project: mcp-notes
2
+ app:
3
+ adapter: node
4
+ entry: app/mcp.mjs
5
+ health: /health
6
+ sources: [app/**]
7
+ inject:
8
+ port: PORT
9
+ dataDir: NOTES_DIR
10
+ tokens: NOTES_TOKENS
11
+ personas:
12
+ owner: { subject: alice }
13
+ intruder: { subject: bob }
@@ -0,0 +1,30 @@
1
+ # Report jobs
2
+
3
+ This sample runs a local HTTP API and a separate Node worker against one persisted
4
+ SQLite queue. Only the worker publishes report rows. Duplicate owner/request keys
5
+ reuse one job, cancellation waits for a worker acknowledgement, and failed jobs
6
+ leave no report. Fixture cleanup deletes its owned job and report atomically.
7
+
8
+ Generate the sample with `tracegrove sample-config --sample report-jobs --output
9
+ <empty-directory>`. From that directory, run `tracegrove test`. Sample generation
10
+ also compiles the low-level corpus and prints its config path; pass that exact
11
+ path to `workflow-verify plan` or `doctor`. Compilation checks the installed Node
12
+ runtime but does not start the API or worker.
13
+
14
+ All flows use the existing HTTP submit/readback/oracle contracts. A 202 submission
15
+ alone cannot satisfy the completion case: it polls job state, reads the persisted
16
+ report independently, checks one-job idempotency and verifies owner isolation.
17
+ `effects.maxJobs: 1` declares each flow's admitted job ceiling; it does not impose
18
+ a quota on an arbitrary external provider.
19
+
20
+ The `REPORTS_TEST_DROP_REPORT=1` application flag is a controlled defect: the
21
+ worker records success without inserting the report. The completion flow must
22
+ fail on independent report readback, while retaining its sealed failed attempt.
23
+ The flag is part of the frozen app launch configuration. It is not a normal
24
+ successful lane.
25
+
26
+ The package's pinned Node 22 range supplies `node:sqlite`; no database server,
27
+ account, model call or OrgX connection is needed. The core attests the complete
28
+ application source set, including worker and storage code. This is local
29
+ application/job behavior, not a separately issued worker attestation, hosted
30
+ provider qualification, a native `job.submit` adapter, or crash-recovery proof.
@@ -0,0 +1,65 @@
1
+ import { createServer } from 'node:http';
2
+ import { fork } from 'node:child_process';
3
+ import { mkdirSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { JobStore, validJobInput } from './store.mjs';
6
+ import { nativeBridge } from './native-bridge.mjs';
7
+ import { send, readBody } from './http.mjs';
8
+
9
+ const dir = process.env.REPORTS_DIR;
10
+ if (!dir) throw new Error('REPORTS_DIR is required');
11
+ mkdirSync(dir, { recursive: true });
12
+ const store = new JobStore(join(dir, 'reports.sqlite'));
13
+ const tokens = JSON.parse(process.env.REPORTS_TOKENS ?? '{}');
14
+ const worker = fork(new URL('./worker.mjs', import.meta.url), [join(dir, 'reports.sqlite')], {
15
+ stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
16
+ env: { REPORTS_TEST_DROP_REPORT: process.env.REPORTS_TEST_DROP_REPORT ?? '0' },
17
+ });
18
+ let ready = false;
19
+ const nativeReady = nativeBridge(store, tokens, () => ready);
20
+ worker.on('message', message => { if (message?.type === 'ready') { ready = true; nativeReady(); } });
21
+ worker.on('exit', () => { ready = false; });
22
+ const view = job => ({ id: job.id, requestKey: job.request_key, title: job.title, mode: job.mode,
23
+ status: job.status, workerPid: job.worker_pid, apiPid: process.pid });
24
+ const server = createServer(async (req, res) => {
25
+ const url = new URL(req.url ?? '/', 'http://127.0.0.1');
26
+ if (req.method === 'GET' && url.pathname === '/health') return send(res, ready ? 200 : 503, { ok: ready, workerPid: worker.pid, apiPid: process.pid });
27
+ const authorization = req.headers.authorization ?? '';
28
+ const token = authorization.startsWith('Bearer ') ? authorization.slice(7) : '';
29
+ const owner = Object.hasOwn(tokens, token) ? tokens[token] : null;
30
+ if (typeof owner !== 'string' || !owner) return send(res, 401, { error: 'unauthorized' });
31
+ try {
32
+ if (url.pathname === '/jobs' && req.method === 'GET') return send(res, 200, { jobs: store.list(owner).map(view) });
33
+ if (url.pathname === '/jobs' && req.method === 'POST') {
34
+ if (!ready) return send(res, 503, { error: 'worker_unavailable' });
35
+ const body = await readBody(req);
36
+ if (!validJobInput(body)) return send(res, 400, { error: 'invalid_job' });
37
+ const result = store.submit(owner, body);
38
+ if (result.conflict) return send(res, 409, { error: 'idempotency_conflict' });
39
+ return send(res, result.duplicate ? 200 : 202, { job: view(result.job), deduplicated: result.duplicate });
40
+ }
41
+ const match = /^\/(jobs|reports)\/([0-9a-f-]{36})(\/cancel)?$/.exec(url.pathname);
42
+ if (!match) return send(res, 404, { error: 'not_found' });
43
+ const [, resource, id, cancel] = match;
44
+ const job = store.get(id);
45
+ if (!job) return send(res, 404, { error: 'not_found' });
46
+ if (job.owner_id !== owner) return send(res, 403, { error: 'forbidden' });
47
+ if (resource === 'reports' && req.method === 'GET' && !cancel) {
48
+ const report = store.report(id);
49
+ return report ? send(res, 200, { report }) : send(res, 404, { error: 'report_absent' });
50
+ }
51
+ if (resource !== 'jobs') return send(res, 405, { error: 'method_not_allowed' });
52
+ if (cancel && req.method === 'POST') return send(res, store.requestCancel(id) ? 202 : 409, { requested: true });
53
+ if (!cancel && req.method === 'GET') return send(res, 200, { job: view(job) });
54
+ if (!cancel && req.method === 'DELETE') { store.remove(id); return send(res, 204); }
55
+ return send(res, 405, { error: 'method_not_allowed' });
56
+ } catch { return send(res, 400, { error: 'bad_request' }); }
57
+ });
58
+ server.listen(Number(process.env.PORT ?? 0), '127.0.0.1', () => {
59
+ process.send?.({ type: 'listening', port: server.address().port });
60
+ });
61
+ process.on('SIGTERM', () => {
62
+ const close = () => server.close(() => { store.close(); process.exit(0); });
63
+ if (worker.exitCode !== null || worker.signalCode !== null) close();
64
+ else { worker.once('exit', close); worker.kill('SIGTERM'); }
65
+ });
@@ -0,0 +1,30 @@
1
+ import { validJobInput } from './store.mjs';
2
+
3
+ /** The application owns auth and queue semantics; the worker and SQLite store remain real. */
4
+ export function nativeBridge(store, tokens, workerReady) {
5
+ if (process.env.TRACEGROVE_NATIVE_JOBS !== 'node_ipc/v1') return () => {};
6
+ const empty = status => ({ jobId: null, status, requestKey: null, output: null, workerId: null });
7
+ process.on('message', request => {
8
+ if (request?.kind !== 'tracegrove.job.request') return;
9
+ const { command, credential } = request;
10
+ const owner = Object.hasOwn(tokens, credential) ? tokens[credential] : null;
11
+ let result = empty('forbidden');
12
+ if (typeof owner === 'string' && command.queue === 'reports') {
13
+ let job;
14
+ if (command.action === 'submit') {
15
+ const input = { ...command.payload, requestKey: command.requestKey };
16
+ if (!workerReady() || !validJobInput(input)) result = empty('conflict');
17
+ else { const submitted = store.submit(owner, input); job = submitted.job; if (submitted.conflict) result = empty('conflict'); }
18
+ } else {
19
+ job = store.get(command.jobId);
20
+ if (!job) result = empty('missing');
21
+ else if (job.owner_id !== owner) { job = null; result = empty('forbidden'); }
22
+ else if (command.action === 'cancel') { store.requestCancel(job.id); job = store.get(job.id); }
23
+ }
24
+ if (job) result = { jobId: job.id, status: job.status, requestKey: job.request_key,
25
+ output: { report: store.report(job.id), apiPid: process.pid, totalJobs: store.list(owner).length }, workerId: job.worker_pid ? String(job.worker_pid) : null };
26
+ }
27
+ process.send?.({ kind: 'tracegrove.job.response', id: request.id, result });
28
+ });
29
+ return () => process.send?.({ kind: 'tracegrove.job.ready', version: 1, queues: ['reports'] });
30
+ }