@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,51 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs';
3
+ import '../workspaces/workspace.route.js';
4
+ import { resolveTimePortalSnapshot } from '../app/timePortalSnapshotResolution.js';
5
+ import { historicalWorkspaceForReadModel, loadTimePortalHistoricalReadModel } from '../app/timePortalHistoricalRead.js';
6
+ import { normalizeTimePortalView, timePortalWithIntent, timePortalWithResolvedSnapshot } from '../workspaces/workspace.timePortal.js';
7
+
8
+ const liveCommit='a'.repeat(40), historicalCommit='b'.repeat(40);
9
+ const liveSource={ id:'github:docs', adapterId:'github', sourceKind:'github.repo', kind:'github-tree', label:'Docs', repo:'owner/repo', ref:'main', materializedCommit:liveCommit, rootPath:'.topics', repoDiscovery:true, explicitFileRefs:[], config:{repo:'owner/repo',ref:'main',rootPath:'.topics'} };
10
+ const liveRecord={id:'live:A',title:'Live A',path:'.topics/live-a.trace.md',markdown:'# Live A',source:{...liveSource},sourceTarget:{inputTarget:'.topics/live-a.trace.md',materializedCommit:liveCommit}};
11
+ const localDraft={id:'local:draft',title:'Local draft',path:'draft.trace.md',markdown:'# Draft',source:{id:'local',adapterId:'local'}};
12
+ const workspace={id:'w1',title:'Docs',sources:[{id:'local',adapterId:'local'},liveSource],records:[liveRecord,localDraft],assets:[]};
13
+ const original=JSON.stringify(workspace);
14
+ const intent=timePortalWithIntent({workspaceVerse:'feed'},{begin:'2026-05-01T10:00',end:'2026-05-31T22:40',sourceId:'github:docs',snapshotInput:historicalCommit});
15
+ assert.equal(normalizeTimePortalView(intent.timePortal).mode,'intent');
16
+ const resolution=await resolveTimePortalSnapshot({workspace,view:intent,snapshotInput:historicalCommit,fetchImpl:async()=>{throw new Error('exact commit must not resolve over network');}});
17
+ assert.equal(resolution.ok,true);
18
+ assert.equal(resolution.snapshot.materializedCommit,historicalCommit);
19
+ const historicalView=timePortalWithResolvedSnapshot(intent,resolution.snapshot);
20
+ assert.equal(historicalView.timePortal.snapshot.materializedCommit,historicalCommit);
21
+ assert.equal(liveSource.materializedCommit,liveCommit,'historical selection must not rewrite live source receipt');
22
+ const treeUrl=`https://api.github.com/repos/owner/repo/git/trees/${historicalCommit}?recursive=1`;
23
+ const rawUrl=`https://raw.githubusercontent.com/owner/repo/${historicalCommit}/.topics/history.trace.md`;
24
+ const read=await loadTimePortalHistoricalReadModel({workspace,snapshot:resolution.snapshot,fetchImpl:async(url)=>{
25
+ if(url===treeUrl)return{ok:true,json:async()=>({truncated:false,tree:[{type:'blob',path:'.topics/history.trace.md'}]})};
26
+ if(url===rawUrl)return{ok:true,text:async()=> '# Historical B\n\nExact old source.'};
27
+ return{ok:false,status:404,statusText:'Not Found',json:async()=>({message:'missing'}),text:async()=>''};
28
+ },options:{allowCache:false}});
29
+ assert.equal(read.state,'loaded');
30
+ assert.equal(JSON.stringify(workspace),original,'historical B cannot redefine live/latest A or local drafts');
31
+ const shell=historicalWorkspaceForReadModel(workspace,read);
32
+ assert.equal(shell.records.length,1);
33
+ assert.equal(shell.records[0].sourceTarget.materializedCommit,historicalCommit);
34
+ assert.equal(shell.records.some((record)=>record.id==='live:A'),false,'historical shell cannot silently show live A as historical');
35
+ assert.equal(shell.records.some((record)=>record.id==='local:draft'),false,'local draft is not projected into historical source review');
36
+ assert.equal(workspace.records.some((record)=>record.id==='local:draft'),true,'local draft remains intact in live workspace');
37
+ assert.equal(shell.sources[0].closeable,false);
38
+ assert.equal(shell.sources[0].loadable,false);
39
+ assert.equal(shell.records[0].sourceMode,'source-backed-historical');
40
+
41
+ const appSource=fs.readFileSync(new URL('../app/TiinexApp.jsx',import.meta.url),'utf8');
42
+ assert.match(appSource,/loadHistoricalSnapshot\(workspace\.id\)/,'historical fetch remains explicit behind product action');
43
+ const routeHandler=appSource.slice(appSource.indexOf('const onRoute ='),appSource.indexOf("window.addEventListener('popstate'"));
44
+ assert.doesNotMatch(routeHandler,/loadHistoricalSnapshot|resolveTimePortalSnapshot|materializeGithubSource/,'semantic route restore must stay network-silent for Time Portal');
45
+ const surfaceSource=fs.readFileSync(new URL('../schemas/workspace/workspace.views.jsx',import.meta.url),'utf8');
46
+ assert.match(surfaceSource,/!readOnlyHistorical && \(verse === 'feed' \|\| verse === 'lineage'\)/,'historical presentation must not prepare canonical mutation actions');
47
+ assert.match(surfaceSource,/readOnly=\{readOnlyHistorical\}/,'historical cards/tree are explicitly read-only');
48
+ const displaySource=fs.readFileSync(new URL('../schemas/workspace/workspace.displayOptions.views.jsx',import.meta.url),'utf8');
49
+ assert.match(displaySource,/Time Portal/);
50
+ assert.match(displaySource,/no date is converted into a commit/);
51
+ console.log('post-v437 M0-E Time Portal product parity closure: PASS');
@@ -0,0 +1,33 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs';
3
+ const read = (path) => fs.readFileSync(new URL(`../${path}`, import.meta.url), 'utf8');
4
+ const plan = read('export/export.plan.js');
5
+ const controller = read('schemas/workspace/workspace.exportDialog.controller.jsx');
6
+ const view = read('schemas/workspace/workspace.exportDialog.views.jsx');
7
+ const product = read('app/workspaceGithubPublication.js');
8
+ const command = read('app/workspaceExportExecutionCommand.js');
9
+ const snapshot = read('adapters/github/github.issueSnapshot.js');
10
+ const publicationRead = read('adapters/github/github.publicationRead.js');
11
+ const readTransport = read('adapters/github/github.readTransport.js');
12
+ const persistence = read('workspaces/workspace.persistence.js');
13
+ assert.ok(plan.includes("status: 'available'") && plan.includes('Exact issue / issue-comment'), 'GitHub social publication must no longer be stale future/Case C UI');
14
+ assert.ok(plan.includes("action: 'guided-github-publication'"), 'export plan exposes guided routine, not hidden write');
15
+ assert.ok(command.includes('github-publication.guided-routine-required'), 'generic export command must not simulate a provider write');
16
+ assert.ok(product.includes('buildPublicationPlan') && product.includes('buildPublicationResult'), 'Site consumes shared plan/result authority directly');
17
+ assert.ok(product.includes('parseExactGithubIssueTarget'), 'final target uses accepted exact shared parser');
18
+ assert.equal(product.includes('parseGithubIssueSnapshotTarget'), false, 'permissive issue snapshot parser must not qualify publication targets');
19
+ assert.ok(publicationRead.includes('readExactGithubIssuePublicationRepresentation'), 'bounded GitHub read sibling exposes exact post-write body observation');
20
+ assert.equal(publicationRead.includes('parseGithubIssueSnapshotTarget'), false, 'verification read owner receives already-qualified target and does not use permissive snapshot parsing');
21
+ assert.ok(publicationRead.includes('fetchGithubJson') && snapshot.includes('fetchGithubJson') && readTransport.includes('export async function fetchGithubJson'), 'publication verification and issue snapshots share one read-only GitHub JSON transport owner');
22
+ assert.ok(controller.includes('copiedPlanSha256') && controller.includes('verificationPlanSha256'), 'transient completion is bound to exact plan identity');
23
+ assert.ok(controller.includes('buildWorkspaceGithubPublicationPreflight') && controller.includes('publicationPreflight'), 'shared publication preflight is memoized per workspace/GitHub selection rather than rebuilt on each form input');
24
+ assert.ok(view.includes('Copy exact payload') && view.includes('Open GitHub') && view.includes('Verify exact publication'), 'guided routine remains visible and ordered');
25
+ assert.ok(view.includes('Final exact GitHub URL'), 'create-new/comment completion requires exact result target');
26
+ assert.ok(persistence.includes('publicationReceipts'), 'qualified local receipt has durable local-delta owner');
27
+ assert.equal(product.includes('fetch('), false, 'Site product owner must not add a second GitHub fetch implementation');
28
+ assert.equal(product.includes('api.github.com'), false, 'Site product owner must not construct GitHub API URLs');
29
+ assert.equal(controller.includes('api.github.com'), false);
30
+ assert.equal(view.includes('api.github.com'), false);
31
+ assert.equal(controller.includes('Issue #3'), false);
32
+ assert.equal(product.includes('Tiinusen'), false);
33
+ console.log('postV447M0FGithubSocialPublicationProductIntegration: PASS');
@@ -0,0 +1,82 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs';
3
+ import { createPersistenceOwnershipPolicy, PersistenceRouteOwner } from '../app/persistenceOwnership.js';
4
+ import { executeCanonicalTransitionLocalCreate } from '../app/canonicalTransitionLocalCreateCommand.js';
5
+ import { canonicalC14nV2SelfState } from '@tiinex/core/integrity/integrity.c14nV2.js';
6
+ import { CANONICAL_TRANSITION_SCHEMA_CACHE_MANIFEST } from '../transitions/canonicalTransition.schemaCache.js';
7
+ import { prepareCanonicalTransitionProductActions, prepareCanonicalTransitionWorkspaceActions } from '../transitions/transition.productPreparation.js';
8
+ import '../workspaces/workspace.persistenceRecovery.js';
9
+ import '../workspaces/workspace.persistenceRouteCache.js';
10
+ import '../workspaces/workspace.persistencePresentation.js';
11
+ import '../workspaces/workspace.persistenceClear.js';
12
+ import '../workspaces/workspace.persistence.js';
13
+ import '../workspaces/workspace.lifecycle.js';
14
+
15
+ const lifecycle=globalThis.TiinexWorkspaceLifecycle, persistence=globalThis.TiinexWorkspacePersistence;
16
+ const ownership=createPersistenceOwnershipPolicy(PersistenceRouteOwner.semanticState);
17
+ const cachePaths={
18
+ 'tiinex.root.v1':'src/transitions/canonical-schema-cache/d69b8ff55a56b8cb9282b8684db6a938a4435b94/tiinex.root.v1.schema.md',
19
+ 'tiinex.transition.definition.v1':'src/transitions/canonical-schema-cache/d69b8ff55a56b8cb9282b8684db6a938a4435b94/tiinex.transition.definition.v1.schema.md',
20
+ 'tiinex.task.v1':'src/schemas/core/task/tiinex.task.v1.schema.md',
21
+ 'tiinex.topic.v1':'src/transitions/canonical-schema-cache/52ecdea0a75893882ce282214d155f70e1309c2a/tiinex.topic.v1.schema.md',
22
+ 'tiinex.interpretation.v1':'src/schemas/core/interpretation/tiinex.interpretation.v1.schema.md',
23
+ 'tiinex.relation.v1':'src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.relation.v1.schema.md',
24
+ 'tiinex.schema.contract.v1':'src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.schema.contract.v1.schema.md',
25
+ 'tiinex.schema.generation.v1':'src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.schema.generation.v1.schema.md'
26
+ };
27
+ const schemaCache=CANONICAL_TRANSITION_SCHEMA_CACHE_MANIFEST.map((item)=>({...item,markdown:fs.readFileSync(cachePaths[item.schemaId],'utf8'),sourceQualification:'source-qualified-cache'}));
28
+ function bundled(path,title,sourceQualification='site-local-definition-source-qualified'){return Object.freeze({path,title,markdown:fs.readFileSync(path,'utf8'),sourceQualification,sourceMode:'bundled-canonical-transition-definition',source:Object.freeze({id:`site:${path}`,adapterId:'static',sourceKind:'bundled-canonical',sourceMode:'bundled-canonical-transition-definition',sourceArtifactPath:path})});}
29
+ const definitions=Object.freeze([
30
+ bundled('src/schemas/core/task/.transitions/topic-to-task-transition-definition.trace.md','Topic to Task','compiled-semantic-package-qualified'),
31
+ bundled('src/schemas/core/interpretation/.transitions/evidence-to-interpretation-transition-definition.trace.md','Evidence to Interpretation'),
32
+ bundled('src/schemas/core/relation/.transitions/topic-references-task-transition-definition.trace.md','Topic references Task'),
33
+ bundled('src/schemas/core/topic/.transitions/create-topic-transition-definition.trace.md','Create standalone Topic'),
34
+ bundled('src/schemas/core/task/.transitions/create-task-transition-definition.trace.md','Create standalone Task')
35
+ ]);
36
+ const state={version:1,activeWorkspaceId:'w',view:{universe:'column',workspaceVerse:'feed',reader:'scan',query:''},workspaces:[{id:'w',name:'Workspace',title:'Workspace',createdAt:'2026-08-20T00:00:00.000Z',kind:'workspace',source:{id:'local',adapterId:'local',kind:'local-session'},sources:[],sourceOrder:[],records:[],assets:[],importLog:[],mode:'feed'}],audit:null};
37
+ const workspaceActions=prepareCanonicalTransitionWorkspaceActions({workspaceId:'w',schemaCache,bundledDefinitions:definitions});
38
+ const createTopic=workspaceActions.actions.find((a)=>a.canonicalIdentifier==='tiinex.site.create-topic.v1');
39
+ const createTask=workspaceActions.actions.find((a)=>a.canonicalIdentifier==='tiinex.site.create-task.v1');
40
+ assert.equal(createTopic.icon,'create'); assert.equal(createTask.icon,'create');
41
+
42
+ // Q-reported valid-looking Topic failure: canonical Topic materialization owns representation-local whitespace normalization; generic authoring values remain untouched.
43
+ const topic=executeCanonicalTransitionLocalCreate({lifecycle,state,workspaceId:'w',currentRecordId:'',definitionKey:createTopic.definitionKey,values:{Summary:' Standalone Topic ','Current Read':' Current state\n','Design Direction':' Move here ','Next Artifacts':' One task '},placementFolder:'.topics/research',schemaCache,bundledDefinitions:definitions,persistenceOwnership:ownership,clock:()=> '2026-08-20T10:00:00.000Z'});
44
+ assert.equal(topic.ok,true,topic.notice);
45
+ assert.equal(topic.record.title,'Standalone Topic');
46
+ assert.match(topic.record.path,/^\.topics\/research\/standalone-topic--topic(?:-\d+)?\.trace\.md$/);
47
+ assert.equal(topic.placement.mode,'explicit-same-workspace-folder');
48
+ assert.equal(topic.placement.folder,'.topics/research');
49
+ assert.equal(canonicalC14nV2SelfState(topic.record.markdown).state,'verified');
50
+
51
+ // Parent semantics remain canonical while only the storage coordinate changes.
52
+ const prep=prepareCanonicalTransitionProductActions({currentRecord:topic.record,workspaceRecords:topic.workspace.records,workspaceId:'w',schemaCache,bundledDefinitions:definitions});
53
+ const cont=prep.actions.find((a)=>a.canonicalIdentifier==='tiinex.site.topic-to-task.v1');
54
+ const reference=prep.actions.find((a)=>a.canonicalIdentifier==='tiinex.site.topic-references-task.v1');
55
+ assert.equal(cont.icon,'continue'); assert.equal(reference.icon,'reference');
56
+ const task=executeCanonicalTransitionLocalCreate({lifecycle,state:topic.state,workspaceId:'w',currentRecordId:topic.record.id,definitionKey:cont.definitionKey,values:{Summary:'Placed Task',Objective:'Do it','Done Criteria':'Done',Scope:'Local',Dependencies:'None'},placementFolder:'.topics/research/tasks',schemaCache,bundledDefinitions:definitions,persistenceOwnership:ownership,clock:()=> '2026-08-20T10:01:00.000Z'});
57
+ assert.equal(task.ok,true,task.notice);
58
+ assert.match(task.record.path,/^\.topics\/research\/tasks\//);
59
+ assert.equal(task.record.parentSchemaId,'tiinex.topic.v1');
60
+ assert.ok(task.record.trace || task.record.origin, 'canonical Parent representation remains present');
61
+ assert.equal(task.record.sourceTarget,undefined);
62
+
63
+ // Exact placement survives durable workspace persistence/reopen as ordinary path truth.
64
+ const env=memoryEnv(); persistence.writeState(task.state,{storage:env.storage,location:env.location,history:env.history,mode:'replace'}); const reopened=persistence.readRecoverableLocalState(env.storage);
65
+ assert.equal(reopened.workspaces[0].records.find((r)=>r.id===task.record.id).path,task.record.path);
66
+
67
+ // Product shape: one generic selection session drives Reference / fixed Parent review / storage placement; dialogs yield while selection is active.
68
+ const authoring=fs.readFileSync('src/schemas/workspace/workspace.canonicalTaskDialog.views.jsx','utf8');
69
+ const referenceDialog=fs.readFileSync('src/schemas/workspace/workspace.canonicalReferenceDialog.views.jsx','utf8');
70
+ const surface=fs.readFileSync('src/schemas/workspace/workspace.selection.views.jsx','utf8');
71
+ assert(authoring.includes("CANONICAL_STORAGE_PLACEMENT_SELECTION_ROLE = 'storage-placement'"));
72
+ assert(authoring.includes("CANONICAL_CONTINUITY_PARENT_SELECTION_ROLE = 'continuity-parent'"));
73
+ assert(referenceDialog.includes("CANONICAL_REFERENCE_SELECTION_ROLE = 'reference-target'"));
74
+ assert(authoring.includes('return null'));
75
+ assert(referenceDialog.includes('return null'));
76
+ assert(surface.includes('Existing workspace context remains visible while selection is active'));
77
+ assert.equal(surface.includes('session?.candidates'),false,'selection banner no longer owns a parallel generic candidate list');
78
+ assert.equal(authoring.includes("schemaId === 'tiinex.task.v1'"),false);
79
+ assert.equal(referenceDialog.includes("canonicalIdentifier ==="),false);
80
+
81
+ console.log('post-v450 M0 product acceptance hardening: PASS');
82
+ function memoryEnv(){const map=new Map();const location={pathname:'/index.html',search:'',hash:''};const history={replaceState:(_a,_b,url)=>{location.hash=url.includes('#')?`#${url.split('#').pop()}`:'';},pushState:(_a,_b,url)=>{location.hash=url.includes('#')?`#${url.split('#').pop()}`:'';}};const storage={getItem:(k)=>map.get(k)||null,setItem:(k,v)=>map.set(k,String(v)),removeItem:(k)=>map.delete(k)};return{map,location,history,storage};}
@@ -0,0 +1,236 @@
1
+ import assert from 'node:assert/strict';
2
+ import { readFileSync } from 'node:fs';
3
+ import { createRecordFromMarkdown } from '@tiinex/core/artifacts/artifact.record.js';
4
+ import { openSchemaForRecordCommand } from '../app/schemaNavigationCommand.js';
5
+ import '../workspaces/workspace.lifecycle.js';
6
+
7
+ const lifecycle = globalThis.TiinexWorkspaceLifecycle;
8
+ const schemaId = 'tiinex.topic.v1';
9
+ const taskId = 'tiinex.task.v1';
10
+ const B = 'https://schemas.example.invalid/b/topic.schema.md';
11
+ const topicMarkdown = readFileSync(new URL('../schemas/core/topic/tiinex.topic.v1.schema.md', import.meta.url), 'utf8');
12
+ const topicPath = 'src/schemas/core/topic/tiinex.topic.v1.schema.md';
13
+
14
+ // 1. Invalid same-representation record never receives recovered semantic authority.
15
+ {
16
+ const declaration = declaring('rep-invalid', B);
17
+ const invalid = httpRepresentationRecord('invalid-b', B, '# README\n\nBAD\n');
18
+ const { state, workspace } = workspaceWith('rep-invalid', declaration, invalid);
19
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, B) });
20
+ assert.equal(opened.ok, true, opened.error);
21
+ assert.notEqual(opened.record.id, invalid.id);
22
+ assert.equal(opened.record.markdown, topicMarkdown);
23
+ assert.equal(opened.workspace.records.find((record) => record.id === invalid.id)?.schemaNavigation, undefined);
24
+ }
25
+
26
+ // 2. Invalid first + exact valid second on one representation reuses only the concrete valid record.
27
+ {
28
+ const declaration = declaring('rep-mixed', B);
29
+ const invalid = httpRepresentationRecord('first-invalid', B, '# README\nBAD\n');
30
+ const valid = httpRepresentationRecord('second-valid', B, topicMarkdown);
31
+ const { state, workspace } = workspaceWith('rep-mixed', declaration, invalid, valid);
32
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, B) });
33
+ assert.equal(opened.ok, true, opened.error);
34
+ assert.equal(opened.record.id, valid.id);
35
+ assert.equal(opened.workspace.records.find((record) => record.id === invalid.id)?.schemaNavigation, undefined);
36
+ assert.equal(opened.workspace.records.find((record) => record.id === valid.id)?.schemaNavigation?.reason, 'reading-contract-badge');
37
+ }
38
+
39
+ // 3. One exact semantically-qualified representation collision may be reused truthfully.
40
+ {
41
+ const declaration = declaring('rep-valid', B);
42
+ const valid = httpRepresentationRecord('only-valid', B, topicMarkdown);
43
+ const { state, workspace } = workspaceWith('rep-valid', declaration, valid);
44
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, B) });
45
+ assert.equal(opened.ok, true, opened.error);
46
+ assert.equal(opened.record.id, valid.id);
47
+ assert.equal(opened.record.markdown, topicMarkdown);
48
+ }
49
+
50
+ // 4. Two reusable exact collisions do not become first-hit authority.
51
+ {
52
+ const declaration = declaring('rep-two-valid', B);
53
+ const first = httpRepresentationRecord('valid-1', B, topicMarkdown);
54
+ const second = httpRepresentationRecord('valid-2', B, topicMarkdown);
55
+ const { state, workspace } = workspaceWith('rep-two-valid', declaration, first, second);
56
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, B) });
57
+ assert.equal(opened.ok, false);
58
+ assert.equal(opened.error, 'schema.materialization.ambiguous');
59
+ assert.equal(workspace.records[1].schemaNavigation, undefined);
60
+ assert.equal(workspace.records[2].schemaNavigation, undefined);
61
+ }
62
+
63
+ // 5. Bundled schema + invalid generated-id collision fails closed; invalid bytes are untouched.
64
+ {
65
+ const declaration = declaring('bundled-id', '');
66
+ const workspaceId = 'ws-v470-bundled-id';
67
+ const invalid = { id: `schema:${workspaceId}:${schemaId}`, schemaId, currentSchemaId: schemaId, path: 'ordinary/not-schema.md', markdown: '# README\nBAD\n' };
68
+ const { state, workspace } = workspaceWithId(workspaceId, declaration, invalid);
69
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, schemaEntry: { markdown: topicMarkdown, path: topicPath } });
70
+ assert.equal(opened.ok, false);
71
+ assert.equal(opened.error, 'schema.materialization.identity-conflict');
72
+ assert.equal(invalid.schemaNavigation, undefined);
73
+ }
74
+
75
+ // 6. Bundled schema + invalid exact-path collision fails closed; path is not semantic authority.
76
+ {
77
+ const declaration = declaring('bundled-path', '');
78
+ const invalid = { id: 'invalid-path', schemaId, currentSchemaId: schemaId, path: topicPath, markdown: '# README\nBAD\n' };
79
+ const { state, workspace } = workspaceWith('bundled-path', declaration, invalid);
80
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, schemaEntry: { markdown: topicMarkdown, path: topicPath } });
81
+ assert.equal(opened.ok, false);
82
+ assert.equal(opened.error, 'schema.materialization.identity-conflict');
83
+ assert.equal(invalid.schemaNavigation, undefined);
84
+ }
85
+
86
+ // 7. Unrelated throwing-markdown record with no collision remains unread.
87
+ {
88
+ let reads = 0;
89
+ const declaration = declaring('bounded-unrelated', '');
90
+ const unrelated = throwingRecord('unrelated', taskId, 'ordinary/unrelated.trace.md', () => { reads += 1; });
91
+ const { state, workspace } = workspaceWith('bounded-unrelated', declaration, unrelated);
92
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, schemaEntry: { markdown: topicMarkdown, path: topicPath } });
93
+ assert.equal(opened.ok, true, opened.error);
94
+ assert.equal(reads, 0);
95
+ assert.equal(opened.workspace.records.find((record) => record.id === unrelated.id), unrelated);
96
+ }
97
+
98
+ // 8. Throwing same-representation collision is bounded/read once and never upgraded; exact recovery may materialize separately.
99
+ {
100
+ let reads = 0;
101
+ const declaration = declaring('bounded-collision', B);
102
+ const collision = httpRepresentationRecord('throwing-b', B, '');
103
+ Object.defineProperty(collision, 'markdown', { configurable: true, enumerable: true, get() { reads += 1; throw new Error('collision markdown unreadable'); } });
104
+ const { state, workspace } = workspaceWith('bounded-collision', declaration, collision);
105
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, B) });
106
+ assert.equal(opened.ok, true, opened.error);
107
+ assert.equal(reads, 1);
108
+ assert.notEqual(opened.record.id, collision.id);
109
+ assert.equal(opened.workspace.records.find((record) => record.id === collision.id)?.schemaNavigation, undefined);
110
+ }
111
+
112
+ // 9. One coherent exact GitHub source boundary may coalesce as before.
113
+ {
114
+ const tuple = githubTuple();
115
+ const declaration = declaring('source-exact', tuple.blob);
116
+ const existing = coherentGithubSource('source-exact-existing', tuple);
117
+ const { state, workspace } = workspaceWith('source-exact', declaration);
118
+ workspace.sources = [existing]; workspace.sourceOrder = [existing.id];
119
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, tuple.raw) });
120
+ assert.equal(opened.ok, true, opened.error);
121
+ assert.equal(opened.workspace.sources.length, 1);
122
+ assert.equal(opened.record.source.id, existing.id);
123
+ }
124
+
125
+ // 10. Contradictory repo aliases are not exact coalescing authority and are never repaired.
126
+ {
127
+ const tuple = githubTuple();
128
+ const declaration = declaring('source-repo-conflict', tuple.blob);
129
+ const ambiguous = coherentGithubSource('source-repo-conflict-existing', tuple);
130
+ ambiguous.repository = 'Evil/other';
131
+ ambiguous.config = { ...ambiguous.config, repo: 'Evil/other' };
132
+ const before = JSON.stringify(ambiguous);
133
+ const { state, workspace } = workspaceWith('source-repo-conflict', declaration);
134
+ workspace.sources = [ambiguous]; workspace.sourceOrder = [ambiguous.id];
135
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, tuple.raw) });
136
+ assert.equal(opened.ok, true, opened.error);
137
+ assert.equal(opened.workspace.sources.length, 2);
138
+ assert.equal(JSON.stringify(opened.workspace.sources.find((source) => source.id === ambiguous.id)), before);
139
+ assert.notEqual(opened.record.source.id, ambiguous.id);
140
+ }
141
+
142
+ // 11. Contradictory ref aliases are independently non-coalescing and remain untouched.
143
+ {
144
+ const tuple = githubTuple();
145
+ const declaration = declaring('source-ref-conflict', tuple.blob);
146
+ const ambiguous = coherentGithubSource('source-ref-conflict-existing', tuple);
147
+ ambiguous.config = { ...ambiguous.config, ref: 'other' };
148
+ const before = JSON.stringify(ambiguous);
149
+ const { state, workspace } = workspaceWith('source-ref-conflict', declaration);
150
+ workspace.sources = [ambiguous]; workspace.sourceOrder = [ambiguous.id];
151
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, tuple.raw) });
152
+ assert.equal(opened.ok, true, opened.error);
153
+ assert.equal(opened.workspace.sources.length, 2);
154
+ assert.equal(JSON.stringify(opened.workspace.sources.find((source) => source.id === ambiguous.id)), before);
155
+ assert.notEqual(opened.record.source.id, ambiguous.id);
156
+ }
157
+
158
+ // 12. Root/boundary aliases follow the same exact 0/1/>1 rule.
159
+ {
160
+ const tuple = githubTuple();
161
+ const declaration = declaring('source-root-conflict', tuple.blob);
162
+ const ambiguous = coherentGithubSource('source-root-conflict-existing', tuple);
163
+ ambiguous.config = { ...ambiguous.config, rootPath: 'other-root' };
164
+ const before = JSON.stringify(ambiguous);
165
+ const { state, workspace } = workspaceWith('source-root-conflict', declaration);
166
+ workspace.sources = [ambiguous]; workspace.sourceOrder = [ambiguous.id];
167
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, tuple.raw) });
168
+ assert.equal(opened.ok, true, opened.error);
169
+ assert.equal(opened.workspace.sources.length, 2);
170
+ assert.equal(JSON.stringify(opened.workspace.sources.find((source) => source.id === ambiguous.id)), before);
171
+ }
172
+
173
+ // 13. Multiple coherent exact source candidates are not first-hit authority.
174
+ {
175
+ const tuple = githubTuple();
176
+ const declaration = declaring('source-two-exact', tuple.blob);
177
+ const first = coherentGithubSource('source-exact-1', tuple);
178
+ const second = coherentGithubSource('source-exact-2', tuple);
179
+ const { state, workspace } = workspaceWith('source-two-exact', declaration);
180
+ workspace.sources = [first, second]; workspace.sourceOrder = [first.id, second.id];
181
+ const opened = await openSchemaForRecordCommand({ state, workspace, record: declaration, catalog: {}, fetchImpl: async () => response(topicMarkdown, tuple.raw) });
182
+ assert.equal(opened.ok, false);
183
+ assert.equal(opened.error, 'schema.source.ambiguous');
184
+ assert.equal(workspace.sources[0], first);
185
+ assert.equal(workspace.sources[1], second);
186
+ }
187
+
188
+ // 14. Generic owner/security boundaries remain intact.
189
+ {
190
+ const commandSource = readFileSync(new URL('../app/schemaNavigationCommand.js', import.meta.url), 'utf8');
191
+ const materializationSource = readFileSync(new URL('../app/schemaNavigationMaterialization.js', import.meta.url), 'utf8');
192
+ for (const source of [commandSource, materializationSource]) {
193
+ assert.equal(/tiinex\.topic\.v1|tiinex\.task\.v1|Tiinex\/docs/u.test(source), false);
194
+ assert.equal(/\beval\s*\(|\bnew\s+Function\s*\(|import\s*\(\s*['"`]https?:/u.test(source), false);
195
+ }
196
+ assert.equal(/\.findIndex\(\(item\) => sameRecordIdentity/u.test(commandSource + materializationSource), false, 'first-hit materialization authority must stay removed');
197
+ assert.equal(/source\.repo \|\| source\.repository \|\| source\.config\?\.repo/u.test(materializationSource), false, 'first-value source repo authority must stay removed');
198
+ assert.equal(/source\.ref \|\| source\.config\?\.ref/u.test(materializationSource), false, 'first-value source ref authority must stay removed');
199
+ }
200
+
201
+ console.log('post-v470 schema reading-contract materialization identity + source coalescing authority correction: PASS');
202
+
203
+ function declaring(id, target) {
204
+ const current = target ? `[${schemaId}](${target})` : schemaId;
205
+ const markdown = `# Continuity Context\n\n- Envelope Schema: tiinex.root.v1\n- Current\n - Current Schema: ${current}\n - Created At: 2026-08-21 10:00:00\n - Summary: ${id}\n\n---\n\n# ${id}\n`;
206
+ return Object.assign(createRecordFromMarkdown(markdown, { path: `work/${id}.trace.md`, sourceMode: 'archive-local' }), { id, schemaId, currentSchemaId: schemaId });
207
+ }
208
+
209
+ function httpRepresentationRecord(id, target, markdown) {
210
+ return { id, schemaId, currentSchemaId: schemaId, path: `ordinary/${id}.txt`, sourceMode: 'source-backed', lifecycleStatus: '', markdown,
211
+ source: { id: `src-${id}`, adapterId: 'http', sourceKind: 'http.file', sourceBacked: true, permalink: target },
212
+ sourceTarget: { sourceArtifactPath: target, inputTarget: target, browseUrl: target, rawUrl: target } };
213
+ }
214
+
215
+ function throwingRecord(id, governedSchemaId, path, onRead) {
216
+ return { id, schemaId: governedSchemaId, currentSchemaId: governedSchemaId, path, get markdown() { onRead(); throw new Error('unrelated markdown read'); } };
217
+ }
218
+
219
+ function githubTuple() {
220
+ const repo = 'Acme/repo'; const ref = 'main'; const path = 'schemas/topic.schema.md';
221
+ return { repo, ref, path, rootPath: 'schemas', blob: `https://github.com/${repo}/blob/${ref}/${path}`, raw: `https://raw.githubusercontent.com/${repo}/${ref}/${path}` };
222
+ }
223
+
224
+ function coherentGithubSource(id, tuple) {
225
+ return { id, label: tuple.repo, kind: 'github-tree', adapterId: 'github', sourceKind: 'github.repo', repo: tuple.repo, repository: tuple.repo, ref: tuple.ref, rootPath: tuple.rootPath,
226
+ sourceBacked: true, originReferenceSource: false, recoveryOnly: false, loadable: true, explicitFileRefs: [], config: { repo: tuple.repo, ref: tuple.ref, rootPath: tuple.rootPath, explicitFileRefs: [] } };
227
+ }
228
+
229
+ function workspaceWith(label, ...records) { return workspaceWithId(`ws-v470-${label}`, ...records); }
230
+ function workspaceWithId(id, ...records) {
231
+ const state = lifecycle.createWorkspace(lifecycle.makeEmptyAppState(), { id, name: 'v470' }).state;
232
+ const workspace = lifecycle.activeWorkspace(state);
233
+ workspace.records = records;
234
+ return { state, workspace };
235
+ }
236
+ function response(body, url) { return { ok: true, status: 200, url, redirected: false, text: async () => body }; }
@@ -0,0 +1,196 @@
1
+ import assert from 'node:assert/strict';
2
+ import { createRecordFromMarkdown } from '@tiinex/core/artifacts/artifact.record.js';
3
+ import { runLocalMaterialImportCommand } from '../app/localMaterialCommand.js';
4
+ import { applyGithubSourceMaterializationCommand } from '../app/githubSourceMaterializationCommand.js';
5
+ import { loadFullLineageCommand } from '../app/lineageCommand.js';
6
+ import { buildWorkspaceTreeExportBundle } from '@tiinex/core/export/tree.bundle.js';
7
+ import { exportTreeZipUint8Array } from '@tiinex/core/export/package.zip.js';
8
+ import { buildWorkspaceMaterialLedger } from '../workspaces/workspace.materialLedger.js';
9
+ import { stateWithSourceMaterialCleared } from '../workspaces/workspace.sourceMaterial.js';
10
+ import '../sources/source.identity.js';
11
+ import '../workspaces/workspace.lifecycle.js';
12
+
13
+ const lifecycle = globalThis.TiinexWorkspaceLifecycle;
14
+ const clock = () => '2026-08-09T00:00:00.000Z';
15
+
16
+ const issuePath = '.topics/.github/tiinusen/socials/.issues/3/000-fs25-markaryd.workspace.md';
17
+ const localChildPath = '.topics/.github/tiinusen/socials/.issues/3/004-fler-bondg-rdar.trace.md';
18
+
19
+ const localBundle = {
20
+ schema: 'tiinex.export.tree.bundle.v1',
21
+ packageEnvelope: false,
22
+ files: [
23
+ { path: '.topics/gaming/root.workspace.md', kind: 'workspace-markdown', content: workspaceMarkdown('Gaming Import Shell') },
24
+ { path: localChildPath, kind: 'artifact-markdown', content: artifactMarkdown('Fler bondgårdar', 'tiinex.discovery.finding.v1', 'Gräns i spelet är nådd.', { integrity: 'fler-bondgardar' }) },
25
+ { path: issuePath, kind: 'workspace-markdown', content: workspaceMarkdown('FS25 Markaryd', { integrity: 'fs25-markaryd' }) },
26
+ { path: 'assets/evidence/local-note.txt', kind: 'asset-content', content: 'local evidence' }
27
+ ]
28
+ };
29
+
30
+ const imported = await runLocalMaterialImportCommand({
31
+ lifecycle,
32
+ state: lifecycle.makeEmptyAppState(),
33
+ fileList: [fileFromZip('tiinex-tree-gaming.zip', exportTreeZipUint8Array(localBundle))],
34
+ options: { clock, sourceMode: 'drop' }
35
+ });
36
+ assert.equal(imported.ok, true, imported.error);
37
+ let state = imported.state;
38
+ const importWorkspace = lifecycle.activeWorkspace(state);
39
+ assert.equal(importWorkspace.records.length, 2, 'local tree import rehydrates leaf + workspace artifacts on one canonical record spine');
40
+ assert.equal(importWorkspace.assets.length, 1, 'local tree import rehydrates assets');
41
+ assert.equal(Object.prototype.hasOwnProperty.call(importWorkspace, 'workspaceMergeCandidates'), false, 'new local import does not create the legacy candidate runtime shape');
42
+ assert.equal(importWorkspace.records.filter((record) => record.source?.adapterId === 'local').length, 2, 'imported artifacts stay browser-local/session');
43
+ assert(importWorkspace.records.some((record) => record.path === issuePath && record.workspaceArtifactRole?.openEligible), 'workspace artifact carries Open/Merge capability as a record role');
44
+
45
+ const registered = lifecycle.addWorkspaceSource(state, importWorkspace.id, {
46
+ label: 'Tiinusen/socials',
47
+ repository: 'Tiinusen/socials',
48
+ rootPath: '.topics',
49
+ issueDiscovery: true,
50
+ issueUrls: 'https://github.com/Tiinusen/socials/issues/3',
51
+ requestedSurfaces: { issueSnapshots: { requested: true }, repoFiles: { requested: false }, explicitFiles: { requested: false } }
52
+ });
53
+ assert.equal(registered.ok, true, registered.error);
54
+ state = registered.state;
55
+ const source = registered.source;
56
+ const sourceRecords = [
57
+ sourceRecord('FS25 Markaryd', 'tiinex.workspace.v1', issuePath, workspaceMarkdown('FS25 Markaryd', { integrity: 'fs25-markaryd' })),
58
+ sourceRecord('Lagar och regler', 'tiinex.topic.v1', '.topics/.github/tiinusen/socials/.issues/3/comment-000-lagar-och-regler.trace.md', artifactMarkdown('Lagar och regler', 'tiinex.topic.v1', 'Nu ska vi få ordning på torpet.', { integrity: 'lagar' })),
59
+ sourceRecord('§1 Ångkvistlagen', 'tiinex.decision.v1', '.topics/.github/tiinusen/socials/.issues/3/comment-001-1-ngkvistlagen.trace.md', artifactMarkdown('§1 Ångkvistlagen', 'tiinex.decision.v1', 'Regelutkast för Ångkvistlagen.', { integrity: 'angkvistlagen' })),
60
+ sourceRecord('Klagomuren', 'tiinex.topic.v1', '.topics/.github/tiinusen/socials/.issues/3/comment-002-klagomuren.trace.md', artifactMarkdown('Klagomuren', 'tiinex.topic.v1', 'Klagomuren är parent till fler bondgårdar.', { integrity: 'klagomuren' })),
61
+ sourceRecord('Fler bondgårdar', 'tiinex.discovery.finding.v1', localChildPath, artifactMarkdown('Fler bondgårdar', 'tiinex.discovery.finding.v1', 'Gräns i spelet är nådd.', { trace: 'comment-002-klagomuren.trace.md', integrity: 'fler-bondgardar' }))
62
+ ];
63
+ const materialized = applyGithubSourceMaterializationCommand({
64
+ lifecycle,
65
+ state,
66
+ workspaceId: importWorkspace.id,
67
+ source,
68
+ sourceId: source.id,
69
+ sourceLabel: source.label,
70
+ adapterResult: { okCount: sourceRecords.length, records: sourceRecords, diagnostics: { surfaces: { issueSnapshots: { loaded: sourceRecords.length } } } },
71
+ repository: 'Tiinusen/socials',
72
+ rootPath: '.topics',
73
+ issueDiscovery: true,
74
+ issueUrls: 'https://github.com/Tiinusen/socials/issues/3',
75
+ requestedSurfaces: source.requestedSurfaces,
76
+ selectedTransportSurfaces: ['issueSnapshots'],
77
+ transportLabel: 'proxy',
78
+ transportRefreshTier: 'proxy'
79
+ });
80
+ assert.equal(materialized.ok, true, materialized.error);
81
+ state = materialized.state;
82
+ const sourceWorkspace = state.workspaces.find((workspace) => workspace.id === importWorkspace.id);
83
+ const sourceAfter = sourceWorkspace.sources.find((item) => item.id === source.id);
84
+ assert.equal(sourceAfter.discoveryState, 'loaded', 'materialized source is marked loaded');
85
+ assert.equal(sourceAfter.count, 5, 'source count tracks inserted source-backed records');
86
+ assert.equal(sourceAfter.surfaces.issueSnapshots.loaded, 5, 'issue surface count survives source command');
87
+ assert.equal(sourceWorkspace.records.filter((record) => record.source?.id === source.id).length, 5, 'source command inserts all source issue artifacts');
88
+ assert.equal(sourceWorkspace.records.filter((record) => record.source?.adapterId === 'local').length, 0, 'verified equivalent local artifacts are pruned once source becomes canonical');
89
+ assert.equal(Object.prototype.hasOwnProperty.call(sourceWorkspace, 'workspaceMergeCandidates'), false, 'workspace artifacts stay canonical records without a legacy candidate runtime shape');
90
+ const ledger = buildWorkspaceMaterialLedger(sourceWorkspace, { displayOptions: sourceWorkspace.displayOptions || {} });
91
+ assert.equal(ledger.recordsBySource[source.id], 5, 'ledger source count matches inserted issue artifacts');
92
+ assert.equal(Number(ledger.groupedRecordsBySource.local || 0), 0, 'exact local duplicates are not hidden as shadow payloads');
93
+ assert.equal(ledger.workspaceArtifactsBySource[source.id], 1, 'ledger counts source-backed workspace artifact records');
94
+ assert.equal(materialized.materialLedgerReceipt.rawAdapterRecords, 5, 'source receipt keeps raw adapter count');
95
+ assert.equal(materialized.materialLedgerReceipt.sourceRecords, 5, 'source receipt keeps inserted source count');
96
+ assert.equal(materialized.materialLedgerReceipt.sourceWorkspaceArtifacts, 1, 'source receipt exposes workspace artifact role without candidate duplication');
97
+
98
+ const cleared = stateWithSourceMaterialCleared(state, importWorkspace.id, source.id, { discoveryState: 'deferred' });
99
+ assert.equal(cleared.ok, true, cleared.error);
100
+ assert.equal(cleared.workspace.records.some((record) => record.source?.id === source.id), false, 'source refresh clear removes source-backed records');
101
+ assert.equal(cleared.workspace.records.filter((record) => record.source?.adapterId === 'local').length, 0, 'source clear does not resurrect deduplicated local copies');
102
+ assert.equal(cleared.workspace.assets.length, 1, 'independent local asset remains after source clear');
103
+
104
+ const exportBundle = buildWorkspaceTreeExportBundle(sourceWorkspace, { clock });
105
+ assert.equal(exportBundle.packageEnvelope, false, 'ordinary tree export remains envelope-free');
106
+ assert.equal(exportBundle.counts.records, 4, 'tree export counts non-workspace artifact Markdown separately');
107
+ assert.equal(exportBundle.counts.workspaceEntries, 2, 'tree export includes current workspace entry and canonical workspace artifact record');
108
+ assert(exportBundle.files.some((file) => file.path === issuePath), 'tree export preserves source-canonical workspace entry path');
109
+ assert(!exportBundle.files.some((file) => file.path.startsWith('tiinex.package/')), 'ordinary tree export does not include package envelope paths');
110
+
111
+ const reimported = await runLocalMaterialImportCommand({
112
+ lifecycle,
113
+ state: lifecycle.makeEmptyAppState(),
114
+ fileList: [fileFromZip('roundtrip.zip', exportTreeZipUint8Array(exportBundle))],
115
+ options: { clock, sourceMode: 'acceptance-roundtrip' }
116
+ });
117
+ assert.equal(reimported.ok, true, reimported.error);
118
+ const roundtripWorkspace = lifecycle.activeWorkspace(reimported.state);
119
+ assert(roundtripWorkspace.records.length >= 5, 'roundtrip rehydrates exported artifact records');
120
+ assert.equal(roundtripWorkspace.records.filter((record) => record.source?.adapterId === 'github').length, 0, 'roundtrip import remains local/session and does not infer GitHub source-backed authority');
121
+ assert.equal(Object.prototype.hasOwnProperty.call(roundtripWorkspace, 'workspaceMergeCandidates'), false, 'roundtrip preserves workspace capability on records without legacy candidate runtime shape');
122
+ assert(roundtripWorkspace.records.some((record) => record.path === issuePath && record.workspaceArtifactRole?.openEligible), 'roundtrip preserves workspace artifact capability');
123
+
124
+ const lineageChildMarkdown = `# Continuity Context\n\n- Envelope Schema: [tiinex.root.v1](tiinex.root.v1.schema.md)\n- Parent\n - Parent Schema: [tiinex.topic.v1](tiinex.topic.v1.schema.md)\n - Trace: [Recovered parent](recovered-parent.trace.md)\n - Origin: [Recovered parent](https://github.com/Tiinex/docs/blob/abc123/.topics/recovered-parent.trace.md)\n- Current\n - Current Schema: [tiinex.topic.v1](tiinex.topic.v1.schema.md)\n - Summary: Local child with explicit source boundary\n\n---\n\n# Local Child With Explicit Origin`;
125
+ const lineageChild = Object.assign(createRecordFromMarkdown(lineageChildMarkdown, { path: 'local/child.trace.md', sourceMode: 'archive-local' }), {
126
+ id: 'local:acceptance-origin-child',
127
+ source: { id: 'local', kind: 'local', adapterId: 'local', sourceKind: 'local.session' }
128
+ });
129
+ const lineageCreated = lifecycle.createWorkspace(lifecycle.makeEmptyAppState(), { name: 'Acceptance Lineage' }, { clock });
130
+ const lineageWorkspace = lifecycle.activeWorkspace(lineageCreated.state);
131
+ lineageWorkspace.records = [lineageChild];
132
+ lineageWorkspace.sources = [{ id: 'local', kind: 'local', adapterId: 'local', sourceKind: 'local.session', sourceBacked: false }];
133
+ const fetched = [];
134
+ const lineageLoaded = await loadFullLineageCommand({
135
+ lifecycle,
136
+ state: lineageCreated.state,
137
+ workspace: lineageWorkspace,
138
+ selectedRecordId: lineageChild.id,
139
+ fetchImpl: async (url) => {
140
+ fetched.push(String(url || ''));
141
+ return { ok: true, status: 200, statusText: 'OK', transportTier: 'direct', text: async () => artifactMarkdown('Recovered Parent', 'tiinex.topic.v1', 'Recovered parent', { integrity: 'recovered-parent' }) };
142
+ },
143
+ clock
144
+ });
145
+ assert.equal(lineageLoaded.ok, true, lineageLoaded.error);
146
+ assert.equal(lineageLoaded.recoveredParents, 1, 'explicit origin recovers missing parent without a pre-added discovery source');
147
+ assert.equal(lineageLoaded.lineageLoadReport.state, 'complete');
148
+ assert(fetched.includes('https://raw.githubusercontent.com/tiinex/docs/abc123/.topics/recovered-parent.trace.md'), 'lineage recovery uses exact GitHub blob ref from Origin');
149
+ const lineageAfter = lifecycle.activeWorkspace(lineageLoaded.state);
150
+ assert.equal(lineageAfter.records.find((record) => record.id === lineageChild.id).source.id, 'local', 'declaring imported/local child remains local after recovery');
151
+ const recoverySource = lineageAfter.sources.find((item) => item.id === 'origin:github:tiinex:docs');
152
+ assert(recoverySource && recoverySource.originReferenceSource, 'recovery-only source boundary is registered');
153
+ assert.equal(recoverySource.sourceBacked, false, 'recovery-only boundary does not claim imported material is source-backed');
154
+
155
+ console.log('✓ recovery acceptance scenarios passed');
156
+
157
+ function fileFromZip(name, zip) {
158
+ return { name, size: zip.byteLength, type: 'application/zip', arrayBuffer: async () => zip.buffer.slice(zip.byteOffset, zip.byteOffset + zip.byteLength) };
159
+ }
160
+
161
+ function sourceRecord(title, schemaId, path, markdown) {
162
+ return {
163
+ title,
164
+ path,
165
+ kind: schemaId,
166
+ schemaId,
167
+ markdown,
168
+ sourceMode: 'github-issue-embedded-artifact',
169
+ sourceTarget: {
170
+ surface: 'issueSnapshots',
171
+ targetKind: 'github-issue-embedded-artifact',
172
+ inputTarget: 'https://github.com/Tiinusen/socials/issues/3',
173
+ sourceArtifactPath: path
174
+ },
175
+ integrity: { entries: [{ towards: 'self', value: integrityFromMarkdown(markdown) }] }
176
+ };
177
+ }
178
+
179
+ function workspaceMarkdown(title, options = {}) {
180
+ const integrity = options.integrity || slug(title);
181
+ return `# Continuity Context\n\n- Envelope Schema: [tiinex.root.v1](tiinex.root.v1.schema.md)\n- Current\n - Current Schema: [tiinex.workspace.v1](tiinex.workspace.v1.schema.md)\n - Created At: 2026-08-09\n - Summary: ${title} workspace.\n\n---\n\n# ${title}\n\n- Browser Title: ${title}\n\n---\n\n# Continuity Integrity\n\n- sha256-base64url-c14n-v2\n - Towards: self\n - Value: ${integrity}\n`;
182
+ }
183
+
184
+ function artifactMarkdown(title, schemaId, summary, options = {}) {
185
+ const parent = options.trace ? `- Parent\n - Parent Schema: [tiinex.topic.v1](tiinex.topic.v1.schema.md)\n - Trace: [Parent](${options.trace})\n` : '';
186
+ const integrity = options.integrity || slug(title);
187
+ return `# Continuity Context\n\n- Envelope Schema: [tiinex.root.v1](tiinex.root.v1.schema.md)\n${parent}- Current\n - Current Schema: [${schemaId}](${schemaId}.schema.md)\n - Created At: 2026-08-09\n - Summary: ${summary}\n\n---\n\n# ${title}\n\n${summary}\n\n---\n\n# Continuity Integrity\n\n- sha256-base64url-c14n-v2\n - Towards: self\n - Value: ${integrity}\n`;
188
+ }
189
+
190
+ function integrityFromMarkdown(markdown = '') {
191
+ return String(markdown).match(/-\s*Value:\s*(.+)$/mi)?.[1]?.trim() || '';
192
+ }
193
+
194
+ function slug(value = '') {
195
+ return String(value || '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'fixture';
196
+ }