@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.
- package/LICENSE +201 -0
- package/NOTICE +31 -0
- package/README.md +26 -0
- package/docs/CONSUMER-CONTRACT.md +65 -0
- package/package.json +94 -0
- package/src/acceptance/knownScenarios.case.mjs +48 -0
- package/src/acceptance/knownScenarios.js +89 -0
- package/src/acceptance/postV423CanonicalTransitionProductVerticalSlice.case.mjs +774 -0
- package/src/acceptance/postV437M0ETimePortalProductParityClosure.case.mjs +51 -0
- package/src/acceptance/postV447M0FGithubSocialPublicationProductIntegration.case.mjs +33 -0
- package/src/acceptance/postV450M0ProductAcceptanceHardening.case.mjs +82 -0
- package/src/acceptance/postV470SchemaReadingContractMaterializationIdentitySourceCoalescingAuthorityCorrection.case.mjs +236 -0
- package/src/acceptance/recoveryAcceptance.case.mjs +196 -0
- package/src/adapters/adapter.definition.schema.json +33 -0
- package/src/adapters/archive/archive.adapter.case.mjs +212 -0
- package/src/adapters/export/export.adapter.js +79 -0
- package/src/adapters/git-native/git-native.adapter.js +43 -0
- package/src/adapters/github/github.adapter.case.mjs +843 -0
- package/src/adapters/github/github.adapter.js +395 -0
- package/src/adapters/github/github.issueEmbedded.js +262 -0
- package/src/adapters/github/github.issueMirror.js +309 -0
- package/src/adapters/github/github.issueSnapshot.js +475 -0
- package/src/adapters/github/github.issueSurface.js +188 -0
- package/src/adapters/github/github.issueTransport.js +237 -0
- package/src/adapters/github/github.publicationRead.js +24 -0
- package/src/adapters/github/github.readTransport.js +18 -0
- package/src/adapters/github/github.repoDiscovery.js +222 -0
- package/src/adapters/github/github.repoMirror.js +255 -0
- package/src/adapters/github/github.repoProxy.js +276 -0
- package/src/adapters/github/github.repoSurface.js +60 -0
- package/src/adapters/github/github.transportDiagnostics.js +68 -0
- package/src/adapters/local/local.adapter.case.mjs +72 -0
- package/src/adapters/local/local.adapter.js +188 -0
- package/src/adapters/registry.js +35 -0
- package/src/adapters/static/static.adapter.js +84 -0
- package/src/app/App.js +1 -0
- package/src/app/TiinexApp.jsx +822 -0
- package/src/app/appShell.views.jsx +58 -0
- package/src/app/artifactAuthoringCapability.js +49 -0
- package/src/app/boot/bootApp.js +19 -0
- package/src/app/boot/environment.js +1 -0
- package/src/app/canonicalAuthoringValues.js +4 -0
- package/src/app/canonicalCreationProductController.js +57 -0
- package/src/app/canonicalCreationProductSettlement.case.mjs +10 -0
- package/src/app/canonicalCreationProductSettlement.js +11 -0
- package/src/app/canonicalReferenceLocalCreateCommand.js +210 -0
- package/src/app/canonicalReferenceTargets.js +73 -0
- package/src/app/canonicalTransitionLocalCreateCommand.js +217 -0
- package/src/app/defaultWorkspaceStart.case.mjs +39 -0
- package/src/app/defaultWorkspaceStart.js +65 -0
- package/src/app/defaultWorkspaceStartCommand.js +55 -0
- package/src/app/durableLocalMutationPolicy.js +21 -0
- package/src/app/githubMaterializationSummary.js +69 -0
- package/src/app/githubProgress.js +25 -0
- package/src/app/githubSourceInput.js +47 -0
- package/src/app/githubSourceMaterializationCommand.js +97 -0
- package/src/app/githubSourceOperation.js +226 -0
- package/src/app/governanceDialogData.js +27 -0
- package/src/app/handoffPackageImportCommand.js +182 -0
- package/src/app/historyAuthority.js +53 -0
- package/src/app/initialWorkspaceBootstrapOperation.js +105 -0
- package/src/app/lineageCommand.js +118 -0
- package/src/app/lineageSourceRecovery.js +339 -0
- package/src/app/localDraftMutationCommand.js +174 -0
- package/src/app/localMaterialCommand.js +124 -0
- package/src/app/nodeGraphVerse.case.mjs +111 -0
- package/src/app/persistenceOwnership.js +92 -0
- package/src/app/productStateBoundary.js +7 -0
- package/src/app/providers/AppProviders.js +1 -0
- package/src/app/providers/LocaleProvider.js +1 -0
- package/src/app/providers/SchemaRegistryProvider.js +1 -0
- package/src/app/providers/WorkspaceProvider.js +1 -0
- package/src/app/publicTarget.js +251 -0
- package/src/app/publicTargetRestoreCommand.js +149 -0
- package/src/app/recordUi.cache.js +35 -0
- package/src/app/recordUi.js +11 -0
- package/src/app/routes/RouteSurface.js +1 -0
- package/src/app/routes/routes.js +1 -0
- package/src/app/runtimeState.js +54 -0
- package/src/app/schemaCurrentDeclaration.js +69 -0
- package/src/app/schemaFactoryLocalCreateCommand.js +101 -0
- package/src/app/schemaFactoryViewerProof.case.mjs +134 -0
- package/src/app/schemaFactoryViewerProof.js +20 -0
- package/src/app/schemaNavigationCommand.js +285 -0
- package/src/app/schemaNavigationMaterialization.js +171 -0
- package/src/app/schemaNavigationRuntimeCatalog.js +25 -0
- package/src/app/schemaNavigationState.js +66 -0
- package/src/app/schemaReadingContractQualification.js +91 -0
- package/src/app/schemaSourceRecovery.js +373 -0
- package/src/app/scrollPersistence.js +30 -0
- package/src/app/semanticOperationHistory.js +18 -0
- package/src/app/shareActionCommand.js +55 -0
- package/src/app/shareProjection.js +190 -0
- package/src/app/shell/AppShell.js +1 -0
- package/src/app/shell/Header.js +1 -0
- package/src/app/shell/Navigation.js +1 -0
- package/src/app/shell/SurfaceSwitcher.js +1 -0
- package/src/app/sourceTransportRefresh.js +176 -0
- package/src/app/startupOwnership.js +40 -0
- package/src/app/startupPresentation.case.mjs +34 -0
- package/src/app/startupPresentation.js +33 -0
- package/src/app/startupPresentation.views.jsx +21 -0
- package/src/app/startupRenderPhase.js +9 -0
- package/src/app/startupWorkspaceCommand.js +62 -0
- package/src/app/startupWorkspaceConfigApplication.js +49 -0
- package/src/app/statePersistenceScheduler.js +106 -0
- package/src/app/tiinexAppConfigPlan.js +108 -0
- package/src/app/tiinexAppConfigSource.js +349 -0
- package/src/app/tiinexAppStartupSource.js +79 -0
- package/src/app/tiinexHostedWorkspaceConventions.js +572 -0
- package/src/app/timePortalHistoricalRead.js +114 -0
- package/src/app/timePortalSnapshotResolution.js +53 -0
- package/src/app/urlMaterialCommand.js +24 -0
- package/src/app/useCanonicalPlacementSelectionOptions.js +9 -0
- package/src/app/useCanonicalReferenceSelectionOptions.js +8 -0
- package/src/app/useLocalMaterialIntake.js +68 -0
- package/src/app/useTimePortalProductController.jsx +111 -0
- package/src/app/useWorkspaceEntrypointIntake.js +77 -0
- package/src/app/useWorkspaceSelectionProductController.jsx +21 -0
- package/src/app/viewState.js +35 -0
- package/src/app/viewport.js +21 -0
- package/src/app/visualDormancy.js +286 -0
- package/src/app/workspaceContinuityNotices.js +32 -0
- package/src/app/workspaceDisplayCounts.js +9 -0
- package/src/app/workspaceEntrypointIntakeCommand.js +87 -0
- package/src/app/workspaceEntrypointProductRouting.case.mjs +20 -0
- package/src/app/workspaceExportCommand.js +21 -0
- package/src/app/workspaceExportDownload.js +23 -0
- package/src/app/workspaceExportExecutionCommand.js +10 -0
- package/src/app/workspaceGithubPublication.js +237 -0
- package/src/app/workspaceHandoffExport.js +56 -0
- package/src/app/workspaceHomeTarget.js +9 -0
- package/src/app/workspaceMulticolumn.js +113 -0
- package/src/app/workspaceNavigationParity.case.mjs +110 -0
- package/src/app/workspaceOpenProgress.js +26 -0
- package/src/app/workspacePlacementOptions.js +46 -0
- package/src/app/workspaceRecordActions.js +158 -0
- package/src/app/workspaceScopedInteraction.js +68 -0
- package/src/app/workspaceSelectionOriginContext.js +29 -0
- package/src/app/workspaceSelectionSession.js +54 -0
- package/src/app/workspaceSourceCloseCommand.js +25 -0
- package/src/app/workspaceSpineProductRouting.case.mjs +22 -0
- package/src/app/workspaceStartupTransition.js +32 -0
- package/src/app/workspaceWindow.js +85 -0
- package/src/artifacts/artifact.fixture.js +1 -0
- package/src/artifacts/artifact.identity.js +6 -0
- package/src/artifacts/artifact.identityAggregation.js +218 -0
- package/src/artifacts/artifact.model.js +2 -0
- package/src/artifacts/artifact.parse.case.mjs +196 -0
- package/src/artifacts/artifact.participantIndex.js +189 -0
- package/src/artifacts/fixtures/evidence.trace.md +50 -0
- package/src/artifacts/fixtures/topic.trace.md +33 -0
- package/src/artifacts/fixtures/unknown-schema.trace.md +25 -0
- package/src/audit/audit.findings.js +1 -0
- package/src/audit/audit.model.js +2 -0
- package/src/audit/audit.plan.js +13 -0
- package/src/audit/audit.report.js +12 -0
- package/src/audit/audit.severity.js +1 -0
- package/src/audit/audit.traverse.js +119 -0
- package/src/audit/integrity/auditIntegrity.checks.js +1 -0
- package/src/audit/integrity/auditIntegrity.compare.js +1 -0
- package/src/audit/lineage/auditLineage.load.js +1 -0
- package/src/audit/lineage/auditLineage.plan.js +1 -0
- package/src/audit/lineage/auditLineage.resolve.js +12 -0
- package/src/audit/sources/auditSources.boundaries.js +1 -0
- package/src/audit/sources/auditSources.checks.js +1 -0
- package/src/audit/validation/auditValidation.recheck.js +1 -0
- package/src/audit/validation/auditValidation.run.js +1 -0
- package/src/build.identity.js +15 -0
- package/src/commands/command.vocabulary.js +14 -0
- package/src/conformance/conformance.fixtures.js +151 -0
- package/src/conformance/conformance.run.js +238 -0
- package/src/data/applicationDataStore.js +23 -0
- package/src/data/companionAccess.js +35 -0
- package/src/diagnostics/events.js +1 -0
- package/src/diagnostics/invariant.js +1 -0
- package/src/diagnostics/schemaBindingChecks.js +1 -0
- package/src/diagnostics/schemaModuleChecks.js +1 -0
- package/src/diagnostics/sourceBoundaryChecks.js +5 -0
- package/src/diagnostics/sourceTransport.report.js +190 -0
- package/src/discovery/discovery.controls.js +7 -0
- package/src/export/export.plan.js +182 -0
- package/src/export/handoff.plan.js +50 -0
- package/src/export/package.builder.case.mjs +97 -0
- package/src/export/package.controlTopology.case.mjs +130 -0
- package/src/export/package.zip.case.mjs +33 -0
- package/src/graph/artifactGraph.model.js +344 -0
- package/src/graph/artifactGraph.project.js +139 -0
- package/src/graph/artifactGraph.worker.js +10 -0
- package/src/i18n/i18n.keys.js +1 -0
- package/src/i18n/i18n.provider.js +1 -0
- package/src/i18n/i18n.resolve.js +5 -0
- package/src/i18n/locales/en/common.json +4 -0
- package/src/i18n/locales/en/schemas/evidence.json +3 -0
- package/src/i18n/locales/en/schemas/presentation-surface.json +3 -0
- package/src/i18n/locales/en/schemas/preservation.json +3 -0
- package/src/i18n/locales/en/schemas/root.json +3 -0
- package/src/i18n/locales/en/schemas/schema-module.json +3 -0
- package/src/i18n/locales/en/schemas/topic.json +3 -0
- package/src/i18n/locales/en/surfaces/audit.json +3 -0
- package/src/i18n/locales/en/surfaces/create.json +3 -0
- package/src/i18n/locales/en/surfaces/detail.json +3 -0
- package/src/i18n/locales/en/surfaces/display-options.json +3 -0
- package/src/i18n/locales/en/surfaces/edit.json +3 -0
- package/src/i18n/locales/en/surfaces/feed.json +3 -0
- package/src/i18n/locales/en/surfaces/lineage.json +3 -0
- package/src/i18n/locales/en/surfaces/preview.json +3 -0
- package/src/i18n/locales/en/surfaces/share.json +3 -0
- package/src/i18n/locales/en/surfaces/source-settings.json +3 -0
- package/src/i18n/locales/en/surfaces/tree.json +3 -0
- package/src/i18n/locales/sv/common.json +4 -0
- package/src/i18n/locales/sv/schemas/evidence.json +3 -0
- package/src/i18n/locales/sv/schemas/presentation-surface.json +3 -0
- package/src/i18n/locales/sv/schemas/preservation.json +3 -0
- package/src/i18n/locales/sv/schemas/root.json +3 -0
- package/src/i18n/locales/sv/schemas/schema-module.json +3 -0
- package/src/i18n/locales/sv/schemas/topic.json +3 -0
- package/src/i18n/locales/sv/surfaces/audit.json +3 -0
- package/src/i18n/locales/sv/surfaces/create.json +3 -0
- package/src/i18n/locales/sv/surfaces/detail.json +3 -0
- package/src/i18n/locales/sv/surfaces/display-options.json +3 -0
- package/src/i18n/locales/sv/surfaces/edit.json +3 -0
- package/src/i18n/locales/sv/surfaces/feed.json +3 -0
- package/src/i18n/locales/sv/surfaces/lineage.json +3 -0
- package/src/i18n/locales/sv/surfaces/preview.json +3 -0
- package/src/i18n/locales/sv/surfaces/share.json +3 -0
- package/src/i18n/locales/sv/surfaces/source-settings.json +3 -0
- package/src/i18n/locales/sv/surfaces/tree.json +3 -0
- package/src/index.js +10 -0
- package/src/integrity/integrity.testFixture.js +9 -0
- package/src/interaction/interaction.spine.js +12 -0
- package/src/lineage/lineage.audit.js +1 -0
- package/src/lineage/lineage.edges.js +1 -0
- package/src/main.js +319 -0
- package/src/main.jsx +34 -0
- package/src/multiverse/multiverse.model.js +10 -0
- package/src/parity/poc.m1ParityScenarios.js +42 -0
- package/src/parity/poc.parityLedger.js +261 -0
- package/src/publication/publication.githubSocialContract.case.mjs +247 -0
- package/src/publication/publication.preflight.case.mjs +64 -0
- package/src/react/TiinexApplication.jsx +39 -0
- package/src/react/VerseHost.jsx +29 -0
- package/src/react/applicationDataContext.jsx +30 -0
- package/src/react.js +2 -0
- package/src/readers/modes/audit.reader.js +1 -0
- package/src/readers/modes/detail.reader.js +1 -0
- package/src/readers/modes/handover.reader.js +1 -0
- package/src/readers/modes/mobile.reader.js +1 -0
- package/src/readers/modes/print.reader.js +1 -0
- package/src/readers/modes/scan.reader.js +1 -0
- package/src/readers/reader.model.js +1 -0
- package/src/readers/reader.resolve.js +2 -0
- package/src/reingest/reingest.plan.case.mjs +65 -0
- package/src/runtime.js +54 -0
- package/src/schemas/README.md +99 -0
- package/src/schemas/coordination/handoff/tiinex.handoff.v1.schema.md +614 -0
- package/src/schemas/coordination/project/tiinex.project.v1.schema.md +311 -0
- package/src/schemas/core/decision/tiinex.decision.v1.schema.md +227 -0
- package/src/schemas/core/evidence/tiinex.evidence.v1.schema.md +318 -0
- package/src/schemas/core/feedback/tiinex.feedback.v1.schema.md +243 -0
- package/src/schemas/core/interpretation/.transitions/evidence-to-interpretation-transition-definition.trace.md +102 -0
- package/src/schemas/core/interpretation/tiinex.interpretation.v1.schema.md +308 -0
- package/src/schemas/core/preservation/tiinex.preservation.v1.schema.md +312 -0
- package/src/schemas/core/relation/.generation/reference-relation-generation-authority.trace.md +185 -0
- package/src/schemas/core/relation/.transitions/topic-references-task-transition-definition.trace.md +119 -0
- package/src/schemas/core/relation/tiinex.relation.v1.schema.md +240 -0
- package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.schema.md +550 -0
- package/src/schemas/core/signal/tiinex.signal.v1.schema.md +239 -0
- package/src/schemas/core/task/.transitions/create-task-transition-definition.trace.md +93 -0
- package/src/schemas/core/task/.transitions/topic-to-task-transition-definition.trace.md +102 -0
- package/src/schemas/core/task/task-semantic-package.trace.md +53 -0
- package/src/schemas/core/task/tiinex.task.v1-transitions.trace.md +33 -0
- package/src/schemas/core/task/tiinex.task.v1.authoring.js +65 -0
- package/src/schemas/core/task/tiinex.task.v1.schema.md +229 -0
- package/src/schemas/core/topic/.transitions/create-topic-transition-definition.trace.md +93 -0
- package/src/schemas/core/topic/tiinex.topic.v1-transitions.trace.md +33 -0
- package/src/schemas/core/topic/tiinex.topic.v1.schema.md +197 -0
- package/src/schemas/core/topic/topic-semantic-package.trace.md +53 -0
- package/src/schemas/discovery/finding/tiinex.discovery.finding.v1.schema.md +240 -0
- package/src/schemas/discovery/tiinex.discovery.v1.schema.md +294 -0
- package/src/schemas/manifest.json +367 -0
- package/src/schemas/origins.js +46 -0
- package/src/schemas/party/organization/tiinex.party.organization.v1.schema.md +290 -0
- package/src/schemas/party/role/tiinex.party.role.v1.schema.md +298 -0
- package/src/schemas/party/tiinex.party.v1.schema.js +14 -0
- package/src/schemas/party/tiinex.party.v1.schema.json +23 -0
- package/src/schemas/party/tiinex.party.v1.schema.md +311 -0
- package/src/schemas/party/tiinex.party.v1.schema.runtime.json +2033 -0
- package/src/schemas/party/tiinex.party.v1.schema.source.js +9 -0
- package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.schema.md +476 -0
- package/src/schemas/reduction/tiinex.reduction.v1.schema.md +248 -0
- package/src/schemas/schema/module/tiinex.schema.module.v1.schema.md +465 -0
- package/src/schemas/schema.companionContract.case.mjs +259 -0
- package/src/schemas/schema.factory.case.mjs +256 -0
- package/src/schemas/schema.factory.viewerProjection.js +183 -0
- package/src/schemas/schemaMarkdownCatalog.js +19 -0
- package/src/schemas/tiinex.root.v1.schema.md +865 -0
- package/src/schemas/validation/finding/tiinex.validation.finding.v1.schema.md +309 -0
- package/src/schemas/validation/method/tiinex.validation.method.v1.schema.md +280 -0
- package/src/schemas/validation/report/tiinex.validation.report.v1.schema.md +300 -0
- package/src/schemas/workspace/tiinex.workspace.v1.schema.md +486 -0
- package/src/schemas/workspace/workspace.add.views.jsx +327 -0
- package/src/schemas/workspace/workspace.audit.views.jsx +160 -0
- package/src/schemas/workspace/workspace.auditBadge.views.jsx +98 -0
- package/src/schemas/workspace/workspace.canonicalReferenceDialog.views.jsx +63 -0
- package/src/schemas/workspace/workspace.canonicalTaskDialog.views.jsx +169 -0
- package/src/schemas/workspace/workspace.cardActions.js +9 -0
- package/src/schemas/workspace/workspace.cards.views.jsx +146 -0
- package/src/schemas/workspace/workspace.chrome.views.jsx +299 -0
- package/src/schemas/workspace/workspace.continuationDialog.views.jsx +80 -0
- package/src/schemas/workspace/workspace.discovery.views.jsx +63 -0
- package/src/schemas/workspace/workspace.discoveryRenderWindow.js +56 -0
- package/src/schemas/workspace/workspace.displayOptions.views.jsx +114 -0
- package/src/schemas/workspace/workspace.entrypointChoice.views.jsx +30 -0
- package/src/schemas/workspace/workspace.exportDialog.controller.jsx +40 -0
- package/src/schemas/workspace/workspace.exportDialog.views.jsx +142 -0
- package/src/schemas/workspace/workspace.governance.views.jsx +45 -0
- package/src/schemas/workspace/workspace.graph.views.jsx +134 -0
- package/src/schemas/workspace/workspace.lineage.views.jsx +307 -0
- package/src/schemas/workspace/workspace.read.views.jsx +105 -0
- package/src/schemas/workspace/workspace.recordActionButton.views.jsx +35 -0
- package/src/schemas/workspace/workspace.recordDialogs.views.jsx +257 -0
- package/src/schemas/workspace/workspace.selection.views.jsx +14 -0
- package/src/schemas/workspace/workspace.sourceReceipt.views.jsx +40 -0
- package/src/schemas/workspace/workspace.timePortal.views.jsx +56 -0
- package/src/schemas/workspace/workspace.tree.views.jsx +107 -0
- package/src/schemas/workspace/workspace.viewFormatting.js +172 -0
- package/src/schemas/workspace/workspace.views.jsx +210 -0
- package/src/source-settings/sourceSettings.model.js +7 -0
- package/src/sources/draft/draft.source.js +1 -0
- package/src/sources/github/github.loader.js +204 -0
- package/src/sources/github/github.permalink.js +1 -0
- package/src/sources/github/github.source.js +1 -0
- package/src/sources/github/github.transport.case.mjs +237 -0
- package/src/sources/github/github.transport.js +472 -0
- package/src/sources/local/local.source.js +1 -0
- package/src/sources/source.assetReferences.js +109 -0
- package/src/sources/source.boundaries.js +24 -0
- package/src/sources/source.identity.js +56 -0
- package/src/sources/source.model.case.mjs +26 -0
- package/src/sources/source.model.js +56 -0
- package/src/sources/source.presenter.js +66 -0
- package/src/sources/source.resolve.js +11 -0
- package/src/sources/static/static.source.js +1 -0
- package/src/sources/transport.policy.case.mjs +39 -0
- package/src/sources/transport.policy.js +81 -0
- package/src/storage/storage.policy.js +79 -0
- package/src/styles/app.css +8699 -0
- package/src/styles/responsive.css +10 -0
- package/src/styles/theme.css +4 -0
- package/src/styles/tokens.css +30 -0
- package/src/surfaces/audit/AuditSurface.js +1 -0
- package/src/surfaces/audit/audit.model.js +1 -0
- package/src/surfaces/audit/audit.render.js +1 -0
- package/src/surfaces/contracts.js +45 -0
- package/src/surfaces/create/CreateSurface.js +1 -0
- package/src/surfaces/create/create.model.js +1 -0
- package/src/surfaces/create/create.render.js +1 -0
- package/src/surfaces/detail/DetailSurface.js +1 -0
- package/src/surfaces/detail/detail.model.js +1 -0
- package/src/surfaces/detail/detail.render.js +1 -0
- package/src/surfaces/display-options/DisplayOptionsSurface.js +1 -0
- package/src/surfaces/display-options/displayOptions.model.js +1 -0
- package/src/surfaces/display-options/displayOptions.render.js +1 -0
- package/src/surfaces/edit/EditSurface.js +1 -0
- package/src/surfaces/edit/edit.model.js +1 -0
- package/src/surfaces/edit/edit.render.js +1 -0
- package/src/surfaces/feed/FeedSurface.js +1 -0
- package/src/surfaces/feed/feed.model.js +1 -0
- package/src/surfaces/feed/feed.render.js +1 -0
- package/src/surfaces/lineage/LineageSurface.js +1 -0
- package/src/surfaces/lineage/lineage.model.js +1 -0
- package/src/surfaces/lineage/lineage.render.js +1 -0
- package/src/surfaces/preview/PreviewSurface.js +1 -0
- package/src/surfaces/preview/preview.model.js +1 -0
- package/src/surfaces/preview/preview.render.js +1 -0
- package/src/surfaces/registry.js +58 -0
- package/src/surfaces/share/ShareSurface.js +1 -0
- package/src/surfaces/share/share.model.js +1 -0
- package/src/surfaces/share/share.render.js +1 -0
- package/src/surfaces/source-settings/SourceSettingsSurface.js +1 -0
- package/src/surfaces/source-settings/sourceSettings.model.js +1 -0
- package/src/surfaces/source-settings/sourceSettings.render.js +1 -0
- package/src/surfaces/surfaceContext.js +1 -0
- package/src/surfaces/tree/TreeSurface.js +1 -0
- package/src/surfaces/tree/tree.model.js +1 -0
- package/src/surfaces/tree/tree.render.js +1 -0
- package/src/tooling/portable/adapters/cli/cli.common-output.case.mjs +153 -0
- package/src/tooling/portable/adapters/cli/cli.handoff-sibling-allocation.case.mjs +52 -0
- package/src/tooling/portable/adapters/cli/cli.run.case.mjs +372 -0
- package/src/tooling/portable/adapters/cli/cli.summaryProjection.case.mjs +46 -0
- package/src/tooling/portable/audit/audit.capability.case.mjs +45 -0
- package/src/tooling/portable/fixtures/legacy-artifacts/collaboration/dogfood/001-tiinex-development-dogfood-collaboration-model.trace.fixture.txt +37 -0
- package/src/tooling/portable/fixtures/legacy-artifacts/handoff/tooling/001-v480-tooling-workflow-schema-enablement-handoff.trace.fixture.txt +108 -0
- 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
- package/src/tooling/portable/fixtures/legacy-artifacts/loom/role/001-loom-role.trace.fixture.txt +61 -0
- package/src/tooling/portable/fixtures/legacy-artifacts/sigma/role/001-1-sigma-role.trace.fixture.txt +61 -0
- 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
- 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
- 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
- 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
- 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
- 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
- package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-1-site-tooling-v471-portable-lineage-authoring-closure-result.trace.fixture.txt +48 -0
- package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/001-site-tooling-v471-portable-lineage-authoring-closure.trace.fixture.txt +39 -0
- package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/002-1-v475-canonical-artifact-envelope-reference-integrity-validation.trace.fixture.txt +43 -0
- package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/003-1-v476-canonical-authority-binding-integrity-method-lineage-alloca.trace.fixture.txt +42 -0
- package/src/tooling/portable/fixtures/legacy-artifacts/tooling/dogfood/027-handoff-package-workspace-archive-and-control-plane-minimality-audit.trace.fixture.txt +56 -0
- package/src/tooling/portable/fixtures/legacyArtifactFixtures.mjs +34 -0
- package/src/tooling/portable/grounding/grounding.capsule.case.mjs +65 -0
- package/src/tooling/portable/grounding/grounding.readiness.case.mjs +543 -0
- package/src/tooling/portable/grounding/grounding.semanticIntegration.case.mjs +131 -0
- package/src/tooling/portable/handoff/boundedWorkspaceRepresentation.case.mjs +103 -0
- package/src/tooling/portable/handoff/carrierLineage.fixedWidth.case.mjs +97 -0
- package/src/tooling/portable/handoff/coldStartQualification.case.mjs +293 -0
- package/src/tooling/portable/handoff/fixtures/027-invalid-audit-result.fixture.txt +192 -0
- package/src/tooling/portable/handoff/fixtures/027-invalid-return-handoff.fixture.txt +92 -0
- package/src/tooling/portable/handoff/fixtures/cold-start-qualification.v1.examples.json +60 -0
- package/src/tooling/portable/handoff/handoff.manufacture.case.mjs +293 -0
- package/src/tooling/portable/handoff/materialClosure.case.mjs +727 -0
- package/src/tooling/portable/handoff/multiRootManufacture.case.mjs +615 -0
- package/src/tooling/portable/handoff/operatorBridgeCore.case.mjs +205 -0
- package/src/tooling/portable/handoff/workspaceLandingPlan.case.mjs +143 -0
- package/src/tooling/portable/input/node.input.case.mjs +293 -0
- package/src/tooling/portable/lifecycle/lifecycle.readiness.case.mjs +179 -0
- package/src/tooling/portable/lineage/fixtures/lineage.integrity.repair-projection.v1.examples.json +605 -0
- package/src/tooling/portable/lineage/lineage.integrity.shared-capability.case.mjs +37 -0
- package/src/tooling/portable/lineage/publicationProviderReceipt.fixture.mjs +50 -0
- package/src/tooling/portable/package/fixtures/reference-relation-generation-authority.trace.md +84 -0
- package/src/tooling/portable/package/fixtures/tiinex.root.v1.package-authority.contract-fixture.md +64 -0
- package/src/tooling/portable/package/fixtures/tiinex.schema.generation.v1.generation-binding.contract-fixture.md +140 -0
- package/src/tooling/portable/package/fixtures/tiinex.schema.transition.companion.v1.contract-fixture.md +73 -0
- package/src/tooling/portable/package/fixtures/tiinex.semantic.package.v1.contract-fixture.md +147 -0
- package/src/tooling/portable/package/fixtures/tiinex.transition.definition.v1.package-contract-fixture.md +77 -0
- package/src/tooling/portable/providers/schema.providers.genericity.case.mjs +31 -0
- package/src/tooling/portable/reduction/reduction.preflight.case.mjs +298 -0
- package/src/tooling/portable/schema/fixtures/evidence-preservation-body.inheritance-record-fixture.md +65 -0
- package/src/tooling/portable/schema/fixtures/tiinex.portal.time.v1.contract-fixture.md +294 -0
- package/src/tooling/portable/schema/fixtures/tiinex.root.v1.contract-fixture.md +584 -0
- package/src/tooling/portable/schema/fixtures/tiinex.root.v1.machine-shape.contract-fixture.md +44 -0
- package/src/tooling/portable/schema/fixtures/tiinex.root.v1.ordinary-target.contract-fixture.md +630 -0
- package/src/tooling/portable/schema/fixtures/tiinex.schema.contract.v1.repeated-record.contract-fixture.md +69 -0
- package/src/tooling/portable/schema/fixtures/tiinex.schema.generation.v1.repeated-record.contract-fixture.md +98 -0
- package/src/tooling/portable/schema/fixtures/tiinex.schema.inheritance.v1.repeated-record.contract-fixture.md +58 -0
- package/src/tooling/portable/schema/fixtures/tiinex.task.v1.contract-fixture.md +165 -0
- package/src/tooling/portable/schema/fixtures/tiinex.transition.definition.v1.contract-fixture.md +744 -0
- package/src/tooling/portable/schema/fixtures/tiinex.transition.definition.v1.field-domain.contract-fixture.md +319 -0
- package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.relation.v1.schema.md +240 -0
- package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.schema.contract.v1.schema.md +391 -0
- package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.schema.generation.v1.schema.md +379 -0
- package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.schema.transition.companion.v1.schema.md +265 -0
- package/src/transitions/canonical-schema-cache/053d46ce082d4ec261b82abc44ecca403d61e240/tiinex.semantic.package.v1.schema.md +402 -0
- package/src/transitions/canonical-schema-cache/52ecdea0a75893882ce282214d155f70e1309c2a/tiinex.topic.v1.schema.md +197 -0
- package/src/transitions/canonical-schema-cache/d69b8ff55a56b8cb9282b8684db6a938a4435b94/tiinex.root.v1.schema.md +797 -0
- package/src/transitions/canonical-schema-cache/d69b8ff55a56b8cb9282b8684db6a938a4435b94/tiinex.transition.definition.v1.schema.md +1062 -0
- package/src/transitions/canonicalTransition.packageContracts.js +22 -0
- package/src/transitions/canonicalTransition.productDefaults.js +105 -0
- package/src/transitions/canonicalTransition.schemaCache.case.mjs +45 -0
- package/src/transitions/canonicalTransition.schemaCache.js +81 -0
- package/src/transitions/canonicalTransition.semanticPackage.js +146 -0
- package/src/transitions/record.transitions.case.mjs +88 -0
- package/src/transitions/transition.authorityRepresentation.js +55 -0
- package/src/transitions/transition.availabilityPlanner.js +376 -0
- package/src/transitions/transition.availabilitySemantics.js +150 -0
- package/src/transitions/transition.definitionReadProjection.js +107 -0
- package/src/transitions/transition.definitionRegistry.js +355 -0
- package/src/transitions/transition.definitionRegistryAggregation.js +21 -0
- package/src/transitions/transition.definitions.js +46 -0
- package/src/transitions/transition.explicitGenerationPlanner.js +58 -0
- package/src/transitions/transition.generationInputPlanner.js +19 -0
- package/src/transitions/transition.interpretationMaterializer.js +2 -0
- package/src/transitions/transition.invocationBindingPacket.js +52 -0
- package/src/transitions/transition.invocationBindingPlanner.js +467 -0
- package/src/transitions/transition.legacyShorthand.js +133 -0
- package/src/transitions/transition.localArtifactMaterializers.js +16 -0
- package/src/transitions/transition.localCreateCapability.js +111 -0
- package/src/transitions/transition.outputMaterializationPlanner.js +336 -0
- package/src/transitions/transition.parentReference.js +90 -0
- package/src/transitions/transition.presentation.js +43 -0
- package/src/transitions/transition.productPreparation.js +377 -0
- package/src/transitions/transition.productPresentation.browser.js +28 -0
- package/src/transitions/transition.productPresentation.js +55 -0
- package/src/transitions/transition.referenceCreateCapability.js +119 -0
- package/src/transitions/transition.referenceTarget.js +50 -0
- package/src/transitions/transition.relationMaterializer.js +2 -0
- package/src/transitions/transition.resultSemantics.js +453 -0
- package/src/transitions/transition.taskMaterializer.js +2 -0
- package/src/transitions/transition.topicMaterializer.js +2 -0
- package/src/transitions/transition.validate.case.mjs +58 -0
- package/src/ui/cards/ArtifactCard.js +1 -0
- package/src/ui/cards/SchemaCard.js +1 -0
- package/src/ui/cards/SourceCard.js +1 -0
- package/src/ui/dialog.presenter.js +24 -0
- package/src/ui/feedback/DegradedNotice.js +1 -0
- package/src/ui/feedback/EmptyState.js +1 -0
- package/src/ui/feedback/ValidationNotice.js +1 -0
- package/src/ui/forms/FormRenderer.js +1 -0
- package/src/ui/forms/fields/MarkdownField.js +1 -0
- package/src/ui/forms/fields/SelectField.js +1 -0
- package/src/ui/forms/fields/SourcePickerField.js +1 -0
- package/src/ui/forms/fields/TextField.js +1 -0
- package/src/ui/icon.paths.js +37 -0
- package/src/ui/layout/Panel.js +1 -0
- package/src/ui/layout/ResponsiveFrame.js +1 -0
- package/src/ui/layout/SplitView.js +1 -0
- package/src/ui/layout/Stack.js +1 -0
- package/src/ui/panels/DetailPanel.js +1 -0
- package/src/ui/panels/LineagePanel.js +1 -0
- package/src/ui/panels/SourcePanel.js +1 -0
- package/src/ui/primitives/Badge.js +1 -0
- package/src/ui/primitives/Badge.jsx +5 -0
- package/src/ui/primitives/Button.js +1 -0
- package/src/ui/primitives/Button.jsx +12 -0
- package/src/ui/primitives/Card.js +1 -0
- package/src/ui/primitives/Field.js +1 -0
- package/src/ui/primitives/Field.jsx +21 -0
- package/src/ui/primitives/Icon.jsx +90 -0
- package/src/ui/primitives/Modal.jsx +27 -0
- package/src/validation/i18n.js +37 -0
- package/src/validation/validateArtifact.case.mjs +41 -0
- package/src/verses/column/ColumnVerse.js +1 -0
- package/src/verses/column/column.model.js +6 -0
- package/src/verses/column/column.project.js +7 -0
- package/src/verses/context.js +26 -0
- package/src/verses/contracts.js +1 -0
- package/src/verses/hostRegistry.js +47 -0
- package/src/verses/registry.js +22 -0
- package/src/verses/universe.model.js +8 -0
- package/src/verses/universe.presenter.js +8 -0
- package/src/verses/universe.project.js +12 -0
- package/src/viewer.js +34 -0
- package/src/workspace.model.js +5 -0
- package/src/workspaces/workspace.actions.js +1 -0
- package/src/workspaces/workspace.artifactActions.js +56 -0
- package/src/workspaces/workspace.auditView.js +153 -0
- package/src/workspaces/workspace.candidates.js +149 -0
- package/src/workspaces/workspace.config.js +153 -0
- package/src/workspaces/workspace.configuredSource.js +68 -0
- package/src/workspaces/workspace.discoveryProgress.js +34 -0
- package/src/workspaces/workspace.discoveryView.js +386 -0
- package/src/workspaces/workspace.displayFilters.js +63 -0
- package/src/workspaces/workspace.displayOptions.js +58 -0
- package/src/workspaces/workspace.emptyStateCopy.js +24 -0
- package/src/workspaces/workspace.entrypointLifecycle.js +131 -0
- package/src/workspaces/workspace.entrypointViewIntent.js +83 -0
- package/src/workspaces/workspace.entrypoints.js +157 -0
- package/src/workspaces/workspace.feedSort.js +152 -0
- package/src/workspaces/workspace.import.js +212 -0
- package/src/workspaces/workspace.importConflicts.js +200 -0
- package/src/workspaces/workspace.importLifecycle.case.mjs +103 -0
- package/src/workspaces/workspace.lifecycle.case.mjs +353 -0
- package/src/workspaces/workspace.lifecycle.js +357 -0
- package/src/workspaces/workspace.lineageView.js +244 -0
- package/src/workspaces/workspace.localSourceLifecycle.js +91 -0
- package/src/workspaces/workspace.materialLedger.js +110 -0
- package/src/workspaces/workspace.materialReconciliation.case.mjs +164 -0
- package/src/workspaces/workspace.materialReconciliation.js +390 -0
- package/src/workspaces/workspace.memberIdentity.js +140 -0
- package/src/workspaces/workspace.model.js +2 -0
- package/src/workspaces/workspace.navigation.js +20 -0
- package/src/workspaces/workspace.openSemantics.js +33 -0
- package/src/workspaces/workspace.pathTree.js +132 -0
- package/src/workspaces/workspace.persistence.case.mjs +271 -0
- package/src/workspaces/workspace.persistence.js +469 -0
- package/src/workspaces/workspace.persistenceCache.js +41 -0
- package/src/workspaces/workspace.persistenceClear.js +45 -0
- package/src/workspaces/workspace.persistencePresentation.js +93 -0
- package/src/workspaces/workspace.persistenceRecovery.js +147 -0
- package/src/workspaces/workspace.persistenceRouteCache.js +82 -0
- package/src/workspaces/workspace.publicationReceipts.case.mjs +36 -0
- package/src/workspaces/workspace.publicationReceipts.js +56 -0
- package/src/workspaces/workspace.recoverabilityView.js +264 -0
- package/src/workspaces/workspace.route.js +432 -0
- package/src/workspaces/workspace.runtimeCanonical.js +18 -0
- package/src/workspaces/workspace.sourceMaterial.js +71 -0
- package/src/workspaces/workspace.sourceRecordPath.js +5 -0
- package/src/workspaces/workspace.sourceRecords.js +75 -0
- package/src/workspaces/workspace.store.js +3 -0
- package/src/workspaces/workspace.summary.js +116 -0
- package/src/workspaces/workspace.timePortal.js +137 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import { createRecordFromMarkdown } from '@tiinex/core/artifacts/artifact.record.js';
|
|
3
|
+
import { stateWithSourceMaterialCleared } from './workspace.sourceMaterial.js';
|
|
4
|
+
|
|
5
|
+
// Load the lifecycle to attach to globalThis
|
|
6
|
+
await import('../sources/source.identity.js');
|
|
7
|
+
await import('./workspace.lifecycle.js');
|
|
8
|
+
const lifecycle = globalThis.TiinexWorkspaceLifecycle;
|
|
9
|
+
|
|
10
|
+
function fail(msg) { throw new Error(msg); }
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
// 1) createRecordFromMarkdown now returns a record-shaped input only
|
|
14
|
+
// (identity and provenance are assigned by the lifecycle layer)
|
|
15
|
+
const md = '# Title\n\nSome body text';
|
|
16
|
+
const rec = createRecordFromMarkdown(md, { path: 'a.md', name: 'a.md', sourceMode: 'manual-file' });
|
|
17
|
+
assert(rec && rec.title, 'record shape missing title');
|
|
18
|
+
if ('id' in rec) fail('createRecordFromMarkdown must not add id');
|
|
19
|
+
if ('createdAt' in rec) fail('createRecordFromMarkdown must not add createdAt');
|
|
20
|
+
if ('source' in rec) fail('createRecordFromMarkdown must not add source');
|
|
21
|
+
const pathTitleRecord = createRecordFromMarkdown('Body without heading', { path: 'docs/architecture/source-provenance-grounding.md', sourceMode: 'archive-local' });
|
|
22
|
+
assert.equal(pathTitleRecord.title, 'Source Provenance Grounding', 'headingless Markdown should use readable path-derived title instead of Untitled artifact');
|
|
23
|
+
|
|
24
|
+
// 2) Normal addWorkspaceRecords keeps local/session provenance
|
|
25
|
+
const base = lifecycle.makeEmptyAppState();
|
|
26
|
+
const create = lifecycle.createWorkspace(base, { name: 'Test' });
|
|
27
|
+
if (!create?.ok) fail('createWorkspace failed');
|
|
28
|
+
const ws = create.workspace;
|
|
29
|
+
const renamed = lifecycle.renameWorkspace(create.state, ws.id, 'Renamed Test');
|
|
30
|
+
if (!renamed?.ok) fail('renameWorkspace failed');
|
|
31
|
+
if (renamed.workspace.id !== ws.id) fail('renameWorkspace must preserve stable workspace id');
|
|
32
|
+
if (renamed.workspace.title !== 'Renamed Test' || renamed.workspace.name !== 'Renamed Test') fail('renameWorkspace must update visible workspace title/name');
|
|
33
|
+
const blankRename = lifecycle.renameWorkspace(renamed.state, ws.id, ' ');
|
|
34
|
+
if (blankRename?.ok || blankRename?.error !== 'workspace.name.required') fail('renameWorkspace must reject empty names');
|
|
35
|
+
const addLocal = lifecycle.addWorkspaceRecords(create.state, ws.id, [rec]);
|
|
36
|
+
if (!addLocal?.ok) fail('addWorkspaceRecords failed');
|
|
37
|
+
const added = addLocal.records[0];
|
|
38
|
+
if (!added?.source || added.source.kind !== lifecycle.SESSION_SOURCE_KIND) fail('local record must have session source');
|
|
39
|
+
if (!lifecycle.activeWorkspace(addLocal.state).sources.find((source) => source.id === 'local')?.closeable) fail('Local source row must become closeable when it contains local/session material');
|
|
40
|
+
if (added.path !== 'a.md') fail('local record must preserve path');
|
|
41
|
+
if (!added.markdown || !added.markdown.includes('# Title')) fail('local record must preserve markdown for detail view');
|
|
42
|
+
|
|
43
|
+
// 2b) Same local path is an idempotent upsert, and same-title/different-path files remain distinct
|
|
44
|
+
const samePathAgain = createRecordFromMarkdown('# Title\n\nUpdated body', { path: 'a.md', name: 'a.md', sourceMode: 'manual-file' });
|
|
45
|
+
const addLocalAgain = lifecycle.addWorkspaceRecords(addLocal.state, ws.id, [samePathAgain]);
|
|
46
|
+
if (!addLocalAgain?.ok) fail('addWorkspaceRecords failed for repeated local path');
|
|
47
|
+
const afterLocalAgain = lifecycle.activeWorkspace(addLocalAgain.state);
|
|
48
|
+
const localARecords = afterLocalAgain.records.filter((item) => item.path === 'a.md');
|
|
49
|
+
if (localARecords.length !== 1) fail('repeated local path must upsert to one record');
|
|
50
|
+
if (!String(localARecords[0].markdown || '').includes('Updated body')) fail('repeated local path must update material');
|
|
51
|
+
const secondPath = createRecordFromMarkdown('# Title\n\nOther body', { path: 'folder/a.md', name: 'a.md', sourceMode: 'manual-folder' });
|
|
52
|
+
const addSecondPath = lifecycle.addWorkspaceRecords(addLocalAgain.state, ws.id, [secondPath]);
|
|
53
|
+
if (!addSecondPath?.ok) fail('addWorkspaceRecords failed for same title different path');
|
|
54
|
+
const afterSecondPath = lifecycle.activeWorkspace(addSecondPath.state);
|
|
55
|
+
if (!afterSecondPath.records.some((item) => item.path === 'a.md') || !afterSecondPath.records.some((item) => item.path === 'folder/a.md')) fail('same title with distinct paths must remain distinct records');
|
|
56
|
+
|
|
57
|
+
const draftAdd = lifecycle.addWorkspaceRecord(addSecondPath.state, ws.id, { title: 'Draft Task', summary: 'draft', path: '.topics/news/001-1-draft-task.trace.md', kind: 'tiinex.task.v1', status: 'local', sourceMode: 'local-transition', markdown: '# Draft Task' });
|
|
58
|
+
if (!draftAdd?.ok) fail('addWorkspaceRecord failed for transition draft');
|
|
59
|
+
const draftRecord = draftAdd.record;
|
|
60
|
+
const deleteDraft = lifecycle.removeWorkspaceRecord(draftAdd.state, ws.id, draftRecord.id);
|
|
61
|
+
if (!deleteDraft?.ok) fail('removeWorkspaceRecord must delete browser-local transition drafts');
|
|
62
|
+
if (lifecycle.activeWorkspace(deleteDraft.state).records.some((item) => item.id === draftRecord.id)) fail('removed local draft must leave workspace records');
|
|
63
|
+
const missingDeleteRefused = lifecycle.removeWorkspaceRecord(draftAdd.state, ws.id, 'missing-source-record');
|
|
64
|
+
if (missingDeleteRefused?.ok) fail('removeWorkspaceRecord must not succeed for unknown records');
|
|
65
|
+
|
|
66
|
+
// ensure adding records using 'local' as sourceId is rejected
|
|
67
|
+
const badLocal = lifecycle.addWorkspaceSourceRecords(addLocal.state, ws.id, 'local', [rec]);
|
|
68
|
+
if (badLocal?.ok || badLocal?.error !== 'source.not.configured') fail('addWorkspaceSourceRecords must reject local sourceId');
|
|
69
|
+
|
|
70
|
+
// 3) Add configured source and verify addWorkspaceSourceRecords behavior
|
|
71
|
+
const addSource = lifecycle.addWorkspaceSource(addSecondPath.state, ws.id, { label: 'Repo', repository: 'owner/repo', ref: 'master', rootPath: '.topics', count: 0, transportLabel: 'Source Pages mirror' });
|
|
72
|
+
if (!addSource?.ok) fail('addWorkspaceSource failed');
|
|
73
|
+
const sourceId = addSource.source.id;
|
|
74
|
+
if (addSource.source.discoveryState !== 'deferred') fail('configured source registration must start as deferred');
|
|
75
|
+
if (addSource.source.id !== 'github:owner-repo:master:topics') fail('configured source id must include repo/ref/root identity');
|
|
76
|
+
const otherRefSource = lifecycle.makeConfiguredSource({ repository: 'owner/repo', ref: 'develop', rootPath: '.topics' });
|
|
77
|
+
if (otherRefSource.id === addSource.source.id) fail('configured source identity must not collide across refs');
|
|
78
|
+
const otherRootSource = lifecycle.makeConfiguredSource({ repository: 'owner/repo', ref: 'master', rootPath: 'docs' });
|
|
79
|
+
if (otherRootSource.id === addSource.source.id) fail('configured source identity must not collide across roots');
|
|
80
|
+
const continuationSource = lifecycle.makeConfiguredSource({ label: 'Plan', repository: 'owner/repo', ref: 'master', rootPath: '.topics', repoDiscovery: true, issueDiscovery: true, issueUrls: 'https://github.com/owner/repo/issues/1', surfaces: { repoFiles: { requested: true, loaded: 7 }, issueSnapshots: { requested: true, deferred: true, loaded: 0 } }, governanceBoundary: { schema: 'tiinex.governance.boundary.v1', status: 'origin-fallback', policy: { kind: 'LICENSE' } } });
|
|
81
|
+
if (!continuationSource.repoDiscovery || !continuationSource.issueDiscovery) fail('configured source must preserve requested source surfaces for continuation');
|
|
82
|
+
if (!continuationSource.surfaces.issueSnapshots?.deferred) fail('configured source must preserve deferred surface state');
|
|
83
|
+
if (continuationSource.governanceBoundary?.status !== 'origin-fallback') fail('configured source must preserve governance boundary metadata');
|
|
84
|
+
const invalidStateSource = lifecycle.makeConfiguredSource({ label: 'Bad State', repository: 'owner/repo', discoveryState: 'resolved' });
|
|
85
|
+
if (invalidStateSource.discoveryState !== 'deferred') fail('unknown source discovery state must normalize to deferred');
|
|
86
|
+
if (lifecycle.normalizeSourceDiscoveryState('partial') !== 'partial') fail('known source discovery state must be preserved');
|
|
87
|
+
if (lifecycle.normalizeSourceDiscoveryState('resolved') !== 'deferred') fail('resolved must not become a hidden source discovery state');
|
|
88
|
+
|
|
89
|
+
const srcRec = createRecordFromMarkdown('# S\n\nbody', { path: '.topics/1.md', name: '1.md', sourceMode: 'source' });
|
|
90
|
+
const addSrcRes = lifecycle.addWorkspaceSourceRecords(addSource.state, ws.id, sourceId, [srcRec]);
|
|
91
|
+
if (!addSrcRes?.ok) fail('addWorkspaceSourceRecords failed');
|
|
92
|
+
const inserted = addSrcRes.records[0];
|
|
93
|
+
if (!inserted?.source || inserted.source.id !== sourceId) fail('inserted record must have explicit source provenance');
|
|
94
|
+
if (!inserted?.id || !String(inserted.id).startsWith('source:')) fail('source-backed record must have deterministic source id');
|
|
95
|
+
if (String(inserted.path || '') !== '.topics/1.md') fail('source-backed record path must be canonicalized to include rootPath');
|
|
96
|
+
const sourceDelete = lifecycle.removeWorkspaceRecord(addSrcRes.state, ws.id, inserted.id);
|
|
97
|
+
if (sourceDelete?.ok || sourceDelete?.error !== 'record.remove.refused') fail('removeWorkspaceRecord must refuse source-backed material');
|
|
98
|
+
const foundSource = addSrcRes.workspace.sources.find((s) => s.id === sourceId);
|
|
99
|
+
if (!foundSource) fail('configured source not present after insert');
|
|
100
|
+
if (!(Number(foundSource.count) > 0)) fail('configured source count not updated');
|
|
101
|
+
if (foundSource.discoveryState !== 'loaded') fail('configured source must become loaded after source records are inserted');
|
|
102
|
+
if (addSrcRes.workspace.discoveryProgress) fail('discoveryProgress must remain untouched/null by insertion');
|
|
103
|
+
|
|
104
|
+
const preserveViewState = JSON.parse(JSON.stringify(addSrcRes.state));
|
|
105
|
+
preserveViewState.view = Object.assign({}, preserveViewState.view || {}, { workspaceVerse: 'lineage', selectedRecordId: inserted.id });
|
|
106
|
+
const preserveViewInsert = lifecycle.addWorkspaceSourceRecords(preserveViewState, ws.id, sourceId, [createRecordFromMarkdown('# Preserve\n\nbody', { path: '.topics/preserve.md', name: 'preserve.md', sourceMode: 'source' })], { discoveryState: 'partial', preserveView: true });
|
|
107
|
+
if (!preserveViewInsert?.ok) fail('addWorkspaceSourceRecords preserveView insert failed');
|
|
108
|
+
if (preserveViewInsert.state.view.workspaceVerse !== 'lineage') fail('source parent recovery inserts must preserve active workspace verse');
|
|
109
|
+
if (preserveViewInsert.state.view.selectedRecordId !== inserted.id) fail('source parent recovery inserts must preserve selected record');
|
|
110
|
+
|
|
111
|
+
const stateWithSourceMaterial = JSON.parse(JSON.stringify(addSrcRes.state));
|
|
112
|
+
stateWithSourceMaterial.view = Object.assign({}, stateWithSourceMaterial.view || {}, { selectedRecordId: inserted.id, lineageLoadReport: { selectedRecordId: inserted.id }, lineageAuditReport: { selectedRecordId: inserted.id } });
|
|
113
|
+
const materialWorkspace = stateWithSourceMaterial.workspaces.find((item) => item.id === ws.id);
|
|
114
|
+
materialWorkspace.assets = [
|
|
115
|
+
{ id: 'source-asset', path: 'source.png', source: { id: sourceId } },
|
|
116
|
+
{ id: 'local-asset', path: 'local.png', source: { id: 'local' } }
|
|
117
|
+
];
|
|
118
|
+
materialWorkspace.records.push(
|
|
119
|
+
{ id: 'source-workspace-artifact', title: 'Source workspace', path: 'source.workspace.md', kind: 'tiinex.workspace.v1', schemaId: 'tiinex.workspace.v1', sourceMode: 'source-backed-workspace-file', source: { id: sourceId, adapterId: 'github', kind: 'github-tree' }, workspaceArtifactRole: { schema: 'tiinex.workspace.artifact.role.v1', openEligible: true, mergeEligible: true } },
|
|
120
|
+
{ id: 'local-workspace-artifact', title: 'Local workspace', path: 'local.workspace.md', kind: 'tiinex.workspace.v1', schemaId: 'tiinex.workspace.v1', sourceMode: 'local-workspace-file', source: { id: 'local', adapterId: 'local', kind: 'local-session' }, workspaceArtifactRole: { schema: 'tiinex.workspace.artifact.role.v1', openEligible: true, mergeEligible: true } }
|
|
121
|
+
);
|
|
122
|
+
materialWorkspace.discoveryProgress = { sourceId, step: 'materializing' };
|
|
123
|
+
const closeSourceRes = lifecycle.closeWorkspaceSource(stateWithSourceMaterial, ws.id, sourceId);
|
|
124
|
+
if (!closeSourceRes?.ok) fail('closeWorkspaceSource failed');
|
|
125
|
+
const closedWorkspace = lifecycle.activeWorkspace(closeSourceRes.state);
|
|
126
|
+
if (closedWorkspace.sources.some((s) => s.id === sourceId)) fail('closed source must be removed from workspace sources');
|
|
127
|
+
if (closedWorkspace.records.some((r) => r.source && r.source.id === sourceId)) fail('closed source must remove source-backed records from the workspace');
|
|
128
|
+
if (!closedWorkspace.records.some((r) => r.source && (r.source.id === 'local' || r.source.kind === lifecycle.SESSION_SOURCE_KIND))) fail('closeWorkspaceSource must preserve local/session records');
|
|
129
|
+
if (closedWorkspace.assets.some((asset) => asset.source?.id === sourceId)) fail('closed source must remove source-backed assets');
|
|
130
|
+
if (!closedWorkspace.assets.some((asset) => asset.source?.id === 'local')) fail('closeWorkspaceSource must preserve local assets');
|
|
131
|
+
if (closedWorkspace.records.some((record) => record.id === 'source-workspace-artifact')) fail('closed source must remove source-backed workspace artifact records');
|
|
132
|
+
if (!closedWorkspace.records.some((record) => record.id === 'local-workspace-artifact')) fail('closeWorkspaceSource must preserve local workspace artifact records');
|
|
133
|
+
if (closedWorkspace.discoveryProgress) fail('closed source must clear in-flight discovery progress');
|
|
134
|
+
if (closeSourceRes.state.view.selectedRecordId) fail('closeWorkspaceSource must clear a dangling selected source record');
|
|
135
|
+
|
|
136
|
+
const localBeforeClose = closedWorkspace.records.find((record) => record.source?.kind === lifecycle.SESSION_SOURCE_KIND || record.source?.id === 'local');
|
|
137
|
+
if (!localBeforeClose) fail('local close fixture must retain local material before clearing local source');
|
|
138
|
+
const closeLocalState = JSON.parse(JSON.stringify(closeSourceRes.state));
|
|
139
|
+
closeLocalState.view = Object.assign({}, closeLocalState.view || {}, { workspaceVerse: 'lineage', selectedRecordId: localBeforeClose.id });
|
|
140
|
+
const closeLocalRes = lifecycle.closeWorkspaceSource(closeLocalState, ws.id, 'local');
|
|
141
|
+
if (!closeLocalRes?.ok || !closeLocalRes.localSessionCleared) fail('closeWorkspaceSource must clear local/session source material when local is requested');
|
|
142
|
+
const localClearedWorkspace = lifecycle.activeWorkspace(closeLocalRes.state);
|
|
143
|
+
if (!localClearedWorkspace.sources.some((source) => source.id === 'local')) fail('clearing local source material must keep the Local source row available');
|
|
144
|
+
if (localClearedWorkspace.sources.find((source) => source.id === 'local')?.closeable) fail('empty Local source row should not remain closeable');
|
|
145
|
+
if (localClearedWorkspace.records.some((record) => record.source?.id === 'local' || record.source?.kind === lifecycle.SESSION_SOURCE_KIND)) fail('clearing local source material must remove local/session records');
|
|
146
|
+
if (localClearedWorkspace.assets.some((asset) => asset.source?.id === 'local' || asset.source?.kind === lifecycle.SESSION_SOURCE_KIND)) fail('clearing local source material must remove local/session assets');
|
|
147
|
+
if (localClearedWorkspace.records.some((record) => record.id === 'local-workspace-artifact')) fail('clearing local source material must remove local/session workspace artifact records');
|
|
148
|
+
if (Number(localClearedWorkspace.sources.find((source) => source.id === 'local')?.count || 0) !== 0) fail('empty Local source count must be zero after clearing all local material');
|
|
149
|
+
if (closeLocalRes.state.view.selectedRecordId) fail('clearing local source material must clear selected local records');
|
|
150
|
+
|
|
151
|
+
const sourceLessWorkspaceArtifactState = JSON.parse(JSON.stringify(closedWorkspace));
|
|
152
|
+
sourceLessWorkspaceArtifactState.records = [{ id: 'local-archive-workspace', title: 'Archive workspace', path: 'archive.workspace.md', kind: 'tiinex.workspace.v1', schemaId: 'tiinex.workspace.v1', sourceMode: 'package-import-workspace-file', workspaceArtifactRole: { schema: 'tiinex.workspace.artifact.role.v1', openEligible: true, mergeEligible: true } }];
|
|
153
|
+
sourceLessWorkspaceArtifactState.assets = [];
|
|
154
|
+
sourceLessWorkspaceArtifactState.sources = [lifecycle.makeLocalSource()];
|
|
155
|
+
const sourceLessAppState = Object.assign(lifecycle.makeEmptyAppState(), { activeWorkspaceId: sourceLessWorkspaceArtifactState.id, workspaces: [sourceLessWorkspaceArtifactState], view: { workspaceVerse: 'feed' } });
|
|
156
|
+
const closeSourceLessWorkspaceArtifact = lifecycle.closeWorkspaceSource(sourceLessAppState, sourceLessWorkspaceArtifactState.id, 'local');
|
|
157
|
+
if (!closeSourceLessWorkspaceArtifact?.ok) fail('clearing Local with source-less workspace artifact must succeed');
|
|
158
|
+
if (closeSourceLessWorkspaceArtifact.counts?.records !== 1) fail('clearing Local must treat source-less imported workspace artifact as local/session record material');
|
|
159
|
+
const sourceLessClearedWorkspace = lifecycle.activeWorkspace(closeSourceLessWorkspaceArtifact.state);
|
|
160
|
+
if (sourceLessClearedWorkspace.records.length !== 0) fail('clearing Local must remove source-less imported workspace artifact records');
|
|
161
|
+
if (sourceLessClearedWorkspace.sources.find((source) => source.id === 'local')?.closeable) fail('Local row should not be closeable after source-less workspace artifacts are cleared');
|
|
162
|
+
|
|
163
|
+
const clearSourceState = JSON.parse(JSON.stringify(addSrcRes.state));
|
|
164
|
+
clearSourceState.view = Object.assign({}, clearSourceState.view || {}, { workspaceVerse: 'lineage', selectedRecordId: inserted.id });
|
|
165
|
+
const clearWorkspace = clearSourceState.workspaces.find((item) => item.id === ws.id);
|
|
166
|
+
clearWorkspace.assets = [{ id: 'source-asset-2', path: 'source-2.png', source: { id: sourceId } }, { id: 'local-asset-2', path: 'local-2.png', source: { id: 'local' } }];
|
|
167
|
+
const clearMaterialRes = stateWithSourceMaterialCleared(clearSourceState, ws.id, sourceId, { discoveryState: 'deferred' });
|
|
168
|
+
if (!clearMaterialRes?.ok) fail('clearWorkspaceSourceMaterial failed');
|
|
169
|
+
const clearedMaterialWorkspace = lifecycle.activeWorkspace(clearMaterialRes.state);
|
|
170
|
+
if (!clearedMaterialWorkspace.sources.some((s) => s.id === sourceId)) fail('clearing material must keep the configured source boundary pinned');
|
|
171
|
+
if (clearedMaterialWorkspace.records.some((r) => r.source?.id === sourceId)) fail('clearing material must remove source-backed records');
|
|
172
|
+
if (clearedMaterialWorkspace.assets.some((asset) => asset.source?.id === sourceId)) fail('clearing material must remove source-backed assets');
|
|
173
|
+
if (!clearedMaterialWorkspace.assets.some((asset) => asset.source?.id === 'local')) fail('clearing material must preserve local assets');
|
|
174
|
+
if (clearMaterialRes.state.view.workspaceVerse !== 'lineage') fail('clearing material during transport refresh must not reset the workspace verse');
|
|
175
|
+
if (clearMaterialRes.state.view.selectedRecordId) fail('clearing material must clear a dangling selected source record');
|
|
176
|
+
if (Number(clearedMaterialWorkspace.sources.find((s) => s.id === sourceId)?.count ?? -1) !== 0) fail('cleared source boundary count must reset to zero');
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
const surfaceClearState = JSON.parse(JSON.stringify(addSource.state));
|
|
180
|
+
const repoSurfaceRec = Object.assign(createRecordFromMarkdown('# Repo file\n\nbody', { path: '.topics/repo.md', name: 'repo.md', sourceMode: 'source' }), { sourceTarget: { surface: 'repoFiles', transportTier: 'mirror' } });
|
|
181
|
+
const issueSurfaceRec = Object.assign(createRecordFromMarkdown('# Issue\n\nbody', { path: '.topics/.github issue sidecars/1.md', name: '1.md', sourceMode: 'source' }), { sourceTarget: { surface: 'issueSnapshots', transportTier: 'proxy' } });
|
|
182
|
+
let surfaceState = lifecycle.addWorkspaceSourceRecords(surfaceClearState, ws.id, sourceId, [repoSurfaceRec, issueSurfaceRec]).state;
|
|
183
|
+
const surfaceClearRes = stateWithSourceMaterialCleared(surfaceState, ws.id, sourceId, { discoveryState: 'loading', surfaces: ['issueSnapshots'] });
|
|
184
|
+
if (!surfaceClearRes?.ok) fail('surface-scoped clear failed');
|
|
185
|
+
const surfaceClearedWorkspace = lifecycle.activeWorkspace(surfaceClearRes.state);
|
|
186
|
+
if (!surfaceClearedWorkspace.records.some((r) => r.source?.id === sourceId && r.sourceTarget?.surface === 'repoFiles')) fail('surface-scoped clear must preserve other surface records');
|
|
187
|
+
if (surfaceClearedWorkspace.records.some((r) => r.source?.id === sourceId && r.sourceTarget?.surface === 'issueSnapshots')) fail('surface-scoped clear must remove selected surface records');
|
|
188
|
+
if (Number(surfaceClearedWorkspace.sources.find((s) => s.id === sourceId)?.count ?? -1) !== 1) fail('surface-scoped clear must keep source count for preserved records');
|
|
189
|
+
|
|
190
|
+
// 4) Unknown sourceId should fail
|
|
191
|
+
const bad = lifecycle.addWorkspaceSourceRecords(addSrcRes.state, ws.id, 'nope', [srcRec]);
|
|
192
|
+
if (bad?.ok) fail('addWorkspaceSourceRecords must fail for unknown source');
|
|
193
|
+
|
|
194
|
+
// 5) Path variant case: different logical path forms should dedupe to one record
|
|
195
|
+
const variants = [
|
|
196
|
+
createRecordFromMarkdown('# V\n\nbody', { path: '.topics/README.md', name: 'README.md', sourceMode: 'source' }),
|
|
197
|
+
createRecordFromMarkdown('# V\n\nbody', { path: 'README.md', name: 'README.md', sourceMode: 'source' }),
|
|
198
|
+
createRecordFromMarkdown('# V\n\nbody', { path: './README.md', name: 'README.md', sourceMode: 'source' }),
|
|
199
|
+
createRecordFromMarkdown('# V\n\nbody', { path: 'https://raw.githubusercontent.com/owner/repo/master/README.md', name: 'README.md', sourceMode: 'source' })
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
// Capture prev configured-source count, then insert variants sequentially
|
|
203
|
+
const prevCount = Number(addSrcRes.workspace.sources.find((s) => s.id === sourceId)?.count || 0);
|
|
204
|
+
let currentState = addSrcRes.state;
|
|
205
|
+
for (const v of variants) {
|
|
206
|
+
const res = lifecycle.addWorkspaceSourceRecords(currentState, ws.id, sourceId, [v]);
|
|
207
|
+
if (!res?.ok) fail('addWorkspaceSourceRecords failed for variant insert');
|
|
208
|
+
currentState = res.state;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Final assertions against the workspace state after sequential inserts
|
|
212
|
+
const finalWorkspace = lifecycle.activeWorkspace(currentState);
|
|
213
|
+
const cfg = finalWorkspace.sources.find((s) => s.id === sourceId);
|
|
214
|
+
if (!cfg) fail('configured source missing after variants');
|
|
215
|
+
if (Number(cfg.count) !== prevCount + 1) fail('expected source count to increase by exactly 1 for README variants');
|
|
216
|
+
if (cfg.discoveryState !== 'loaded') fail('source with loaded material must remain loaded after upserts');
|
|
217
|
+
if (lifecycle.countLocalRecords(finalWorkspace) !== 2) fail('local source count must include only local records and not source-backed records');
|
|
218
|
+
const found = finalWorkspace.records.filter((r) => r.source && r.source.id === sourceId && r.path === '.topics/README.md');
|
|
219
|
+
if (found.length !== 1) fail('workspace must contain a single canonical source-backed record for the logical README');
|
|
220
|
+
const single = found[0];
|
|
221
|
+
if (!single.id || !single.id.startsWith('source:')) fail('canonical record must have source id');
|
|
222
|
+
if (single.id !== `source:${sourceId}:.topics/README.md`) fail('canonical README id mismatch');
|
|
223
|
+
if (finalWorkspace.discoveryProgress) fail('discoveryProgress must remain untouched/null by insertion');
|
|
224
|
+
|
|
225
|
+
const lineageVerseState = lifecycle.setWorkspaceVerse(currentState, 'lineage');
|
|
226
|
+
if (lineageVerseState.view.workspaceVerse !== 'lineage') fail('lineage verse must be a first-class workspace verse');
|
|
227
|
+
const auditVerseState = lifecycle.setWorkspaceVerse(currentState, 'audit');
|
|
228
|
+
if (auditVerseState.view.workspaceVerse !== 'audit') fail('audit verse must be a first-class loaded-only workspace verse');
|
|
229
|
+
const invalidVerseState = lifecycle.setWorkspaceVerse(currentState, 'map');
|
|
230
|
+
if (invalidVerseState.view.workspaceVerse !== 'feed') fail('unknown workspace verse should fall back to feed');
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
// 6) Asset insertion is separate from leaf records and keeps local/session boundary
|
|
234
|
+
const assetRes = lifecycle.addWorkspaceAssets(currentState, ws.id, [{ path: 'assets/picture.png', name: 'picture.png', type: 'image/png', size: 7, dataUrl: 'data:image/png;base64,ZmFrZQ==' }]);
|
|
235
|
+
if (!assetRes?.ok) fail('addWorkspaceAssets failed');
|
|
236
|
+
const assetWorkspace = lifecycle.activeWorkspace(assetRes.state);
|
|
237
|
+
if (!Array.isArray(assetWorkspace.assets) || assetWorkspace.assets.length !== 1) fail('workspace asset must be stored separately from records');
|
|
238
|
+
if (assetWorkspace.records.some((record) => record.path === 'assets/picture.png')) fail('asset must not become a fake leaf record');
|
|
239
|
+
const assetAgain = lifecycle.addWorkspaceAssets(assetRes.state, ws.id, [{ path: './assets//picture.png', name: 'picture.png', type: 'image/png', size: 8 }]);
|
|
240
|
+
if (!assetAgain?.ok) fail('addWorkspaceAssets repeated path failed');
|
|
241
|
+
const assetAgainWorkspace = lifecycle.activeWorkspace(assetAgain.state);
|
|
242
|
+
if (assetAgainWorkspace.assets.length !== 1 || Number(assetAgainWorkspace.assets[0].size) !== 8) fail('asset path must upsert deterministically');
|
|
243
|
+
if (Number(assetAgainWorkspace.sources.find((source) => source.id === 'local')?.count || 0) < lifecycle.countLocalRecords(assetAgainWorkspace) + 1) fail('Local source count should include local assets as local/session material');
|
|
244
|
+
|
|
245
|
+
// 7) .workspace.md opens as a workspace object, not as a leaf
|
|
246
|
+
const workspaceMd = '# Tiinex Viewer\n\n## Workspace Entrypoints\n';
|
|
247
|
+
const openWs = lifecycle.openWorkspaceFromMarkdown(lifecycle.makeEmptyAppState(), workspaceMd, { path: 'viewer.workspace.md', title: 'Imported Viewer' });
|
|
248
|
+
if (!openWs?.ok) fail('openWorkspaceFromMarkdown failed');
|
|
249
|
+
if (openWs.workspace.records.length !== 0) fail('.workspace.md must not become a normal record');
|
|
250
|
+
if (openWs.workspace.workspaceImport?.path !== 'viewer.workspace.md') fail('workspace import path missing');
|
|
251
|
+
const merge = lifecycle.mergeWorkspaceArtifactContext(openWs.state, openWs.workspace.id, { path: 'other.workspace.md', title: 'Other' });
|
|
252
|
+
if (!merge?.ok) fail('mergeWorkspaceArtifactContext failed');
|
|
253
|
+
const mergedWorkspace = lifecycle.activeWorkspace(merge.state);
|
|
254
|
+
if (Object.prototype.hasOwnProperty.call(mergedWorkspace, 'workspaceMergeCandidates')) fail('workspace artifact merge must not create a legacy candidate runtime shape');
|
|
255
|
+
if (mergedWorkspace.workspaceMergedEntries?.length !== 1) fail('workspace artifact merge should record one metadata/context entry');
|
|
256
|
+
const mergeAgain = lifecycle.mergeWorkspaceArtifactContext(merge.state, openWs.workspace.id, { path: './other.workspace.md', title: 'Other updated' });
|
|
257
|
+
if (!mergeAgain?.ok) fail('mergeWorkspaceArtifactContext repeat failed');
|
|
258
|
+
const mergedAgainWorkspace = lifecycle.activeWorkspace(mergeAgain.state);
|
|
259
|
+
if (Object.prototype.hasOwnProperty.call(mergedAgainWorkspace, 'workspaceMergeCandidates')) fail('repeat merge must stay on canonical artifact/context model without legacy candidate shape');
|
|
260
|
+
if (mergedAgainWorkspace.workspaceMergedEntries.length !== 1) fail('workspace artifact merge path must upsert, not duplicate');
|
|
261
|
+
if (mergedAgainWorkspace.workspaceMergedEntries[0].title !== 'Other updated') fail('workspace artifact merge upsert should refresh metadata');
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
// 8) Issue snapshot source identity must preserve material paths instead of collapsing every issue/comment to the issue URL.
|
|
265
|
+
{
|
|
266
|
+
let issueState = lifecycle.makeEmptyAppState();
|
|
267
|
+
const issueCreated = lifecycle.createWorkspace(issueState, { name: 'Issue path guard' }, { clock: () => '2026-07-24T00:00:00.000Z' });
|
|
268
|
+
issueState = issueCreated.state;
|
|
269
|
+
const issueSource = lifecycle.addWorkspaceSource(issueState, issueCreated.workspace.id, { repository: 'Tiinex/docs', ref: 'main', rootPath: '.topics', label: 'Tiinex/docs' });
|
|
270
|
+
issueState = issueSource.state;
|
|
271
|
+
const issueLoaded = lifecycle.addWorkspaceSourceRecords(issueState, issueCreated.workspace.id, issueSource.source.id, [{
|
|
272
|
+
title: 'Issue snapshot',
|
|
273
|
+
path: 'https://github.com/Tiinex/docs/issues/123',
|
|
274
|
+
kind: 'tiinex.evidence.v1',
|
|
275
|
+
sourceMode: 'github-issue-snapshot',
|
|
276
|
+
sourceTarget: { surface: 'issueSnapshots', targetKind: 'github-issue-snapshot', inputTarget: 'https://github.com/Tiinex/docs/issues/123' },
|
|
277
|
+
markdown: `# Continuity Context
|
|
278
|
+
|
|
279
|
+
# Evidence
|
|
280
|
+
`
|
|
281
|
+
}, {
|
|
282
|
+
title: 'Comment artifact one',
|
|
283
|
+
path: '.topics/.github/.issues/tiinex-docs-issue-123/comment-001-5001-recovered-one.trace.md',
|
|
284
|
+
kind: 'tiinex.topic.v1',
|
|
285
|
+
sourceMode: 'github-comment-embedded-artifact',
|
|
286
|
+
sourceTarget: { surface: 'issueSnapshots', targetKind: 'github-comment-embedded-artifact', inputTarget: 'https://github.com/Tiinex/docs/issues/123#issuecomment-5001' },
|
|
287
|
+
snapshot: { embedded: true, sourceArtifactPath: '' },
|
|
288
|
+
markdown: `# Continuity Context
|
|
289
|
+
|
|
290
|
+
# One
|
|
291
|
+
`
|
|
292
|
+
}, {
|
|
293
|
+
title: 'Comment artifact two',
|
|
294
|
+
path: '.topics/.github/.issues/tiinex-docs-issue-123/comment-002-5002-recovered-two.trace.md',
|
|
295
|
+
kind: 'tiinex.topic.v1',
|
|
296
|
+
sourceMode: 'github-comment-embedded-artifact',
|
|
297
|
+
sourceTarget: { surface: 'issueSnapshots', targetKind: 'github-comment-embedded-artifact', inputTarget: 'https://github.com/Tiinex/docs/issues/123#issuecomment-5002' },
|
|
298
|
+
snapshot: { embedded: true, sourceArtifactPath: '' },
|
|
299
|
+
markdown: `# Continuity Context
|
|
300
|
+
|
|
301
|
+
# Two
|
|
302
|
+
`
|
|
303
|
+
}]);
|
|
304
|
+
assert.equal(issueLoaded.ok, true, 'issue snapshot source records should insert');
|
|
305
|
+
assert.equal(issueLoaded.records[0].path, '.topics/.github/tiinex/docs/.issues/123/000-issue-snapshot.trace.md', 'plain issue snapshot path should use logical .topics/.github/<owner>/<repo>/.issues scope, not a GitHub URL pseudo-tree');
|
|
306
|
+
assert(!issueLoaded.records[0].id.includes('.topics/tiinex/docs/issues'), 'plain issue snapshot deterministic id must not inherit repo rootPath');
|
|
307
|
+
const issueRecords = issueLoaded.workspace.records.filter((record) => record.source?.id === issueSource.source.id);
|
|
308
|
+
assert.equal(issueRecords.length, 3, 'comment-embedded issue artifacts must survive addWorkspaceSourceRecords as distinct records');
|
|
309
|
+
assert(issueRecords.some((record) => record.path === '.topics/.github/tiinex/docs/.issues/123/001-one.trace.md'), 'first comment embedded artifact path should normalize to logical issue scope');
|
|
310
|
+
assert(issueRecords.some((record) => record.path === '.topics/.github/tiinex/docs/.issues/123/002-two.trace.md'), 'second comment embedded artifact path should normalize to logical issue scope');
|
|
311
|
+
const outsideRoot = lifecycle.addWorkspaceSourceRecords(issueLoaded.state, issueCreated.workspace.id, issueSource.source.id, [{
|
|
312
|
+
title: 'Outside root embedded artifact',
|
|
313
|
+
path: '.topics/.github/.issues/tiinex-docs-issue-123/comment-003-5003-recovered-outside.trace.md',
|
|
314
|
+
kind: 'tiinex.topic.v1',
|
|
315
|
+
sourceMode: 'github-comment-embedded-artifact',
|
|
316
|
+
sourceTarget: { surface: 'issueSnapshots', targetKind: 'github-comment-embedded-artifact', inputTarget: 'https://github.com/Tiinex/docs/issues/123#issuecomment-5003', sourceArtifactPath: 'odysseus/001-1-1.trace.md' },
|
|
317
|
+
snapshot: { embedded: true, sourceArtifactPath: 'odysseus/001-1-1.trace.md' },
|
|
318
|
+
markdown: `# Continuity Context
|
|
319
|
+
|
|
320
|
+
# Outside
|
|
321
|
+
`
|
|
322
|
+
}]);
|
|
323
|
+
assert.equal(outsideRoot.records[0].path, 'odysseus/001-1-1.trace.md', 'embedded artifact Source Path outside discovery root must not be rewritten under rootPath');
|
|
324
|
+
const workspacePayload = lifecycle.addWorkspaceSourceRecords(outsideRoot.state, issueCreated.workspace.id, issueSource.source.id, [{
|
|
325
|
+
title: 'FS25 Markaryd',
|
|
326
|
+
path: '.topics/.github/tiinex/docs/.issues/123/000-fs25-markaryd.workspace.md',
|
|
327
|
+
kind: 'tiinex.workspace.v1',
|
|
328
|
+
schemaId: 'tiinex.workspace.v1',
|
|
329
|
+
sourceMode: 'github-issue-embedded-artifact',
|
|
330
|
+
sourceTarget: { surface: 'issueSnapshots', targetKind: 'github-issue-embedded-artifact', inputTarget: 'https://github.com/Tiinex/docs/issues/123', sourceArtifactPath: '.topics/.github/tiinex/docs/.issues/123/000-fs25-markaryd.workspace.md' },
|
|
331
|
+
markdown: `# Continuity Context
|
|
332
|
+
|
|
333
|
+
- Current
|
|
334
|
+
- Current Schema: [tiinex.workspace.v1](tiinex.workspace.v1.schema.md)
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
# FS25 Markaryd
|
|
339
|
+
`
|
|
340
|
+
}]);
|
|
341
|
+
assert.equal(workspacePayload.ok, true, 'source-backed workspace payload should insert as a record');
|
|
342
|
+
assert.equal(workspacePayload.workspace.records.filter((record) => record.kind === 'tiinex.workspace.v1').length, 1, 'source-backed workspace payload must remain a workspace record for lineage/source material');
|
|
343
|
+
assert.equal(Object.prototype.hasOwnProperty.call(workspacePayload.workspace, 'workspaceMergeCandidates'), false, 'source-backed workspace artifacts remain canonical records; no legacy candidate runtime shape is created');
|
|
344
|
+
assert.equal(workspacePayload.receipt.rawAdapterRecords, 1, 'source insertion receipt should preserve raw adapter count');
|
|
345
|
+
assert.equal(workspacePayload.receipt.sourceRecords, 5, 'source insertion receipt should reflect all source-backed records after insertion');
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
console.log('✓ workspace.lifecycle tests passed');
|
|
349
|
+
process.exit(0);
|
|
350
|
+
} catch (err) {
|
|
351
|
+
console.error('workspace.lifecycle tests failed:', err && err.stack ? err.stack : err);
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|