@tiinex/app 0.1.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 (580) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +31 -0
  3. package/README.md +26 -0
  4. package/docs/CONSUMER-CONTRACT.md +65 -0
  5. package/package.json +94 -0
  6. package/src/acceptance/knownScenarios.case.mjs +48 -0
  7. package/src/acceptance/knownScenarios.js +89 -0
  8. package/src/acceptance/postV423CanonicalTransitionProductVerticalSlice.case.mjs +774 -0
  9. package/src/acceptance/postV437M0ETimePortalProductParityClosure.case.mjs +51 -0
  10. package/src/acceptance/postV447M0FGithubSocialPublicationProductIntegration.case.mjs +33 -0
  11. package/src/acceptance/postV450M0ProductAcceptanceHardening.case.mjs +82 -0
  12. package/src/acceptance/postV470SchemaReadingContractMaterializationIdentitySourceCoalescingAuthorityCorrection.case.mjs +236 -0
  13. package/src/acceptance/recoveryAcceptance.case.mjs +196 -0
  14. package/src/adapters/adapter.definition.schema.json +33 -0
  15. package/src/adapters/archive/archive.adapter.case.mjs +212 -0
  16. package/src/adapters/export/export.adapter.js +79 -0
  17. package/src/adapters/git-native/git-native.adapter.js +43 -0
  18. package/src/adapters/github/github.adapter.case.mjs +843 -0
  19. package/src/adapters/github/github.adapter.js +395 -0
  20. package/src/adapters/github/github.issueEmbedded.js +262 -0
  21. package/src/adapters/github/github.issueMirror.js +309 -0
  22. package/src/adapters/github/github.issueSnapshot.js +475 -0
  23. package/src/adapters/github/github.issueSurface.js +188 -0
  24. package/src/adapters/github/github.issueTransport.js +237 -0
  25. package/src/adapters/github/github.publicationRead.js +24 -0
  26. package/src/adapters/github/github.readTransport.js +18 -0
  27. package/src/adapters/github/github.repoDiscovery.js +222 -0
  28. package/src/adapters/github/github.repoMirror.js +255 -0
  29. package/src/adapters/github/github.repoProxy.js +276 -0
  30. package/src/adapters/github/github.repoSurface.js +60 -0
  31. package/src/adapters/github/github.transportDiagnostics.js +68 -0
  32. package/src/adapters/local/local.adapter.case.mjs +72 -0
  33. package/src/adapters/local/local.adapter.js +188 -0
  34. package/src/adapters/registry.js +35 -0
  35. package/src/adapters/static/static.adapter.js +84 -0
  36. package/src/app/App.js +1 -0
  37. package/src/app/TiinexApp.jsx +822 -0
  38. package/src/app/appShell.views.jsx +58 -0
  39. package/src/app/artifactAuthoringCapability.js +49 -0
  40. package/src/app/boot/bootApp.js +19 -0
  41. package/src/app/boot/environment.js +1 -0
  42. package/src/app/canonicalAuthoringValues.js +4 -0
  43. package/src/app/canonicalCreationProductController.js +57 -0
  44. package/src/app/canonicalCreationProductSettlement.case.mjs +10 -0
  45. package/src/app/canonicalCreationProductSettlement.js +11 -0
  46. package/src/app/canonicalReferenceLocalCreateCommand.js +210 -0
  47. package/src/app/canonicalReferenceTargets.js +73 -0
  48. package/src/app/canonicalTransitionLocalCreateCommand.js +217 -0
  49. package/src/app/defaultWorkspaceStart.case.mjs +39 -0
  50. package/src/app/defaultWorkspaceStart.js +65 -0
  51. package/src/app/defaultWorkspaceStartCommand.js +55 -0
  52. package/src/app/durableLocalMutationPolicy.js +21 -0
  53. package/src/app/githubMaterializationSummary.js +69 -0
  54. package/src/app/githubProgress.js +25 -0
  55. package/src/app/githubSourceInput.js +47 -0
  56. package/src/app/githubSourceMaterializationCommand.js +97 -0
  57. package/src/app/githubSourceOperation.js +226 -0
  58. package/src/app/governanceDialogData.js +27 -0
  59. package/src/app/handoffPackageImportCommand.js +182 -0
  60. package/src/app/historyAuthority.js +53 -0
  61. package/src/app/initialWorkspaceBootstrapOperation.js +105 -0
  62. package/src/app/lineageCommand.js +118 -0
  63. package/src/app/lineageSourceRecovery.js +339 -0
  64. package/src/app/localDraftMutationCommand.js +174 -0
  65. package/src/app/localMaterialCommand.js +124 -0
  66. package/src/app/nodeGraphVerse.case.mjs +111 -0
  67. package/src/app/persistenceOwnership.js +92 -0
  68. package/src/app/productStateBoundary.js +7 -0
  69. package/src/app/providers/AppProviders.js +1 -0
  70. package/src/app/providers/LocaleProvider.js +1 -0
  71. package/src/app/providers/SchemaRegistryProvider.js +1 -0
  72. package/src/app/providers/WorkspaceProvider.js +1 -0
  73. package/src/app/publicTarget.js +251 -0
  74. package/src/app/publicTargetRestoreCommand.js +149 -0
  75. package/src/app/recordUi.cache.js +35 -0
  76. package/src/app/recordUi.js +11 -0
  77. package/src/app/routes/RouteSurface.js +1 -0
  78. package/src/app/routes/routes.js +1 -0
  79. package/src/app/runtimeState.js +54 -0
  80. package/src/app/schemaCurrentDeclaration.js +69 -0
  81. package/src/app/schemaFactoryLocalCreateCommand.js +101 -0
  82. package/src/app/schemaFactoryViewerProof.case.mjs +134 -0
  83. package/src/app/schemaFactoryViewerProof.js +20 -0
  84. package/src/app/schemaNavigationCommand.js +285 -0
  85. package/src/app/schemaNavigationMaterialization.js +171 -0
  86. package/src/app/schemaNavigationRuntimeCatalog.js +25 -0
  87. package/src/app/schemaNavigationState.js +66 -0
  88. package/src/app/schemaReadingContractQualification.js +91 -0
  89. package/src/app/schemaSourceRecovery.js +373 -0
  90. package/src/app/scrollPersistence.js +30 -0
  91. package/src/app/semanticOperationHistory.js +18 -0
  92. package/src/app/shareActionCommand.js +55 -0
  93. package/src/app/shareProjection.js +190 -0
  94. package/src/app/shell/AppShell.js +1 -0
  95. package/src/app/shell/Header.js +1 -0
  96. package/src/app/shell/Navigation.js +1 -0
  97. package/src/app/shell/SurfaceSwitcher.js +1 -0
  98. package/src/app/sourceTransportRefresh.js +176 -0
  99. package/src/app/startupOwnership.js +40 -0
  100. package/src/app/startupPresentation.case.mjs +34 -0
  101. package/src/app/startupPresentation.js +33 -0
  102. package/src/app/startupPresentation.views.jsx +21 -0
  103. package/src/app/startupRenderPhase.js +9 -0
  104. package/src/app/startupWorkspaceCommand.js +62 -0
  105. package/src/app/startupWorkspaceConfigApplication.js +49 -0
  106. package/src/app/statePersistenceScheduler.js +106 -0
  107. package/src/app/tiinexAppConfigPlan.js +108 -0
  108. package/src/app/tiinexAppConfigSource.js +349 -0
  109. package/src/app/tiinexAppStartupSource.js +79 -0
  110. package/src/app/tiinexHostedWorkspaceConventions.js +572 -0
  111. package/src/app/timePortalHistoricalRead.js +114 -0
  112. package/src/app/timePortalSnapshotResolution.js +53 -0
  113. package/src/app/urlMaterialCommand.js +24 -0
  114. package/src/app/useCanonicalPlacementSelectionOptions.js +9 -0
  115. package/src/app/useCanonicalReferenceSelectionOptions.js +8 -0
  116. package/src/app/useLocalMaterialIntake.js +68 -0
  117. package/src/app/useTimePortalProductController.jsx +111 -0
  118. package/src/app/useWorkspaceEntrypointIntake.js +77 -0
  119. package/src/app/useWorkspaceSelectionProductController.jsx +21 -0
  120. package/src/app/viewState.js +35 -0
  121. package/src/app/viewport.js +21 -0
  122. package/src/app/visualDormancy.js +286 -0
  123. package/src/app/workspaceContinuityNotices.js +32 -0
  124. package/src/app/workspaceDisplayCounts.js +9 -0
  125. package/src/app/workspaceEntrypointIntakeCommand.js +87 -0
  126. package/src/app/workspaceEntrypointProductRouting.case.mjs +20 -0
  127. package/src/app/workspaceExportCommand.js +21 -0
  128. package/src/app/workspaceExportDownload.js +23 -0
  129. package/src/app/workspaceExportExecutionCommand.js +10 -0
  130. package/src/app/workspaceGithubPublication.js +237 -0
  131. package/src/app/workspaceHandoffExport.js +56 -0
  132. package/src/app/workspaceHomeTarget.js +9 -0
  133. package/src/app/workspaceMulticolumn.js +113 -0
  134. package/src/app/workspaceNavigationParity.case.mjs +110 -0
  135. package/src/app/workspaceOpenProgress.js +26 -0
  136. package/src/app/workspacePlacementOptions.js +46 -0
  137. package/src/app/workspaceRecordActions.js +158 -0
  138. package/src/app/workspaceScopedInteraction.js +68 -0
  139. package/src/app/workspaceSelectionOriginContext.js +29 -0
  140. package/src/app/workspaceSelectionSession.js +54 -0
  141. package/src/app/workspaceSourceCloseCommand.js +25 -0
  142. package/src/app/workspaceSpineProductRouting.case.mjs +22 -0
  143. package/src/app/workspaceStartupTransition.js +32 -0
  144. package/src/app/workspaceWindow.js +85 -0
  145. package/src/artifacts/artifact.fixture.js +1 -0
  146. package/src/artifacts/artifact.identity.js +6 -0
  147. package/src/artifacts/artifact.identityAggregation.js +218 -0
  148. package/src/artifacts/artifact.model.js +2 -0
  149. package/src/artifacts/artifact.parse.case.mjs +196 -0
  150. package/src/artifacts/artifact.participantIndex.js +189 -0
  151. package/src/artifacts/fixtures/evidence.trace.md +50 -0
  152. package/src/artifacts/fixtures/topic.trace.md +33 -0
  153. package/src/artifacts/fixtures/unknown-schema.trace.md +25 -0
  154. package/src/audit/audit.findings.js +1 -0
  155. package/src/audit/audit.model.js +2 -0
  156. package/src/audit/audit.plan.js +13 -0
  157. package/src/audit/audit.report.js +12 -0
  158. package/src/audit/audit.severity.js +1 -0
  159. package/src/audit/audit.traverse.js +119 -0
  160. package/src/audit/integrity/auditIntegrity.checks.js +1 -0
  161. package/src/audit/integrity/auditIntegrity.compare.js +1 -0
  162. package/src/audit/lineage/auditLineage.load.js +1 -0
  163. package/src/audit/lineage/auditLineage.plan.js +1 -0
  164. package/src/audit/lineage/auditLineage.resolve.js +12 -0
  165. package/src/audit/sources/auditSources.boundaries.js +1 -0
  166. package/src/audit/sources/auditSources.checks.js +1 -0
  167. package/src/audit/validation/auditValidation.recheck.js +1 -0
  168. package/src/audit/validation/auditValidation.run.js +1 -0
  169. package/src/build.identity.js +15 -0
  170. package/src/commands/command.vocabulary.js +14 -0
  171. package/src/conformance/conformance.fixtures.js +151 -0
  172. package/src/conformance/conformance.run.js +238 -0
  173. package/src/data/applicationDataStore.js +23 -0
  174. package/src/data/companionAccess.js +35 -0
  175. package/src/diagnostics/events.js +1 -0
  176. package/src/diagnostics/invariant.js +1 -0
  177. package/src/diagnostics/schemaBindingChecks.js +1 -0
  178. package/src/diagnostics/schemaModuleChecks.js +1 -0
  179. package/src/diagnostics/sourceBoundaryChecks.js +5 -0
  180. package/src/diagnostics/sourceTransport.report.js +190 -0
  181. package/src/discovery/discovery.controls.js +7 -0
  182. package/src/export/export.plan.js +182 -0
  183. package/src/export/handoff.plan.js +50 -0
  184. package/src/export/package.builder.case.mjs +97 -0
  185. package/src/export/package.controlTopology.case.mjs +130 -0
  186. package/src/export/package.zip.case.mjs +33 -0
  187. package/src/graph/artifactGraph.model.js +344 -0
  188. package/src/graph/artifactGraph.project.js +139 -0
  189. package/src/graph/artifactGraph.worker.js +10 -0
  190. package/src/i18n/i18n.keys.js +1 -0
  191. package/src/i18n/i18n.provider.js +1 -0
  192. package/src/i18n/i18n.resolve.js +5 -0
  193. package/src/i18n/locales/en/common.json +4 -0
  194. package/src/i18n/locales/en/schemas/evidence.json +3 -0
  195. package/src/i18n/locales/en/schemas/presentation-surface.json +3 -0
  196. package/src/i18n/locales/en/schemas/preservation.json +3 -0
  197. package/src/i18n/locales/en/schemas/root.json +3 -0
  198. package/src/i18n/locales/en/schemas/schema-module.json +3 -0
  199. package/src/i18n/locales/en/schemas/topic.json +3 -0
  200. package/src/i18n/locales/en/surfaces/audit.json +3 -0
  201. package/src/i18n/locales/en/surfaces/create.json +3 -0
  202. package/src/i18n/locales/en/surfaces/detail.json +3 -0
  203. package/src/i18n/locales/en/surfaces/display-options.json +3 -0
  204. package/src/i18n/locales/en/surfaces/edit.json +3 -0
  205. package/src/i18n/locales/en/surfaces/feed.json +3 -0
  206. package/src/i18n/locales/en/surfaces/lineage.json +3 -0
  207. package/src/i18n/locales/en/surfaces/preview.json +3 -0
  208. package/src/i18n/locales/en/surfaces/share.json +3 -0
  209. package/src/i18n/locales/en/surfaces/source-settings.json +3 -0
  210. package/src/i18n/locales/en/surfaces/tree.json +3 -0
  211. package/src/i18n/locales/sv/common.json +4 -0
  212. package/src/i18n/locales/sv/schemas/evidence.json +3 -0
  213. package/src/i18n/locales/sv/schemas/presentation-surface.json +3 -0
  214. package/src/i18n/locales/sv/schemas/preservation.json +3 -0
  215. package/src/i18n/locales/sv/schemas/root.json +3 -0
  216. package/src/i18n/locales/sv/schemas/schema-module.json +3 -0
  217. package/src/i18n/locales/sv/schemas/topic.json +3 -0
  218. package/src/i18n/locales/sv/surfaces/audit.json +3 -0
  219. package/src/i18n/locales/sv/surfaces/create.json +3 -0
  220. package/src/i18n/locales/sv/surfaces/detail.json +3 -0
  221. package/src/i18n/locales/sv/surfaces/display-options.json +3 -0
  222. package/src/i18n/locales/sv/surfaces/edit.json +3 -0
  223. package/src/i18n/locales/sv/surfaces/feed.json +3 -0
  224. package/src/i18n/locales/sv/surfaces/lineage.json +3 -0
  225. package/src/i18n/locales/sv/surfaces/preview.json +3 -0
  226. package/src/i18n/locales/sv/surfaces/share.json +3 -0
  227. package/src/i18n/locales/sv/surfaces/source-settings.json +3 -0
  228. package/src/i18n/locales/sv/surfaces/tree.json +3 -0
  229. package/src/index.js +10 -0
  230. package/src/integrity/integrity.testFixture.js +9 -0
  231. package/src/interaction/interaction.spine.js +12 -0
  232. package/src/lineage/lineage.audit.js +1 -0
  233. package/src/lineage/lineage.edges.js +1 -0
  234. package/src/main.js +319 -0
  235. package/src/main.jsx +34 -0
  236. package/src/multiverse/multiverse.model.js +10 -0
  237. package/src/parity/poc.m1ParityScenarios.js +42 -0
  238. package/src/parity/poc.parityLedger.js +261 -0
  239. package/src/publication/publication.githubSocialContract.case.mjs +247 -0
  240. package/src/publication/publication.preflight.case.mjs +64 -0
  241. package/src/react/TiinexApplication.jsx +39 -0
  242. package/src/react/VerseHost.jsx +29 -0
  243. package/src/react/applicationDataContext.jsx +30 -0
  244. package/src/react.js +2 -0
  245. package/src/readers/modes/audit.reader.js +1 -0
  246. package/src/readers/modes/detail.reader.js +1 -0
  247. package/src/readers/modes/handover.reader.js +1 -0
  248. package/src/readers/modes/mobile.reader.js +1 -0
  249. package/src/readers/modes/print.reader.js +1 -0
  250. package/src/readers/modes/scan.reader.js +1 -0
  251. package/src/readers/reader.model.js +1 -0
  252. package/src/readers/reader.resolve.js +2 -0
  253. package/src/reingest/reingest.plan.case.mjs +65 -0
  254. package/src/runtime.js +54 -0
  255. package/src/schemas/README.md +99 -0
  256. package/src/schemas/coordination/handoff/tiinex.handoff.v1.schema.md +614 -0
  257. package/src/schemas/coordination/project/tiinex.project.v1.schema.md +311 -0
  258. package/src/schemas/core/decision/tiinex.decision.v1.schema.md +227 -0
  259. package/src/schemas/core/evidence/tiinex.evidence.v1.schema.md +318 -0
  260. package/src/schemas/core/feedback/tiinex.feedback.v1.schema.md +243 -0
  261. package/src/schemas/core/interpretation/.transitions/evidence-to-interpretation-transition-definition.trace.md +102 -0
  262. package/src/schemas/core/interpretation/tiinex.interpretation.v1.schema.md +308 -0
  263. package/src/schemas/core/preservation/tiinex.preservation.v1.schema.md +312 -0
  264. package/src/schemas/core/relation/.generation/reference-relation-generation-authority.trace.md +185 -0
  265. package/src/schemas/core/relation/.transitions/topic-references-task-transition-definition.trace.md +119 -0
  266. package/src/schemas/core/relation/tiinex.relation.v1.schema.md +240 -0
  267. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.schema.md +550 -0
  268. package/src/schemas/core/signal/tiinex.signal.v1.schema.md +239 -0
  269. package/src/schemas/core/task/.transitions/create-task-transition-definition.trace.md +93 -0
  270. package/src/schemas/core/task/.transitions/topic-to-task-transition-definition.trace.md +102 -0
  271. package/src/schemas/core/task/task-semantic-package.trace.md +53 -0
  272. package/src/schemas/core/task/tiinex.task.v1-transitions.trace.md +33 -0
  273. package/src/schemas/core/task/tiinex.task.v1.authoring.js +65 -0
  274. package/src/schemas/core/task/tiinex.task.v1.schema.md +229 -0
  275. package/src/schemas/core/topic/.transitions/create-topic-transition-definition.trace.md +93 -0
  276. package/src/schemas/core/topic/tiinex.topic.v1-transitions.trace.md +33 -0
  277. package/src/schemas/core/topic/tiinex.topic.v1.schema.md +197 -0
  278. package/src/schemas/core/topic/topic-semantic-package.trace.md +53 -0
  279. package/src/schemas/discovery/finding/tiinex.discovery.finding.v1.schema.md +240 -0
  280. package/src/schemas/discovery/tiinex.discovery.v1.schema.md +294 -0
  281. package/src/schemas/manifest.json +367 -0
  282. package/src/schemas/origins.js +46 -0
  283. package/src/schemas/party/organization/tiinex.party.organization.v1.schema.md +290 -0
  284. package/src/schemas/party/role/tiinex.party.role.v1.schema.md +298 -0
  285. package/src/schemas/party/tiinex.party.v1.schema.js +14 -0
  286. package/src/schemas/party/tiinex.party.v1.schema.json +23 -0
  287. package/src/schemas/party/tiinex.party.v1.schema.md +311 -0
  288. package/src/schemas/party/tiinex.party.v1.schema.runtime.json +2033 -0
  289. package/src/schemas/party/tiinex.party.v1.schema.source.js +9 -0
  290. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.schema.md +476 -0
  291. package/src/schemas/reduction/tiinex.reduction.v1.schema.md +248 -0
  292. package/src/schemas/schema/module/tiinex.schema.module.v1.schema.md +465 -0
  293. package/src/schemas/schema.companionContract.case.mjs +259 -0
  294. package/src/schemas/schema.factory.case.mjs +256 -0
  295. package/src/schemas/schema.factory.viewerProjection.js +183 -0
  296. package/src/schemas/schemaMarkdownCatalog.js +19 -0
  297. package/src/schemas/tiinex.root.v1.schema.md +865 -0
  298. package/src/schemas/validation/finding/tiinex.validation.finding.v1.schema.md +309 -0
  299. package/src/schemas/validation/method/tiinex.validation.method.v1.schema.md +280 -0
  300. package/src/schemas/validation/report/tiinex.validation.report.v1.schema.md +300 -0
  301. package/src/schemas/workspace/tiinex.workspace.v1.schema.md +486 -0
  302. package/src/schemas/workspace/workspace.add.views.jsx +327 -0
  303. package/src/schemas/workspace/workspace.audit.views.jsx +160 -0
  304. package/src/schemas/workspace/workspace.auditBadge.views.jsx +98 -0
  305. package/src/schemas/workspace/workspace.canonicalReferenceDialog.views.jsx +63 -0
  306. package/src/schemas/workspace/workspace.canonicalTaskDialog.views.jsx +169 -0
  307. package/src/schemas/workspace/workspace.cardActions.js +9 -0
  308. package/src/schemas/workspace/workspace.cards.views.jsx +146 -0
  309. package/src/schemas/workspace/workspace.chrome.views.jsx +299 -0
  310. package/src/schemas/workspace/workspace.continuationDialog.views.jsx +80 -0
  311. package/src/schemas/workspace/workspace.discovery.views.jsx +63 -0
  312. package/src/schemas/workspace/workspace.discoveryRenderWindow.js +56 -0
  313. package/src/schemas/workspace/workspace.displayOptions.views.jsx +114 -0
  314. package/src/schemas/workspace/workspace.entrypointChoice.views.jsx +30 -0
  315. package/src/schemas/workspace/workspace.exportDialog.controller.jsx +40 -0
  316. package/src/schemas/workspace/workspace.exportDialog.views.jsx +142 -0
  317. package/src/schemas/workspace/workspace.governance.views.jsx +45 -0
  318. package/src/schemas/workspace/workspace.graph.views.jsx +134 -0
  319. package/src/schemas/workspace/workspace.lineage.views.jsx +307 -0
  320. package/src/schemas/workspace/workspace.read.views.jsx +105 -0
  321. package/src/schemas/workspace/workspace.recordActionButton.views.jsx +35 -0
  322. package/src/schemas/workspace/workspace.recordDialogs.views.jsx +257 -0
  323. package/src/schemas/workspace/workspace.selection.views.jsx +14 -0
  324. package/src/schemas/workspace/workspace.sourceReceipt.views.jsx +40 -0
  325. package/src/schemas/workspace/workspace.timePortal.views.jsx +56 -0
  326. package/src/schemas/workspace/workspace.tree.views.jsx +107 -0
  327. package/src/schemas/workspace/workspace.viewFormatting.js +172 -0
  328. package/src/schemas/workspace/workspace.views.jsx +210 -0
  329. package/src/source-settings/sourceSettings.model.js +7 -0
  330. package/src/sources/draft/draft.source.js +1 -0
  331. package/src/sources/github/github.loader.js +204 -0
  332. package/src/sources/github/github.permalink.js +1 -0
  333. package/src/sources/github/github.source.js +1 -0
  334. package/src/sources/github/github.transport.case.mjs +237 -0
  335. package/src/sources/github/github.transport.js +472 -0
  336. package/src/sources/local/local.source.js +1 -0
  337. package/src/sources/source.assetReferences.js +109 -0
  338. package/src/sources/source.boundaries.js +24 -0
  339. package/src/sources/source.identity.js +56 -0
  340. package/src/sources/source.model.case.mjs +26 -0
  341. package/src/sources/source.model.js +56 -0
  342. package/src/sources/source.presenter.js +66 -0
  343. package/src/sources/source.resolve.js +11 -0
  344. package/src/sources/static/static.source.js +1 -0
  345. package/src/sources/transport.policy.case.mjs +39 -0
  346. package/src/sources/transport.policy.js +81 -0
  347. package/src/storage/storage.policy.js +79 -0
  348. package/src/styles/app.css +8699 -0
  349. package/src/styles/responsive.css +10 -0
  350. package/src/styles/theme.css +4 -0
  351. package/src/styles/tokens.css +30 -0
  352. package/src/surfaces/audit/AuditSurface.js +1 -0
  353. package/src/surfaces/audit/audit.model.js +1 -0
  354. package/src/surfaces/audit/audit.render.js +1 -0
  355. package/src/surfaces/contracts.js +45 -0
  356. package/src/surfaces/create/CreateSurface.js +1 -0
  357. package/src/surfaces/create/create.model.js +1 -0
  358. package/src/surfaces/create/create.render.js +1 -0
  359. package/src/surfaces/detail/DetailSurface.js +1 -0
  360. package/src/surfaces/detail/detail.model.js +1 -0
  361. package/src/surfaces/detail/detail.render.js +1 -0
  362. package/src/surfaces/display-options/DisplayOptionsSurface.js +1 -0
  363. package/src/surfaces/display-options/displayOptions.model.js +1 -0
  364. package/src/surfaces/display-options/displayOptions.render.js +1 -0
  365. package/src/surfaces/edit/EditSurface.js +1 -0
  366. package/src/surfaces/edit/edit.model.js +1 -0
  367. package/src/surfaces/edit/edit.render.js +1 -0
  368. package/src/surfaces/feed/FeedSurface.js +1 -0
  369. package/src/surfaces/feed/feed.model.js +1 -0
  370. package/src/surfaces/feed/feed.render.js +1 -0
  371. package/src/surfaces/lineage/LineageSurface.js +1 -0
  372. package/src/surfaces/lineage/lineage.model.js +1 -0
  373. package/src/surfaces/lineage/lineage.render.js +1 -0
  374. package/src/surfaces/preview/PreviewSurface.js +1 -0
  375. package/src/surfaces/preview/preview.model.js +1 -0
  376. package/src/surfaces/preview/preview.render.js +1 -0
  377. package/src/surfaces/registry.js +58 -0
  378. package/src/surfaces/share/ShareSurface.js +1 -0
  379. package/src/surfaces/share/share.model.js +1 -0
  380. package/src/surfaces/share/share.render.js +1 -0
  381. package/src/surfaces/source-settings/SourceSettingsSurface.js +1 -0
  382. package/src/surfaces/source-settings/sourceSettings.model.js +1 -0
  383. package/src/surfaces/source-settings/sourceSettings.render.js +1 -0
  384. package/src/surfaces/surfaceContext.js +1 -0
  385. package/src/surfaces/tree/TreeSurface.js +1 -0
  386. package/src/surfaces/tree/tree.model.js +1 -0
  387. package/src/surfaces/tree/tree.render.js +1 -0
  388. package/src/tooling/portable/adapters/cli/cli.common-output.case.mjs +153 -0
  389. package/src/tooling/portable/adapters/cli/cli.handoff-sibling-allocation.case.mjs +52 -0
  390. package/src/tooling/portable/adapters/cli/cli.run.case.mjs +372 -0
  391. package/src/tooling/portable/adapters/cli/cli.summaryProjection.case.mjs +46 -0
  392. package/src/tooling/portable/audit/audit.capability.case.mjs +45 -0
  393. package/src/tooling/portable/fixtures/legacy-artifacts/collaboration/dogfood/001-tiinex-development-dogfood-collaboration-model.trace.fixture.txt +37 -0
  394. package/src/tooling/portable/fixtures/legacy-artifacts/handoff/tooling/001-v480-tooling-workflow-schema-enablement-handoff.trace.fixture.txt +108 -0
  395. package/src/tooling/portable/fixtures/legacy-artifacts/handoff/tooling/002-v481-tooling-recipient-relative-handoff-material-closure-planner-foundation-handoff.trace.fixture.txt +130 -0
  396. package/src/tooling/portable/fixtures/legacy-artifacts/loom/role/001-loom-role.trace.fixture.txt +61 -0
  397. package/src/tooling/portable/fixtures/legacy-artifacts/sigma/role/001-1-sigma-role.trace.fixture.txt +61 -0
  398. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-1-1-1-1-1-1-1-site-tooling-v474-loaded-parent-identity-evidence-closure-result.trace.fixture.txt +48 -0
  399. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-1-1-1-1-1-1-site-tooling-v474-loaded-parent-identity-evidence-closure.trace.fixture.txt +48 -0
  400. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-1-1-1-1-1-site-tooling-v473-portable-parent-authority-coherence-metadata-fidelity-closure-result.trace.fixture.txt +48 -0
  401. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-1-1-1-1-site-tooling-v473-portable-parent-authority-coherence-metadata-fidelity-closure.trace.fixture.txt +48 -0
  402. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-1-1-1-site-tooling-v472-portable-exact-authoring-fidelity-closure-result.trace.fixture.txt +48 -0
  403. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-1-1-site-tooling-v472-portable-exact-authoring-fidelity-closure.trace.fixture.txt +48 -0
  404. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-1-site-tooling-v471-portable-lineage-authoring-closure-result.trace.fixture.txt +48 -0
  405. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-site-tooling-v471-portable-lineage-authoring-closure.trace.fixture.txt +39 -0
  406. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/002-1-v475-canonical-artifact-envelope-reference-integrity-validation.trace.fixture.txt +43 -0
  407. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/003-1-v476-canonical-authority-binding-integrity-method-lineage-alloca.trace.fixture.txt +42 -0
  408. package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/027-handoff-package-workspace-archive-and-control-plane-minimality-audit.trace.fixture.txt +56 -0
  409. package/src/tooling/portable/fixtures/legacyArtifactFixtures.mjs +34 -0
  410. package/src/tooling/portable/grounding/grounding.capsule.case.mjs +65 -0
  411. package/src/tooling/portable/grounding/grounding.readiness.case.mjs +543 -0
  412. package/src/tooling/portable/grounding/grounding.semanticIntegration.case.mjs +131 -0
  413. package/src/tooling/portable/handoff/boundedWorkspaceRepresentation.case.mjs +103 -0
  414. package/src/tooling/portable/handoff/carrierLineage.fixedWidth.case.mjs +97 -0
  415. package/src/tooling/portable/handoff/coldStartQualification.case.mjs +293 -0
  416. package/src/tooling/portable/handoff/fixtures/027-invalid-audit-result.fixture.txt +192 -0
  417. package/src/tooling/portable/handoff/fixtures/027-invalid-return-handoff.fixture.txt +92 -0
  418. package/src/tooling/portable/handoff/fixtures/cold-start-qualification.v1.examples.json +60 -0
  419. package/src/tooling/portable/handoff/handoff.manufacture.case.mjs +293 -0
  420. package/src/tooling/portable/handoff/materialClosure.case.mjs +727 -0
  421. package/src/tooling/portable/handoff/multiRootManufacture.case.mjs +615 -0
  422. package/src/tooling/portable/handoff/operatorBridgeCore.case.mjs +205 -0
  423. package/src/tooling/portable/handoff/workspaceLandingPlan.case.mjs +143 -0
  424. package/src/tooling/portable/input/node.input.case.mjs +293 -0
  425. package/src/tooling/portable/lifecycle/lifecycle.readiness.case.mjs +179 -0
  426. package/src/tooling/portable/lineage/fixtures/lineage.integrity.repair-projection.v1.examples.json +605 -0
  427. package/src/tooling/portable/lineage/lineage.integrity.shared-capability.case.mjs +37 -0
  428. package/src/tooling/portable/lineage/publicationProviderReceipt.fixture.mjs +50 -0
  429. package/src/tooling/portable/package/fixtures/reference-relation-generation-authority.trace.md +84 -0
  430. package/src/tooling/portable/package/fixtures/tiinex.root.v1.package-authority.contract-fixture.md +64 -0
  431. package/src/tooling/portable/package/fixtures/tiinex.schema.generation.v1.generation-binding.contract-fixture.md +140 -0
  432. package/src/tooling/portable/package/fixtures/tiinex.schema.transition.companion.v1.contract-fixture.md +73 -0
  433. package/src/tooling/portable/package/fixtures/tiinex.semantic.package.v1.contract-fixture.md +147 -0
  434. package/src/tooling/portable/package/fixtures/tiinex.transition.definition.v1.package-contract-fixture.md +77 -0
  435. package/src/tooling/portable/providers/schema.providers.genericity.case.mjs +31 -0
  436. package/src/tooling/portable/reduction/reduction.preflight.case.mjs +298 -0
  437. package/src/tooling/portable/schema/fixtures/evidence-preservation-body.inheritance-record-fixture.md +65 -0
  438. package/src/tooling/portable/schema/fixtures/tiinex.portal.time.v1.contract-fixture.md +294 -0
  439. package/src/tooling/portable/schema/fixtures/tiinex.root.v1.contract-fixture.md +584 -0
  440. package/src/tooling/portable/schema/fixtures/tiinex.root.v1.machine-shape.contract-fixture.md +44 -0
  441. package/src/tooling/portable/schema/fixtures/tiinex.root.v1.ordinary-target.contract-fixture.md +630 -0
  442. package/src/tooling/portable/schema/fixtures/tiinex.schema.contract.v1.repeated-record.contract-fixture.md +69 -0
  443. package/src/tooling/portable/schema/fixtures/tiinex.schema.generation.v1.repeated-record.contract-fixture.md +98 -0
  444. package/src/tooling/portable/schema/fixtures/tiinex.schema.inheritance.v1.repeated-record.contract-fixture.md +58 -0
  445. package/src/tooling/portable/schema/fixtures/tiinex.task.v1.contract-fixture.md +165 -0
  446. package/src/tooling/portable/schema/fixtures/tiinex.transition.definition.v1.contract-fixture.md +744 -0
  447. package/src/tooling/portable/schema/fixtures/tiinex.transition.definition.v1.field-domain.contract-fixture.md +319 -0
  448. package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.relation.v1.schema.md +240 -0
  449. package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.schema.contract.v1.schema.md +391 -0
  450. package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.schema.generation.v1.schema.md +379 -0
  451. package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.schema.transition.companion.v1.schema.md +265 -0
  452. package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.semantic.package.v1.schema.md +402 -0
  453. package/src/transitions/canonical-schema-cache/52ecdea0a75893882ce282214d155f70e1309c2a/tiinex.topic.v1.schema.md +197 -0
  454. package/src/transitions/canonical-schema-cache/d69b8ff55a56b8cb9282b8684db6a938a4435b94/tiinex.root.v1.schema.md +797 -0
  455. package/src/transitions/canonical-schema-cache/d69b8ff55a56b8cb9282b8684db6a938a4435b94/tiinex.transition.definition.v1.schema.md +1062 -0
  456. package/src/transitions/canonicalTransition.packageContracts.js +22 -0
  457. package/src/transitions/canonicalTransition.productDefaults.js +105 -0
  458. package/src/transitions/canonicalTransition.schemaCache.case.mjs +45 -0
  459. package/src/transitions/canonicalTransition.schemaCache.js +81 -0
  460. package/src/transitions/canonicalTransition.semanticPackage.js +146 -0
  461. package/src/transitions/record.transitions.case.mjs +88 -0
  462. package/src/transitions/transition.authorityRepresentation.js +55 -0
  463. package/src/transitions/transition.availabilityPlanner.js +376 -0
  464. package/src/transitions/transition.availabilitySemantics.js +150 -0
  465. package/src/transitions/transition.definitionReadProjection.js +107 -0
  466. package/src/transitions/transition.definitionRegistry.js +355 -0
  467. package/src/transitions/transition.definitionRegistryAggregation.js +21 -0
  468. package/src/transitions/transition.definitions.js +46 -0
  469. package/src/transitions/transition.explicitGenerationPlanner.js +58 -0
  470. package/src/transitions/transition.generationInputPlanner.js +19 -0
  471. package/src/transitions/transition.interpretationMaterializer.js +2 -0
  472. package/src/transitions/transition.invocationBindingPacket.js +52 -0
  473. package/src/transitions/transition.invocationBindingPlanner.js +467 -0
  474. package/src/transitions/transition.legacyShorthand.js +133 -0
  475. package/src/transitions/transition.localArtifactMaterializers.js +16 -0
  476. package/src/transitions/transition.localCreateCapability.js +111 -0
  477. package/src/transitions/transition.outputMaterializationPlanner.js +336 -0
  478. package/src/transitions/transition.parentReference.js +90 -0
  479. package/src/transitions/transition.presentation.js +43 -0
  480. package/src/transitions/transition.productPreparation.js +377 -0
  481. package/src/transitions/transition.productPresentation.browser.js +28 -0
  482. package/src/transitions/transition.productPresentation.js +55 -0
  483. package/src/transitions/transition.referenceCreateCapability.js +119 -0
  484. package/src/transitions/transition.referenceTarget.js +50 -0
  485. package/src/transitions/transition.relationMaterializer.js +2 -0
  486. package/src/transitions/transition.resultSemantics.js +453 -0
  487. package/src/transitions/transition.taskMaterializer.js +2 -0
  488. package/src/transitions/transition.topicMaterializer.js +2 -0
  489. package/src/transitions/transition.validate.case.mjs +58 -0
  490. package/src/ui/cards/ArtifactCard.js +1 -0
  491. package/src/ui/cards/SchemaCard.js +1 -0
  492. package/src/ui/cards/SourceCard.js +1 -0
  493. package/src/ui/dialog.presenter.js +24 -0
  494. package/src/ui/feedback/DegradedNotice.js +1 -0
  495. package/src/ui/feedback/EmptyState.js +1 -0
  496. package/src/ui/feedback/ValidationNotice.js +1 -0
  497. package/src/ui/forms/FormRenderer.js +1 -0
  498. package/src/ui/forms/fields/MarkdownField.js +1 -0
  499. package/src/ui/forms/fields/SelectField.js +1 -0
  500. package/src/ui/forms/fields/SourcePickerField.js +1 -0
  501. package/src/ui/forms/fields/TextField.js +1 -0
  502. package/src/ui/icon.paths.js +37 -0
  503. package/src/ui/layout/Panel.js +1 -0
  504. package/src/ui/layout/ResponsiveFrame.js +1 -0
  505. package/src/ui/layout/SplitView.js +1 -0
  506. package/src/ui/layout/Stack.js +1 -0
  507. package/src/ui/panels/DetailPanel.js +1 -0
  508. package/src/ui/panels/LineagePanel.js +1 -0
  509. package/src/ui/panels/SourcePanel.js +1 -0
  510. package/src/ui/primitives/Badge.js +1 -0
  511. package/src/ui/primitives/Badge.jsx +5 -0
  512. package/src/ui/primitives/Button.js +1 -0
  513. package/src/ui/primitives/Button.jsx +12 -0
  514. package/src/ui/primitives/Card.js +1 -0
  515. package/src/ui/primitives/Field.js +1 -0
  516. package/src/ui/primitives/Field.jsx +21 -0
  517. package/src/ui/primitives/Icon.jsx +90 -0
  518. package/src/ui/primitives/Modal.jsx +27 -0
  519. package/src/validation/i18n.js +37 -0
  520. package/src/validation/validateArtifact.case.mjs +41 -0
  521. package/src/verses/column/ColumnVerse.js +1 -0
  522. package/src/verses/column/column.model.js +6 -0
  523. package/src/verses/column/column.project.js +7 -0
  524. package/src/verses/context.js +26 -0
  525. package/src/verses/contracts.js +1 -0
  526. package/src/verses/hostRegistry.js +47 -0
  527. package/src/verses/registry.js +22 -0
  528. package/src/verses/universe.model.js +8 -0
  529. package/src/verses/universe.presenter.js +8 -0
  530. package/src/verses/universe.project.js +12 -0
  531. package/src/viewer.js +34 -0
  532. package/src/workspace.model.js +5 -0
  533. package/src/workspaces/workspace.actions.js +1 -0
  534. package/src/workspaces/workspace.artifactActions.js +56 -0
  535. package/src/workspaces/workspace.auditView.js +153 -0
  536. package/src/workspaces/workspace.candidates.js +149 -0
  537. package/src/workspaces/workspace.config.js +153 -0
  538. package/src/workspaces/workspace.configuredSource.js +68 -0
  539. package/src/workspaces/workspace.discoveryProgress.js +34 -0
  540. package/src/workspaces/workspace.discoveryView.js +386 -0
  541. package/src/workspaces/workspace.displayFilters.js +63 -0
  542. package/src/workspaces/workspace.displayOptions.js +58 -0
  543. package/src/workspaces/workspace.emptyStateCopy.js +24 -0
  544. package/src/workspaces/workspace.entrypointLifecycle.js +131 -0
  545. package/src/workspaces/workspace.entrypointViewIntent.js +83 -0
  546. package/src/workspaces/workspace.entrypoints.js +157 -0
  547. package/src/workspaces/workspace.feedSort.js +152 -0
  548. package/src/workspaces/workspace.import.js +212 -0
  549. package/src/workspaces/workspace.importConflicts.js +200 -0
  550. package/src/workspaces/workspace.importLifecycle.case.mjs +103 -0
  551. package/src/workspaces/workspace.lifecycle.case.mjs +353 -0
  552. package/src/workspaces/workspace.lifecycle.js +357 -0
  553. package/src/workspaces/workspace.lineageView.js +244 -0
  554. package/src/workspaces/workspace.localSourceLifecycle.js +91 -0
  555. package/src/workspaces/workspace.materialLedger.js +110 -0
  556. package/src/workspaces/workspace.materialReconciliation.case.mjs +164 -0
  557. package/src/workspaces/workspace.materialReconciliation.js +390 -0
  558. package/src/workspaces/workspace.memberIdentity.js +140 -0
  559. package/src/workspaces/workspace.model.js +2 -0
  560. package/src/workspaces/workspace.navigation.js +20 -0
  561. package/src/workspaces/workspace.openSemantics.js +33 -0
  562. package/src/workspaces/workspace.pathTree.js +132 -0
  563. package/src/workspaces/workspace.persistence.case.mjs +271 -0
  564. package/src/workspaces/workspace.persistence.js +469 -0
  565. package/src/workspaces/workspace.persistenceCache.js +41 -0
  566. package/src/workspaces/workspace.persistenceClear.js +45 -0
  567. package/src/workspaces/workspace.persistencePresentation.js +93 -0
  568. package/src/workspaces/workspace.persistenceRecovery.js +147 -0
  569. package/src/workspaces/workspace.persistenceRouteCache.js +82 -0
  570. package/src/workspaces/workspace.publicationReceipts.case.mjs +36 -0
  571. package/src/workspaces/workspace.publicationReceipts.js +56 -0
  572. package/src/workspaces/workspace.recoverabilityView.js +264 -0
  573. package/src/workspaces/workspace.route.js +432 -0
  574. package/src/workspaces/workspace.runtimeCanonical.js +18 -0
  575. package/src/workspaces/workspace.sourceMaterial.js +71 -0
  576. package/src/workspaces/workspace.sourceRecordPath.js +5 -0
  577. package/src/workspaces/workspace.sourceRecords.js +75 -0
  578. package/src/workspaces/workspace.store.js +3 -0
  579. package/src/workspaces/workspace.summary.js +116 -0
  580. package/src/workspaces/workspace.timePortal.js +137 -0
@@ -0,0 +1,237 @@
1
+ import { buildPublicationPlan, buildPublicationResult } from '@tiinex/core/publication/publication.contract.js';
2
+ import { buildPublicationPreflight } from '@tiinex/core/publication/publication.preflight.js';
3
+ import { GITHUB_ISSUE_BODY_TARGET_KIND, GITHUB_ISSUE_COMMENT_TARGET_KIND } from '@tiinex/core/publication/publication.targetContract.js';
4
+ import { normalizeGithubRepository, parseExactGithubIssueTarget, sameGithubRepository } from '@tiinex/core/sources/github/github.issueTarget.js';
5
+ import { readExactGithubIssuePublicationRepresentation } from '../adapters/github/github.publicationRead.js';
6
+ import { sha256Hex, utf8Bytes } from '@tiinex/core/export/package.bytes.js';
7
+
8
+ export const GITHUB_PUBLICATION_MODE = Object.freeze({
9
+ createIssue: 'create-issue',
10
+ createComment: 'create-comment',
11
+ updateIssue: 'update-issue',
12
+ updateComment: 'update-comment'
13
+ });
14
+
15
+ export const GITHUB_PUBLICATION_HUMAN_MUTATION_ATTESTATION = 'human-github-web-mutation-confirmation';
16
+
17
+ export function buildWorkspaceGithubPublicationPreflight(workspace = {}) { return buildPublicationPreflight(workspace); }
18
+
19
+ export function buildWorkspaceGithubPublicationProduct(workspace = {}, input = {}, options = {}) {
20
+ const preflight = options.preflight || buildWorkspaceGithubPublicationPreflight(workspace);
21
+ const mode = normalizeMode(input.mode);
22
+ const modeSpec = modeSpecification(mode);
23
+ const recordId = String(input.recordId || '').trim();
24
+ const repository = String(input.repository || '');
25
+ const targetInput = String(input.targetInput || '');
26
+ const destination = {
27
+ provider: 'github',
28
+ repository,
29
+ targetKind: modeSpec.targetKind,
30
+ ...(modeSpec.targetField ? { [modeSpec.targetField]: targetInput } : {})
31
+ };
32
+ const plan = buildPublicationPlan(workspace, { recordId, destination, mutationPolicy: modeSpec.mutationPolicy, preflight });
33
+ const openUrl = publicationOpenUrl(plan);
34
+ const verificationTarget = String(input.finalTarget || (plan.mutationPolicy === 'update-known' ? plan.destination?.externalTarget || '' : ''));
35
+ const mutationTargetQualification = qualifyMutationTarget(plan, verificationTarget);
36
+ const latestReceipt = (Array.isArray(workspace.publicationReceipts) ? workspace.publicationReceipts : []).find((entry) => String(entry?.receipt?.localInputId || '') === recordId) || null;
37
+ return Object.freeze({
38
+ schema: 'tiinex.site.githubPublicationProduct.v1',
39
+ mode,
40
+ modes: publicationModes(),
41
+ eligibleRecords: preflight.publishableLocalDrafts || [],
42
+ preflight,
43
+ plan,
44
+ openUrl,
45
+ verificationTarget,
46
+ mutationTarget: mutationTargetQualification.target || null,
47
+ mutationTargetQualified: mutationTargetQualification.ok === true,
48
+ latestReceipt,
49
+ targetLabel: modeSpec.targetLabel,
50
+ targetRequired: Boolean(modeSpec.targetField),
51
+ targetPlaceholder: modeSpec.targetPlaceholder,
52
+ finalTargetRequired: plan.mutationPolicy !== 'update-known',
53
+ boundary: 'Guided browser routine only. Shared publication plan/result own payload and success; Site performs no GitHub mutation.'
54
+ });
55
+ }
56
+
57
+ export function publicationProgressFor(plan = {}, verificationTarget = '', progress = {}) {
58
+ const current = String(plan?.planSha256 || '');
59
+ const targetQualification = qualifyMutationTarget(plan, verificationTarget);
60
+ const mutationAttestation = targetQualification.ok ? qualifiedHumanMutationAttestation(current, targetQualification.target, progress.mutationAttestation) : null;
61
+ return Object.freeze({
62
+ ...progress,
63
+ mutationAttestation,
64
+ copied: Boolean(current && progress.copiedPlanSha256 === current),
65
+ opened: Boolean(current && progress.openedPlanSha256 === current),
66
+ attested: Boolean(mutationAttestation),
67
+ verified: Boolean(current && progress.verificationPlanSha256 === current && progress.result?.status === 'success' && targetQualification.ok && sameExactMutationTarget(targetQualification.target, progress.result?.remoteTarget))
68
+ });
69
+ }
70
+
71
+ export function confirmWorkspaceGithubPublicationMutation(plan = {}, options = {}) {
72
+ const planSha256 = String(plan?.planSha256 || '').trim();
73
+ if (plan.status !== 'ready' || !planSha256) return Object.freeze({ ok: false, error: 'publication.plan.not-ready', mutationAttestation: null, notice: 'Publication plan is not ready for human mutation confirmation.' });
74
+ const targetQualification = qualifyMutationTarget(plan, options.finalTarget);
75
+ if (!targetQualification.ok) return Object.freeze({ ok: false, error: targetQualification.error, mutationAttestation: null, notice: targetQualification.notice });
76
+ const mutationAttestation = Object.freeze({
77
+ schema: 'tiinex.site.githubPublicationHumanMutationAttestation.v2',
78
+ type: GITHUB_PUBLICATION_HUMAN_MUTATION_ATTESTATION,
79
+ planSha256,
80
+ mutationTarget: targetQualification.target,
81
+ confirmedAt: nowIso(options.clock),
82
+ boundary: 'Human confirms they performed the GitHub web mutation for this exact publication plan at this exact qualified GitHub target. Tiinex did not perform a hidden/API write.'
83
+ });
84
+ return Object.freeze({ ok: true, mutationAttestation, notice: 'Human GitHub mutation confirmed for this exact publication plan and exact target.' });
85
+ }
86
+
87
+ export async function copyWorkspaceGithubPublicationPayload(plan = {}, options = {}) {
88
+ if (plan.status !== 'ready') return Object.freeze({ ok: false, error: 'publication.plan.not-ready', planSha256: plan.planSha256 || '', notice: 'Publication plan is not ready.' });
89
+ const clipboard = options.clipboard;
90
+ if (!clipboard || typeof clipboard.writeText !== 'function') return Object.freeze({ ok: false, error: 'clipboard.unavailable', planSha256: plan.planSha256 || '', notice: 'Clipboard is unavailable.' });
91
+ try {
92
+ await clipboard.writeText(String(plan.outboundPayload?.content || ''));
93
+ return Object.freeze({ ok: true, planSha256: plan.planSha256 || '', payloadSha256: plan.outboundPayload?.sha256 || '', notice: 'Exact publication payload copied.' });
94
+ } catch (exception) {
95
+ return Object.freeze({ ok: false, error: 'clipboard.write-failed', exception, planSha256: plan.planSha256 || '', notice: 'Could not copy publication payload.' });
96
+ }
97
+ }
98
+
99
+ export function openWorkspaceGithubPublicationTarget(plan = {}, options = {}) {
100
+ if (plan.status !== 'ready') return Object.freeze({ ok: false, error: 'publication.plan.not-ready', planSha256: plan.planSha256 || '', notice: 'Publication plan is not ready.' });
101
+ const url = publicationOpenUrl(plan);
102
+ if (!url) return Object.freeze({ ok: false, error: 'publication.open-target.unavailable', planSha256: plan.planSha256 || '', notice: 'GitHub target is not qualified for opening.' });
103
+ const open = options.open || options.window?.open?.bind(options.window);
104
+ if (typeof open !== 'function') return Object.freeze({ ok: false, error: 'publication.open.unavailable', planSha256: plan.planSha256 || '', url, notice: 'Browser open is unavailable.' });
105
+ try {
106
+ const opened = open(url, '_blank', 'noopener,noreferrer');
107
+ if (opened === null || opened === false) return Object.freeze({ ok: false, error: 'publication.open.blocked', planSha256: plan.planSha256 || '', url, notice: 'GitHub window could not be opened.' });
108
+ return Object.freeze({ ok: true, planSha256: plan.planSha256 || '', url, notice: 'GitHub opened. This is not publication success.' });
109
+ } catch (exception) {
110
+ return Object.freeze({ ok: false, error: 'publication.open.failed', exception, planSha256: plan.planSha256 || '', url, notice: 'GitHub window could not be opened.' });
111
+ }
112
+ }
113
+
114
+ export async function verifyWorkspaceGithubPublication(plan = {}, input = {}) {
115
+ if (plan.status !== 'ready') return Object.freeze({ ok: false, error: 'publication.plan.not-ready', result: buildPublicationResult(plan, { state: 'failure', verificationStatus: 'not-run' }), notice: 'Publication plan is not ready.' });
116
+ const targetQualification = qualifyMutationTarget(plan, input.finalTarget);
117
+ if (!targetQualification.ok) {
118
+ const result = buildPublicationResult(plan, { state: 'failure', verificationStatus: 'failed', sourceTarget: { adapterId: 'github', targetKind: plan.destination?.targetKind || '', inputTarget: String(input.finalTarget || '') } });
119
+ return Object.freeze({ ok: false, error: targetQualification.error, result, executionAttestation: null, notice: targetQualification.notice });
120
+ }
121
+ const exactTarget = targetQualification.parsed;
122
+ const executionAttestation = qualifiedHumanMutationAttestation(String(plan.planSha256 || ''), targetQualification.target, input.mutationAttestation);
123
+ if (!executionAttestation) {
124
+ const result = buildPublicationResult(plan, { state: 'failure', verificationStatus: 'not-run', sourceTarget: { adapterId: 'github', targetKind: exactTarget.targetKind, inputTarget: exactTarget.inputTarget } });
125
+ return Object.freeze({
126
+ ok: false,
127
+ error: 'publication.verify.human-mutation-attestation-required',
128
+ result,
129
+ executionAttestation: null,
130
+ notice: 'Confirm that you posted or updated this exact payload at this exact GitHub target before verification. Copy/Open are not write evidence.'
131
+ });
132
+ }
133
+ try {
134
+ const observed = await readExactGithubIssuePublicationRepresentation(exactTarget, { fetchImpl: input.fetchImpl });
135
+ const verifiedPayloadSha256 = sha256Hex(utf8Bytes(String(observed.content || '')));
136
+ const result = buildPublicationResult(plan, {
137
+ state: 'success',
138
+ verificationStatus: 'verified',
139
+ verifiedPayloadSha256,
140
+ providerReceiptId: observed.providerReceiptId || '',
141
+ sourceTarget: { adapterId: 'github', targetKind: exactTarget.targetKind, inputTarget: exactTarget.inputTarget },
142
+ verification: { status: 'verified', method: observed.method || 'github-browser-issue-reader-exact-body', observedAt: observed.observedAt || nowIso(input.clock), note: 'Exact GitHub issue/comment body read after shared v446 target qualification.' }
143
+ });
144
+ return Object.freeze({ ok: result.status === 'success' && Boolean(result.sourceBinding), result, observed, executionAttestation, notice: result.status === 'success' ? 'Human-guided GitHub publication verified exactly.' : 'GitHub target was read, but exact publication verification failed.' });
145
+ } catch (exception) {
146
+ const result = buildPublicationResult(plan, { state: 'partial', verificationStatus: 'unavailable', sourceTarget: { adapterId: 'github', targetKind: exactTarget.targetKind, inputTarget: exactTarget.inputTarget }, verification: { status: 'unavailable', method: 'github-browser-issue-reader', observedAt: nowIso(input.clock), note: exception?.message || 'GitHub read unavailable.' } });
147
+ return Object.freeze({ ok: false, error: 'publication.verify.read-unavailable', exception, result, executionAttestation, notice: 'GitHub verification is unavailable; no source binding was created.' });
148
+ }
149
+ }
150
+
151
+ export function publicationOpenUrl(plan = {}) {
152
+ if (plan.status !== 'ready' || plan.destination?.provider !== 'github') return '';
153
+ const rawRepo = String(plan.destination?.repository || '').trim();
154
+ const repo = normalizeGithubRepository(rawRepo);
155
+ if (!repo) return '';
156
+ if (plan.mutationPolicy === 'create-new' && plan.destination?.targetKind === GITHUB_ISSUE_BODY_TARGET_KIND) return `https://github.com/${rawRepo}/issues/new`;
157
+ if (plan.mutationPolicy === 'create-comment' && plan.destination?.targetKind === GITHUB_ISSUE_COMMENT_TARGET_KIND) {
158
+ const parsed = parseExactGithubIssueTarget(plan.destination?.containerTarget || '');
159
+ return parsed.ok ? parsed.issueTarget : '';
160
+ }
161
+ if (plan.mutationPolicy === 'update-known') {
162
+ const parsed = parseExactGithubIssueTarget(plan.destination?.externalTarget || '');
163
+ return parsed.ok ? parsed.inputTarget : '';
164
+ }
165
+ return '';
166
+ }
167
+
168
+ function publicationModes() {
169
+ return Object.freeze([
170
+ Object.freeze({ id: GITHUB_PUBLICATION_MODE.createIssue, label: 'Create new issue' }),
171
+ Object.freeze({ id: GITHUB_PUBLICATION_MODE.createComment, label: 'Create comment' }),
172
+ Object.freeze({ id: GITHUB_PUBLICATION_MODE.updateIssue, label: 'Update known issue' }),
173
+ Object.freeze({ id: GITHUB_PUBLICATION_MODE.updateComment, label: 'Update known comment' })
174
+ ]);
175
+ }
176
+ function normalizeMode(value = '') { return Object.values(GITHUB_PUBLICATION_MODE).includes(value) ? value : GITHUB_PUBLICATION_MODE.createIssue; }
177
+ function modeSpecification(mode) {
178
+ if (mode === GITHUB_PUBLICATION_MODE.createComment) return { targetKind: GITHUB_ISSUE_COMMENT_TARGET_KIND, mutationPolicy: 'create-comment', targetField: 'containerTarget', targetLabel: 'Parent issue URL', targetPlaceholder: 'https://github.com/owner/repo/issues/123' };
179
+ if (mode === GITHUB_PUBLICATION_MODE.updateIssue) return { targetKind: GITHUB_ISSUE_BODY_TARGET_KIND, mutationPolicy: 'update-known', targetField: 'externalTarget', targetLabel: 'Exact issue URL', targetPlaceholder: 'https://github.com/owner/repo/issues/123' };
180
+ if (mode === GITHUB_PUBLICATION_MODE.updateComment) return { targetKind: GITHUB_ISSUE_COMMENT_TARGET_KIND, mutationPolicy: 'update-known', targetField: 'externalTarget', targetLabel: 'Exact comment permalink', targetPlaceholder: 'https://github.com/owner/repo/issues/123#issuecomment-456' };
181
+ return { targetKind: GITHUB_ISSUE_BODY_TARGET_KIND, mutationPolicy: 'create-new', targetField: '', targetLabel: 'Final issue URL after posting', targetPlaceholder: '' };
182
+ }
183
+ function qualifyMutationTarget(plan = {}, rawTarget = '') {
184
+ if (plan.status !== 'ready') return Object.freeze({ ok: false, error: 'publication.plan.not-ready', target: null, parsed: null, notice: 'Publication plan is not ready.' });
185
+ const knownTarget = plan.mutationPolicy === 'update-known' ? String(plan.destination?.externalTarget || '') : '';
186
+ const raw = String(rawTarget || knownTarget || '');
187
+ if (!raw) return Object.freeze({ ok: false, error: 'publication.attestation.target-required', target: null, parsed: null, notice: 'Supply the exact GitHub issue/comment target before confirming the human mutation.' });
188
+ const parsed = parseExactGithubIssueTarget(raw);
189
+ if (!parsed.ok) return Object.freeze({ ok: false, error: 'publication.attestation.target-invalid', target: null, parsed: null, notice: 'Mutation confirmation requires one exact supported GitHub issue/comment target.' });
190
+ if (parsed.targetKind !== String(plan.destination?.targetKind || '')) return Object.freeze({ ok: false, error: 'publication.attestation.target-kind-mismatch', target: null, parsed, notice: 'Mutation target kind differs from the publication plan.' });
191
+ if (!sameGithubRepository(parsed.repository, plan.destination?.repository || '')) return Object.freeze({ ok: false, error: 'publication.attestation.target-repo-mismatch', target: null, parsed, notice: 'Mutation target belongs to a different repository than the publication plan.' });
192
+ if (plan.mutationPolicy === 'create-comment') {
193
+ const container = parseExactGithubIssueTarget(plan.destination?.containerTarget || '');
194
+ if (!container.ok || parsed.issueTarget !== container.issueTarget) return Object.freeze({ ok: false, error: 'publication.attestation.target-container-mismatch', target: null, parsed, notice: 'Mutation comment target belongs to a different issue than the declared comment container.' });
195
+ }
196
+ if (plan.mutationPolicy === 'update-known') {
197
+ const expected = parseExactGithubIssueTarget(plan.destination?.externalTarget || '');
198
+ if (!expected.ok || parsed.inputTarget !== expected.inputTarget || parsed.targetKind !== expected.targetKind) return Object.freeze({ ok: false, error: 'publication.attestation.target-plan-mismatch', target: null, parsed, notice: 'Mutation confirmation must bind the exact known GitHub target already qualified by the publication plan.' });
199
+ }
200
+ const target = exactMutationTargetProjection(parsed);
201
+ return Object.freeze({ ok: true, target, parsed, error: '', notice: '' });
202
+ }
203
+ function exactMutationTargetProjection(parsed = {}) {
204
+ return Object.freeze({
205
+ provider: 'github',
206
+ targetKind: String(parsed.targetKind || ''),
207
+ inputTarget: String(parsed.inputTarget || ''),
208
+ repository: String(parsed.repository || ''),
209
+ issueNumberLexeme: String(parsed.issueNumber || ''),
210
+ commentId: String(parsed.commentId || ''),
211
+ issueTarget: String(parsed.issueTarget || '')
212
+ });
213
+ }
214
+ function sameExactMutationTarget(a = null, b = null) {
215
+ if (!a || !b) return false;
216
+ return String(a.targetKind || '') === String(b.targetKind || '') && String(a.inputTarget || '') === String(b.inputTarget || '');
217
+ }
218
+ function qualifiedHumanMutationAttestation(planSha256 = '', exactTarget = null, value = null) {
219
+ const current = String(planSha256 || '').trim();
220
+ if (!current || !exactTarget || !value || typeof value !== 'object') return null;
221
+ if (String(value.type || '') !== GITHUB_PUBLICATION_HUMAN_MUTATION_ATTESTATION) return null;
222
+ if (String(value.planSha256 || '') !== current) return null;
223
+ if (!sameExactMutationTarget(value.mutationTarget, exactTarget)) return null;
224
+ const parsed = parseExactGithubIssueTarget(value.mutationTarget?.inputTarget || '');
225
+ if (!parsed.ok || parsed.targetKind !== String(value.mutationTarget?.targetKind || '') || parsed.inputTarget !== String(value.mutationTarget?.inputTarget || '')) return null;
226
+ const confirmedAt = String(value.confirmedAt || '').trim();
227
+ if (!confirmedAt) return null;
228
+ return Object.freeze({
229
+ schema: 'tiinex.site.githubPublicationHumanMutationAttestation.v2',
230
+ type: GITHUB_PUBLICATION_HUMAN_MUTATION_ATTESTATION,
231
+ planSha256: current,
232
+ mutationTarget: exactMutationTargetProjection(parsed),
233
+ confirmedAt,
234
+ boundary: String(value.boundary || 'Human-confirmed GitHub web mutation for the exact plan at the exact qualified target; Tiinex did not perform a hidden/API write.')
235
+ });
236
+ }
237
+ function nowIso(clock) { return typeof clock === 'function' ? new Date(clock()).toISOString() : new Date().toISOString(); }
@@ -0,0 +1,56 @@
1
+ import { prepareWorkspaceHandoffExport } from '../export/handoff.plan.js';
2
+ import { exportPackageZipBlob } from '@tiinex/core/export/package.zip.js';
3
+
4
+ export function executeWorkspaceHandoffExportCommand(input = {}) {
5
+ const workspace = input.workspace;
6
+ if (!workspace) return { ok: false, error: 'workspace.missing', notice: 'No workspace to export.' };
7
+ const preparation = prepareWorkspaceHandoffExport(workspace, {
8
+ clock: input.clock,
9
+ includeDegraded: true
10
+ });
11
+ if (!preparation.executable) {
12
+ const reason = firstBlockingFinding(preparation.inspection?.findings || preparation.bundle?.findings || []);
13
+ return { ok: false, error: 'export.handoff.blocked', preparation, notice: reason ? `Handoff package blocked: ${reason}` : 'Handoff package is blocked by package inspection.' };
14
+ }
15
+ try {
16
+ const download = input.download || exportWorkspaceHandoffDownload;
17
+ const result = download(workspace, input.document || globalThis.document, input.window || globalThis.window || globalThis, preparation);
18
+ return {
19
+ ok: true,
20
+ preparation,
21
+ freshness: Object.freeze({ source: 'execution-workspace', workspaceId: String(workspace.id || ''), recordCount: Array.isArray(workspace.records) ? workspace.records.length : 0, assetCount: Array.isArray(workspace.assets) ? workspace.assets.length : 0 }),
22
+ bundle: preparation.bundle,
23
+ filename: result.filename,
24
+ notice: `Handoff package ${preparation.status}: ${preparation.bundle.counts.files} governed file${preparation.bundle.counts.files === 1 ? '' : 's'} · ${preparation.bundle.counts.localDraftFiles} local artifact${preparation.bundle.counts.localDraftFiles === 1 ? '' : 's'} · ${preparation.bundle.counts.sourceReferenceFiles + preparation.bundle.counts.assetReferenceFiles} source reference${preparation.bundle.counts.sourceReferenceFiles + preparation.bundle.counts.assetReferenceFiles === 1 ? '' : 's'}.`
25
+ };
26
+ } catch (error) {
27
+ return { ok: false, error: 'export.handoff.failed', exception: error, preparation, notice: 'Could not build or download Handoff package.' };
28
+ }
29
+ }
30
+
31
+ export function exportWorkspaceHandoffDownload(workspace = {}, doc = globalThis.document, win = globalThis.window || globalThis, preparation = null) {
32
+ const prepared = preparation || prepareWorkspaceHandoffExport(workspace);
33
+ if (!prepared.executable || prepared.inspection?.status !== 'valid') throw new Error('handoff-package-not-valid');
34
+ const blob = exportPackageZipBlob(prepared.bundle);
35
+ const url = win.URL.createObjectURL(blob);
36
+ const link = doc.createElement('a');
37
+ link.href = url;
38
+ link.download = handoffPackageFilename(workspace, prepared.bundle);
39
+ link.rel = 'noopener';
40
+ doc.body.appendChild(link);
41
+ link.click();
42
+ link.remove();
43
+ win.setTimeout(() => win.URL.revokeObjectURL(url), 1000);
44
+ return Object.freeze({ filename: link.download, bundle: prepared.bundle, inspection: prepared.inspection });
45
+ }
46
+
47
+ export function handoffPackageFilename(workspace = {}, bundle = {}) {
48
+ const slug = String(workspace.title || workspace.name || workspace.id || 'workspace').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 48) || 'workspace';
49
+ const stamp = String(bundle.builtAt || new Date().toISOString()).replace(/[^0-9]/g, '').slice(0, 14) || 'session';
50
+ return `tiinex-handoff-${slug}-${stamp}.zip`;
51
+ }
52
+
53
+ function firstBlockingFinding(findings = []) {
54
+ const item = (Array.isArray(findings) ? findings : []).find((finding) => finding?.severity === 'error') || (Array.isArray(findings) ? findings : [])[0];
55
+ return String(item?.message || '').trim();
56
+ }
@@ -0,0 +1,9 @@
1
+ export function workspaceHomeHref(workspaceConfig = {}, locationLike = null) {
2
+ const location = locationLike || globalThis.location || { href: '', pathname: '/', search: '' };
3
+ const identity = workspaceConfig?.viewerIdentity || {};
4
+ const configured = String(identity.workspaceHome || '').trim();
5
+ const publicViewer = String(identity.publicViewerUrl || '').trim();
6
+ return resolveHomeValue(configured, location) || resolveHomeValue(publicViewer, location) || cleanViewerHref(location);
7
+ }
8
+ function resolveHomeValue(value = '', location = {}) { const text = String(value || '').trim(); if (!text || /^(javascript|data|blob):/i.test(text)) return ''; if (text.startsWith('#')) return `${location.pathname || '/'}${location.search || ''}${text}`; try { return new URL(text, location.href || 'http://localhost/').href; } catch (_) { return ''; } }
9
+ function cleanViewerHref(location = {}) { return `${location.pathname || '/'}${location.search || ''}`; }
@@ -0,0 +1,113 @@
1
+ import { hydrateUiWorkspace } from './recordUi.js';
2
+ import { workspaceColumnCapacity, workspaceWindowFor } from './workspaceWindow.js';
3
+ import { qualifiedSchemaFilterValue } from '../workspaces/workspace.displayFilters.js';
4
+ import { normalizeTimePortalView } from '../workspaces/workspace.timePortal.js';
5
+ import { resolveWorkspaceEntrypointViewIntent } from '../workspaces/workspace.entrypointViewIntent.js';
6
+
7
+ const DEFAULT_WORKSPACE_VIEW = Object.freeze({ universe: 'column', workspaceVerse: 'feed', reader: 'scan', query: '', layoutMode: 'expanded' });
8
+
9
+ export function defaultWorkspaceView() {
10
+ return Object.assign({}, DEFAULT_WORKSPACE_VIEW);
11
+ }
12
+
13
+ export function activeWorkspaceViewFor(state = {}, workspaceId = '') {
14
+ const id = String(workspaceId || '').trim();
15
+ const stored = id && state.workspaceViews && typeof state.workspaceViews === 'object' ? state.workspaceViews[id] : null;
16
+ if (stored && typeof stored === 'object') return normalizeWorkspaceView(stored);
17
+ if (id && id === state.activeWorkspaceId && state.view && typeof state.view === 'object') return normalizeWorkspaceView(state.view);
18
+ return defaultWorkspaceView();
19
+ }
20
+
21
+ export function workspaceLayoutModeFor(state = {}, workspaceId = '') {
22
+ return activeWorkspaceViewFor(state, workspaceId).layoutMode === 'compact' ? 'compact' : 'expanded';
23
+ }
24
+
25
+ export function stateForWorkspaceSurface(state = {}, workspaceId = '') {
26
+ return Object.assign({}, state, { view: activeWorkspaceViewFor(state, workspaceId) });
27
+ }
28
+
29
+ export function stateWithWorkspaceViewPatch(state = {}, workspaceId = '', patch = {}) {
30
+ const id = String(workspaceId || state.activeWorkspaceId || '').trim();
31
+ if (!id) return Object.assign({}, state, { view: normalizeWorkspaceView(Object.assign({}, state.view || {}, patch || {})) });
32
+ return stateWithWorkspaceView(state, id, normalizeWorkspaceView(Object.assign({}, activeWorkspaceViewFor(state, id), patch || {})));
33
+ }
34
+
35
+ export function stateWithWorkspaceViewUpdate(state = {}, workspaceId = '', updater = null) {
36
+ const id = String(workspaceId || state.activeWorkspaceId || '').trim();
37
+ const currentView = activeWorkspaceViewFor(state, id);
38
+ const nextView = typeof updater === 'function' ? updater(currentView) : currentView;
39
+ return stateWithWorkspaceView(state, id, normalizeWorkspaceView(nextView));
40
+ }
41
+
42
+ export function stateWithWorkspaceLayoutMode(state = {}, workspaceId = '', layoutMode = 'expanded') {
43
+ return stateWithWorkspaceViewPatch(state, workspaceId, { layoutMode: layoutMode === 'compact' ? 'compact' : 'expanded' });
44
+ }
45
+
46
+ export function stateWithActiveWorkspace(state = {}, workspaceId = '') {
47
+ const id = String(workspaceId || '').trim();
48
+ const workspaces = Array.isArray(state.workspaces) ? state.workspaces : [];
49
+ if (!id || !workspaces.some((workspace) => workspace.id === id)) return state;
50
+ const previousId = String(state.activeWorkspaceId || '').trim();
51
+ const views = Object.assign({}, state.workspaceViews || {});
52
+ if (previousId) views[previousId] = normalizeWorkspaceView(state.view || views[previousId] || DEFAULT_WORKSPACE_VIEW);
53
+ const nextView = normalizeWorkspaceView(views[id] || DEFAULT_WORKSPACE_VIEW);
54
+ views[id] = nextView;
55
+ return Object.assign({}, state, { activeWorkspaceId: id, view: nextView, workspaceViews: views });
56
+ }
57
+
58
+ export function stateWithWorkspacePresentationPruned(state = {}) {
59
+ const workspaces = Array.isArray(state.workspaces) ? state.workspaces : [];
60
+ const workspaceById = new Map(workspaces.map((workspace) => [String(workspace.id || ''), workspace]));
61
+ const allowed = new Set(workspaceById.keys());
62
+ const views = Object.fromEntries(Object.entries(state.workspaceViews || {})
63
+ .filter(([id]) => allowed.has(String(id)))
64
+ .map(([id, view]) => [id, normalizeWorkspaceViewForWorkspace(view, workspaceById.get(String(id)))]));
65
+ const activeId = allowed.has(String(state.activeWorkspaceId || '')) ? state.activeWorkspaceId : (workspaces[0]?.id || '');
66
+ const activeWorkspace = workspaceById.get(String(activeId || '')) || null;
67
+ const view = activeId
68
+ ? normalizeWorkspaceViewForWorkspace(views[activeId] || (activeId === state.activeWorkspaceId ? state.view : DEFAULT_WORKSPACE_VIEW), activeWorkspace)
69
+ : normalizeWorkspaceView(state.view || DEFAULT_WORKSPACE_VIEW);
70
+ if (activeId) views[activeId] = view;
71
+ return Object.assign({}, state, { activeWorkspaceId: activeId, view, workspaceViews: views });
72
+ }
73
+
74
+ export function visibleWorkspaceItemsFor(state = {}, { active = null, activeUi = null, viewportWidth = 0 } = {}) {
75
+ const windowState = workspaceWindowFor(state, { viewportWidth, activeWorkspaceId: active?.id || state.activeWorkspaceId });
76
+ return windowState.visible.map((workspace) => ({
77
+ workspace,
78
+ ui: workspace?.id === active?.id ? activeUi : hydrateUiWorkspace(workspace),
79
+ surfaceState: stateForWorkspaceSurface(state, workspace?.id),
80
+ layoutMode: workspaceLayoutModeFor(state, workspace?.id),
81
+ active: workspace?.id === active?.id
82
+ }));
83
+ }
84
+
85
+ export { workspaceColumnCapacity };
86
+
87
+ function stateWithWorkspaceView(state = {}, workspaceId = '', view = {}) {
88
+ const id = String(workspaceId || '').trim();
89
+ const views = Object.assign({}, state.workspaceViews || {});
90
+ if (id) views[id] = normalizeWorkspaceView(view);
91
+ return Object.assign({}, state, {
92
+ view: id === state.activeWorkspaceId ? views[id] : normalizeWorkspaceView(state.view || DEFAULT_WORKSPACE_VIEW),
93
+ workspaceViews: views
94
+ });
95
+ }
96
+
97
+ function normalizeWorkspaceViewForWorkspace(view = {}, workspace = null) {
98
+ const next = resolveWorkspaceEntrypointViewIntent(normalizeWorkspaceView(view), workspace);
99
+ if (!next.displayOptions || typeof next.displayOptions !== 'object' || Array.isArray(next.displayOptions)) return next;
100
+ const schemaFilter = qualifiedSchemaFilterValue(next.displayOptions.schemaFilter, workspace?.records || []);
101
+ if (schemaFilter === next.displayOptions.schemaFilter) return next;
102
+ return Object.assign({}, next, { displayOptions: Object.assign({}, next.displayOptions, { schemaFilter }) });
103
+ }
104
+
105
+ function normalizeWorkspaceView(view = {}) {
106
+ const next = Object.assign({}, DEFAULT_WORKSPACE_VIEW, view || {});
107
+ if (!['feed', 'tree', 'graph', 'lineage', 'audit'].includes(String(next.workspaceVerse || ''))) next.workspaceVerse = 'feed';
108
+ next.layoutMode = next.layoutMode === 'compact' ? 'compact' : 'expanded';
109
+ const timePortal = normalizeTimePortalView(next.timePortal);
110
+ if (timePortal) next.timePortal = timePortal;
111
+ else delete next.timePortal;
112
+ return next;
113
+ }
@@ -0,0 +1,110 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs';
3
+ import { createRecordFromMarkdown } from '@tiinex/core/artifacts/artifact.record.js';
4
+ import { buildWorkspaceDiscoveryView, buildDiscoveryMaterialIndex } from '../workspaces/workspace.discoveryView.js';
5
+ import { buildWorkspaceLineageView } from '../workspaces/workspace.lineageView.js';
6
+ import { buildWorkspacePathTree } from '../workspaces/workspace.pathTree.js';
7
+ import { WORKSPACE_RECORD_PRIMARY_INTENT, workspaceRecordPrimaryIntent } from '../workspaces/workspace.navigation.js';
8
+ import { stateWithRecordLineageFocused, stateWithWorkspaceViewPatchAndFocus, workspaceVerseNavigationPatch } from './workspaceScopedInteraction.js';
9
+
10
+ const parent = record('parent', 'Root Parent', 'roots/parent.trace.md', '2026-09-01 09:00:00');
11
+ const child = record('child', 'Focused Child', 'branches/deep/child.trace.md', '2026-09-02 09:00:00', '../../roots/parent.trace.md');
12
+ const sibling = record('sibling', 'Sibling Note', 'branches/sibling.trace.md', '2026-09-01 12:00:00');
13
+ const records = [parent, child, sibling];
14
+ const workspace = { id: 'workspace-navigation', title: 'Navigation', records, assets: [] };
15
+ const displayOptions = { leavesOnly: false, showSupportingMarkdown: true, showWorkspaceArtifacts: true, showAssets: false, schemaFilter: 'all', artifactFilter: 'all', sourceFilter: 'all' };
16
+
17
+ // Feed and Tree are presentation projections over the same stable record identity.
18
+ const feed = buildWorkspaceDiscoveryView(workspace, { records, displayOptions, query: '' });
19
+ assert.strictEqual(feed.records.find((item) => item.id === child.id), child);
20
+ const tree = buildWorkspacePathTree({ records: feed.records, assets: [] });
21
+ const treeChild = findTreeRecord(tree, child.id);
22
+ assert.ok(treeChild, 'Tree must contain the Feed-visible child');
23
+ assert.strictEqual(treeChild.source, child, 'Tree must preserve the exact loaded record identity used by Feed');
24
+ assert.equal(treeChild.path, 'branches/deep/child.trace.md');
25
+ assert.equal(workspaceRecordPrimaryIntent({ surface: 'feed' }), WORKSPACE_RECORD_PRIMARY_INTENT.open);
26
+ assert.equal(workspaceRecordPrimaryIntent({ surface: 'tree' }), WORKSPACE_RECORD_PRIMARY_INTENT.open);
27
+ assert.equal(workspaceRecordPrimaryIntent({ surface: 'lineage' }), WORKSPACE_RECORD_PRIMARY_INTENT.toggleLineagePreview);
28
+ assert.equal(workspaceRecordPrimaryIntent({ surface: 'tree', selectionActive: true, selectionCandidate: { id: child.id } }), WORKSPACE_RECORD_PRIMARY_INTENT.select);
29
+ assert.equal(workspaceRecordPrimaryIntent({ surface: 'tree', selectionActive: true }), WORKSPACE_RECORD_PRIMARY_INTENT.unavailable);
30
+
31
+ // Path Tree truth remains independent from declared Parent truth.
32
+ const lineage = buildWorkspaceLineageView(workspace, { records, selectedRecordId: child.id });
33
+ assert.ok(lineage.edges.some((edge) => edge.kind === 'parent' && edge.from === parent.id && edge.to === child.id), 'Lineage must follow the declared Parent Trace across unrelated path folders');
34
+ assert.deepEqual(lineage.selectedTraversal.nodes.map((node) => node.id), [child.id, parent.id]);
35
+ assert.equal(findTreeRecord(tree, parent.id).path, 'roots/parent.trace.md');
36
+ assert.equal(findTreeRecord(tree, child.id).path, 'branches/deep/child.trace.md');
37
+
38
+ // Search/filtering and optional material-index reuse are presentation-only and semantically equivalent.
39
+ const filterOptions = { ...displayOptions, schemaFilter: 'tiinex.topic.v1' };
40
+ const uncached = buildWorkspaceDiscoveryView(workspace, { records, displayOptions: filterOptions, query: 'focused' });
41
+ const cached = buildWorkspaceDiscoveryView(workspace, { records, displayOptions: filterOptions, query: 'focused', materialIndex: buildDiscoveryMaterialIndex(records) });
42
+ assert.deepEqual(cached.records.map((item) => item.id), uncached.records.map((item) => item.id));
43
+ assert.deepEqual(cached.records.map((item) => item.id), [child.id]);
44
+ const lineageAfterFiltering = buildWorkspaceLineageView(workspace, { records, selectedRecordId: child.id });
45
+ assert.deepEqual(lineageAfterFiltering.edges, lineage.edges, 'Discovery filtering must not mutate declared lineage truth');
46
+
47
+ // Feed ordering is deterministic and independent of loaded array order.
48
+ const orderA = buildWorkspaceDiscoveryView(workspace, { records: [parent, child, sibling], displayOptions, query: '' }).records.map((item) => item.id);
49
+ const orderB = buildWorkspaceDiscoveryView(workspace, { records: [sibling, parent, child], displayOptions, query: '' }).records.map((item) => item.id);
50
+ assert.deepEqual(orderA, orderB);
51
+ assert.deepEqual(orderA, [child.id, sibling.id, parent.id]);
52
+
53
+ // Artifact -> Lineage -> Back preserves discovery context while clearing lineage-only state.
54
+ const discoveryView = {
55
+ universe: 'column',
56
+ workspaceVerse: 'tree',
57
+ query: 'focused',
58
+ displayOptions: { ...displayOptions, mismatchesOnly: true },
59
+ expandedTreeFolders: ['branches', 'branches/deep'],
60
+ scrollPositions: { 'workspace-navigation:tree:focused::display': 318 }
61
+ };
62
+ const state = { activeWorkspaceId: workspace.id, workspaces: [workspace], view: discoveryView, workspaceViews: { [workspace.id]: discoveryView } };
63
+ const lineageState = stateWithRecordLineageFocused(state, workspace.id, child.id, 1280);
64
+ assert.equal(lineageState.view.workspaceVerse, 'lineage');
65
+ assert.equal(lineageState.view.lineageReturnVerse, 'tree');
66
+ assert.equal(lineageState.view.selectedRecordId, child.id);
67
+ assert.equal(lineageState.view.query, discoveryView.query);
68
+ assert.deepEqual(lineageState.view.displayOptions, discoveryView.displayOptions);
69
+ assert.deepEqual(lineageState.view.expandedTreeFolders, discoveryView.expandedTreeFolders);
70
+ assert.deepEqual(lineageState.view.scrollPositions, discoveryView.scrollPositions);
71
+ const returned = stateWithWorkspaceViewPatchAndFocus(lineageState, workspace.id, workspaceVerseNavigationPatch(lineageState.view.lineageReturnVerse), 1280);
72
+ assert.equal(returned.view.workspaceVerse, 'tree');
73
+ assert.equal(returned.view.selectedRecordId, '');
74
+ assert.equal(returned.view.lineageReturnVerse, '');
75
+ assert.equal(returned.view.query, discoveryView.query);
76
+ assert.deepEqual(returned.view.displayOptions, discoveryView.displayOptions);
77
+ assert.deepEqual(returned.view.expandedTreeFolders, discoveryView.expandedTreeFolders);
78
+ assert.deepEqual(returned.view.scrollPositions, discoveryView.scrollPositions);
79
+
80
+ // UI wiring must expose opening and lineage as distinct actions rather than conflating primary click with lineage.
81
+ const cardSource = fs.readFileSync(new URL('../schemas/workspace/workspace.cards.views.jsx', import.meta.url), 'utf8');
82
+ const treeSource = fs.readFileSync(new URL('../schemas/workspace/workspace.tree.views.jsx', import.meta.url), 'utf8');
83
+ const detailSource = fs.readFileSync(new URL('../schemas/workspace/workspace.recordDialogs.views.jsx', import.meta.url), 'utf8');
84
+ assert.ok(cardSource.includes("label: lineageContext ? 'Anchor' : 'Lineage'"));
85
+ assert.ok(cardSource.includes('return onOpenRecord?.(record.id);'));
86
+ assert.ok(treeSource.includes('return onOpenRecord?.(item.source.id);'));
87
+ assert.ok(treeSource.includes('Open lineage for ${item.name || item.title || \'artifact\'}'));
88
+ assert.ok(detailSource.includes('onLineage && !historical'));
89
+ assert.ok(detailSource.includes('>Lineage</Button>'));
90
+
91
+ console.log('✓ Viewer navigation parity invariants passed');
92
+
93
+ function record(id, title, path, createdAt, trace = '') {
94
+ const parentBlock = trace ? `- Parent\n - Parent Schema: [tiinex.topic.v1](tiinex.topic.v1.schema.md)\n - Trace: [Parent](${trace})\n` : '';
95
+ const markdown = `# Continuity Context\n\n- Envelope Schema: [tiinex.root.v1](tiinex.root.v1.schema.md)\n${parentBlock}- Current\n - Current Schema: [tiinex.topic.v1](tiinex.topic.v1.schema.md)\n - Created At: ${createdAt}\n - Summary: ${title}\n\n---\n\n# ${title}\n\n${title} body.\n\n---\n\n# Continuity Integrity\n\n- local-test\n - Towards: self\n - Value: ${id}-self\n`;
96
+ return Object.assign(createRecordFromMarkdown(markdown, { path, sourceMode: 'local-test' }), { id });
97
+ }
98
+
99
+ function findTreeRecord(tree, id) {
100
+ const visit = (folder) => {
101
+ const direct = (folder.items || []).find((item) => item.type === 'record' && item.source?.id === id);
102
+ if (direct) return direct;
103
+ for (const childFolder of folder.folders || []) {
104
+ const found = visit(childFolder);
105
+ if (found) return found;
106
+ }
107
+ return null;
108
+ };
109
+ return visit({ folders: tree.folders || [], items: tree.items || [] });
110
+ }
@@ -0,0 +1,26 @@
1
+ import { setWorkspaceDiscoveryProgress } from '../workspaces/workspace.discoveryProgress.js';
2
+
3
+ export function stateWithWorkspaceRecordOpenProgress(openedState = {}, workspaceId = '', sourceInputs = [], entry = {}) {
4
+ const inputs = Array.isArray(sourceInputs) ? sourceInputs : [];
5
+ if (!inputs.length) return openedState;
6
+ let next = openedState;
7
+ for (const input of inputs) {
8
+ const targetWorkspaceId = input.workspaceId || workspaceId || '';
9
+ if (!targetWorkspaceId) continue;
10
+ const primary = input || {};
11
+ const sourceId = String(primary.sourceId || primary.id || '').trim();
12
+ const sourceLabel = String(primary.label || primary.repository || entry?.title || 'Workspace source').trim();
13
+ const workspace = (Array.isArray(next?.workspaces) ? next.workspaces : []).find((item) => item.id === targetWorkspaceId);
14
+ const resolvedSourceId = sourceId || (Array.isArray(workspace?.sources) ? workspace.sources.find((source) => String(source.label || '') === sourceLabel || String(source.repo || source.repository || '') === String(primary.repository || ''))?.id : '') || '';
15
+ const progress = setWorkspaceDiscoveryProgress(next, targetWorkspaceId, {
16
+ sourceId: resolvedSourceId,
17
+ phase: 'workspace-open-source-queued',
18
+ label: `${sourceLabel} source loading queued`,
19
+ active: true,
20
+ quantified: false,
21
+ discoveryState: 'loading'
22
+ });
23
+ if (progress?.ok) next = progress.state;
24
+ }
25
+ return next;
26
+ }
@@ -0,0 +1,46 @@
1
+ export const WORKSPACE_PLACEMENT_OPTIONS_SCHEMA_ID = 'tiinex.site.workspace-placement-options.v1';
2
+
3
+ export function workspacePlacementOptions(state = {}, workspaceId = '') {
4
+ const id = token(workspaceId);
5
+ const workspaces = Array.isArray(state?.workspaces) ? state.workspaces : [];
6
+ const target = workspaces.find((workspace) => token(workspace?.id) === id);
7
+ if (!target) return Object.freeze({ schema: WORKSPACE_PLACEMENT_OPTIONS_SCHEMA_ID, state: 'workspace-unavailable', options: Object.freeze([]) });
8
+ const options = [];
9
+ for (const workspace of workspaces) {
10
+ const currentId = token(workspace?.id);
11
+ for (const path of folderPathsForWorkspace(workspace)) {
12
+ const sameWorkspace = currentId === id;
13
+ options.push(Object.freeze({
14
+ kind: 'folder', key: placementFolderSelectionKey(currentId, path), workspaceId: currentId, path,
15
+ title: path === '.' ? `${workspace.name || workspace.title || currentId} root` : path,
16
+ enabled: sameWorkspace,
17
+ reason: sameWorkspace ? '' : 'cross-workspace-placement-authority-unavailable',
18
+ boundary: sameWorkspace ? 'Same-workspace storage coordinate only; does not change Parent, Reference, or provenance.' : 'Cross-workspace placement requires semantic/lifecycle authority not present in the current canonical create command.'
19
+ }));
20
+ }
21
+ }
22
+ return Object.freeze({ schema: WORKSPACE_PLACEMENT_OPTIONS_SCHEMA_ID, state: 'qualified', workspaceId: id, options: Object.freeze(options), qualifiedOptions: Object.freeze(options.filter((item) => item.enabled)), unavailableOptions: Object.freeze(options.filter((item) => !item.enabled)), crossWorkspaceClassification: 'PLACEMENT AUTHORITY ESCALATION REQUIRED' });
23
+ }
24
+
25
+ export function folderPathsForWorkspace(workspace = {}) {
26
+ const folders = new Set(['.topics']);
27
+ for (const record of Array.isArray(workspace.records) ? workspace.records : []) {
28
+ const path = canonicalPath(record?.path || '');
29
+ const parts = path.split('/').filter(Boolean);
30
+ if (parts.length <= 1) continue;
31
+ let current = '';
32
+ for (const part of parts.slice(0, -1)) { current = current ? `${current}/${part}` : part; folders.add(current); }
33
+ }
34
+ return Object.freeze([...folders].sort((a,b) => a.localeCompare(b)));
35
+ }
36
+
37
+ export function explicitPlacementPath(defaultPath = '', folder = '') {
38
+ const path = canonicalPath(defaultPath), dir = canonicalFolder(folder);
39
+ const name = path.split('/').filter(Boolean).at(-1) || '';
40
+ if (!name || !dir) return '';
41
+ return dir === '.' ? name : `${dir}/${name}`;
42
+ }
43
+ export function placementFolderSelectionKey(workspaceId = '', path = '') { return `placement-folder:${token(workspaceId)}:${canonicalFolder(path)}`; }
44
+ function canonicalPath(value = '') { return token(value).replace(/\\/g,'/').replace(/^\/+|\/+$/g,'').replace(/\/+/g,'/'); }
45
+ function canonicalFolder(value = '') { const v=canonicalPath(value); return v || '.'; }
46
+ function token(value = '') { return String(value || '').trim(); }