@software-dlc/cli 0.157.2
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/CHANGELOG.md +11 -0
- package/LICENSE +105 -0
- package/README.md +31 -0
- package/dist/checkout.d.ts +43 -0
- package/dist/checkout.d.ts.map +1 -0
- package/dist/checkout.js +92 -0
- package/dist/checkout.js.map +1 -0
- package/dist/cli-arguments.d.ts +13 -0
- package/dist/cli-arguments.d.ts.map +1 -0
- package/dist/cli-arguments.js +67 -0
- package/dist/cli-arguments.js.map +1 -0
- package/dist/cli-branch-history.d.ts +48 -0
- package/dist/cli-branch-history.d.ts.map +1 -0
- package/dist/cli-branch-history.js +319 -0
- package/dist/cli-branch-history.js.map +1 -0
- package/dist/cli-branches.d.ts +22 -0
- package/dist/cli-branches.d.ts.map +1 -0
- package/dist/cli-branches.js +59 -0
- package/dist/cli-branches.js.map +1 -0
- package/dist/cli-deploy.d.ts +14 -0
- package/dist/cli-deploy.d.ts.map +1 -0
- package/dist/cli-deploy.js +164 -0
- package/dist/cli-deploy.js.map +1 -0
- package/dist/cli-health.d.ts +3 -0
- package/dist/cli-health.d.ts.map +1 -0
- package/dist/cli-health.js +73 -0
- package/dist/cli-health.js.map +1 -0
- package/dist/cli-help.d.ts +21 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +176 -0
- package/dist/cli-help.js.map +1 -0
- package/dist/cli-login.d.ts +76 -0
- package/dist/cli-login.d.ts.map +1 -0
- package/dist/cli-login.js +634 -0
- package/dist/cli-login.js.map +1 -0
- package/dist/cli-operation.d.ts +2 -0
- package/dist/cli-operation.d.ts.map +1 -0
- package/dist/cli-operation.js +66 -0
- package/dist/cli-operation.js.map +1 -0
- package/dist/cli-org.d.ts +12 -0
- package/dist/cli-org.d.ts.map +1 -0
- package/dist/cli-org.js +218 -0
- package/dist/cli-org.js.map +1 -0
- package/dist/cli-rebuild.d.ts +20 -0
- package/dist/cli-rebuild.d.ts.map +1 -0
- package/dist/cli-rebuild.js +29 -0
- package/dist/cli-rebuild.js.map +1 -0
- package/dist/cli-reset.d.ts +27 -0
- package/dist/cli-reset.d.ts.map +1 -0
- package/dist/cli-reset.js +44 -0
- package/dist/cli-reset.js.map +1 -0
- package/dist/cli-snapshot.d.ts +398 -0
- package/dist/cli-snapshot.d.ts.map +1 -0
- package/dist/cli-snapshot.js +45 -0
- package/dist/cli-snapshot.js.map +1 -0
- package/dist/cli-task-context.d.ts +3 -0
- package/dist/cli-task-context.d.ts.map +1 -0
- package/dist/cli-task-context.js +112 -0
- package/dist/cli-task-context.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1004 -0
- package/dist/cli.js.map +1 -0
- package/dist/graph-packages-lock.d.ts +169 -0
- package/dist/graph-packages-lock.d.ts.map +1 -0
- package/dist/graph-packages-lock.js +503 -0
- package/dist/graph-packages-lock.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/local/aggregate-preflight.d.ts +12 -0
- package/dist/local/aggregate-preflight.d.ts.map +1 -0
- package/dist/local/aggregate-preflight.js +22 -0
- package/dist/local/aggregate-preflight.js.map +1 -0
- package/dist/local/allow-mcp.d.ts +77 -0
- package/dist/local/allow-mcp.d.ts.map +1 -0
- package/dist/local/allow-mcp.js +394 -0
- package/dist/local/allow-mcp.js.map +1 -0
- package/dist/local/api-client.d.ts +15 -0
- package/dist/local/api-client.d.ts.map +1 -0
- package/dist/local/api-client.js +87 -0
- package/dist/local/api-client.js.map +1 -0
- package/dist/local/app-contract-readers.d.ts +229 -0
- package/dist/local/app-contract-readers.d.ts.map +1 -0
- package/dist/local/app-contract-readers.js +450 -0
- package/dist/local/app-contract-readers.js.map +1 -0
- package/dist/local/app-org-reader.d.ts +21 -0
- package/dist/local/app-org-reader.d.ts.map +1 -0
- package/dist/local/app-org-reader.js +66 -0
- package/dist/local/app-org-reader.js.map +1 -0
- package/dist/local/app-shell-readers.d.ts +96 -0
- package/dist/local/app-shell-readers.d.ts.map +1 -0
- package/dist/local/app-shell-readers.js +381 -0
- package/dist/local/app-shell-readers.js.map +1 -0
- package/dist/local/app-tasks-read.d.ts +202 -0
- package/dist/local/app-tasks-read.d.ts.map +1 -0
- package/dist/local/app-tasks-read.js +290 -0
- package/dist/local/app-tasks-read.js.map +1 -0
- package/dist/local/app-worktrees.d.ts +69 -0
- package/dist/local/app-worktrees.d.ts.map +1 -0
- package/dist/local/app-worktrees.js +554 -0
- package/dist/local/app-worktrees.js.map +1 -0
- package/dist/local/base-sync-manifest.d.ts +12 -0
- package/dist/local/base-sync-manifest.d.ts.map +1 -0
- package/dist/local/base-sync-manifest.js +57 -0
- package/dist/local/base-sync-manifest.js.map +1 -0
- package/dist/local/blast-radius.d.ts +191 -0
- package/dist/local/blast-radius.d.ts.map +1 -0
- package/dist/local/blast-radius.js +585 -0
- package/dist/local/blast-radius.js.map +1 -0
- package/dist/local/canonical.d.ts +2 -0
- package/dist/local/canonical.d.ts.map +1 -0
- package/dist/local/canonical.js +2 -0
- package/dist/local/canonical.js.map +1 -0
- package/dist/local/config.d.ts +22 -0
- package/dist/local/config.d.ts.map +1 -0
- package/dist/local/config.js +57 -0
- package/dist/local/config.js.map +1 -0
- package/dist/local/document-commands.d.ts +163 -0
- package/dist/local/document-commands.d.ts.map +1 -0
- package/dist/local/document-commands.js +620 -0
- package/dist/local/document-commands.js.map +1 -0
- package/dist/local/document-embeds.d.ts +21 -0
- package/dist/local/document-embeds.d.ts.map +1 -0
- package/dist/local/document-embeds.js +38 -0
- package/dist/local/document-embeds.js.map +1 -0
- package/dist/local/environment-context.d.ts +39 -0
- package/dist/local/environment-context.d.ts.map +1 -0
- package/dist/local/environment-context.js +193 -0
- package/dist/local/environment-context.js.map +1 -0
- package/dist/local/environment-exclude.d.ts +7 -0
- package/dist/local/environment-exclude.d.ts.map +1 -0
- package/dist/local/environment-exclude.js +82 -0
- package/dist/local/environment-exclude.js.map +1 -0
- package/dist/local/environment-sidecar.d.ts +126 -0
- package/dist/local/environment-sidecar.d.ts.map +1 -0
- package/dist/local/environment-sidecar.js +442 -0
- package/dist/local/environment-sidecar.js.map +1 -0
- package/dist/local/environment-switch.d.ts +22 -0
- package/dist/local/environment-switch.d.ts.map +1 -0
- package/dist/local/environment-switch.js +385 -0
- package/dist/local/environment-switch.js.map +1 -0
- package/dist/local/exact-remote-projection.d.ts +17 -0
- package/dist/local/exact-remote-projection.d.ts.map +1 -0
- package/dist/local/exact-remote-projection.js +53 -0
- package/dist/local/exact-remote-projection.js.map +1 -0
- package/dist/local/experimental/path-object-store.d.ts +66 -0
- package/dist/local/experimental/path-object-store.d.ts.map +1 -0
- package/dist/local/experimental/path-object-store.js +135 -0
- package/dist/local/experimental/path-object-store.js.map +1 -0
- package/dist/local/external-worktree-binding.d.ts +21 -0
- package/dist/local/external-worktree-binding.d.ts.map +1 -0
- package/dist/local/external-worktree-binding.js +56 -0
- package/dist/local/external-worktree-binding.js.map +1 -0
- package/dist/local/folder-members.d.ts +34 -0
- package/dist/local/folder-members.d.ts.map +1 -0
- package/dist/local/folder-members.js +168 -0
- package/dist/local/folder-members.js.map +1 -0
- package/dist/local/git-ref-authority.d.ts +11 -0
- package/dist/local/git-ref-authority.d.ts.map +1 -0
- package/dist/local/git-ref-authority.js +76 -0
- package/dist/local/git-ref-authority.js.map +1 -0
- package/dist/local/git.d.ts +88 -0
- package/dist/local/git.d.ts.map +1 -0
- package/dist/local/git.js +413 -0
- package/dist/local/git.js.map +1 -0
- package/dist/local/graph-read.d.ts +168 -0
- package/dist/local/graph-read.d.ts.map +1 -0
- package/dist/local/graph-read.js +360 -0
- package/dist/local/graph-read.js.map +1 -0
- package/dist/local/graph-sync.d.ts +39 -0
- package/dist/local/graph-sync.d.ts.map +1 -0
- package/dist/local/graph-sync.js +186 -0
- package/dist/local/graph-sync.js.map +1 -0
- package/dist/local/guide-commands.d.ts +79 -0
- package/dist/local/guide-commands.d.ts.map +1 -0
- package/dist/local/guide-commands.js +247 -0
- package/dist/local/guide-commands.js.map +1 -0
- package/dist/local/health-files.d.ts +24 -0
- package/dist/local/health-files.d.ts.map +1 -0
- package/dist/local/health-files.js +133 -0
- package/dist/local/health-files.js.map +1 -0
- package/dist/local/health-inspection.d.ts +12 -0
- package/dist/local/health-inspection.d.ts.map +1 -0
- package/dist/local/health-inspection.js +407 -0
- package/dist/local/health-inspection.js.map +1 -0
- package/dist/local/health-policy.d.ts +11 -0
- package/dist/local/health-policy.d.ts.map +1 -0
- package/dist/local/health-policy.js +257 -0
- package/dist/local/health-policy.js.map +1 -0
- package/dist/local/health-projection.d.ts +14 -0
- package/dist/local/health-projection.d.ts.map +1 -0
- package/dist/local/health-projection.js +102 -0
- package/dist/local/health-projection.js.map +1 -0
- package/dist/local/health-schema.d.ts +338 -0
- package/dist/local/health-schema.d.ts.map +1 -0
- package/dist/local/health-schema.js +213 -0
- package/dist/local/health-schema.js.map +1 -0
- package/dist/local/health-store.d.ts +61 -0
- package/dist/local/health-store.d.ts.map +1 -0
- package/dist/local/health-store.js +218 -0
- package/dist/local/health-store.js.map +1 -0
- package/dist/local/index.d.ts +66 -0
- package/dist/local/index.d.ts.map +1 -0
- package/dist/local/index.js +66 -0
- package/dist/local/index.js.map +1 -0
- package/dist/local/journey-commands.d.ts +65 -0
- package/dist/local/journey-commands.d.ts.map +1 -0
- package/dist/local/journey-commands.js +138 -0
- package/dist/local/journey-commands.js.map +1 -0
- package/dist/local/local-org-store.d.ts +46 -0
- package/dist/local/local-org-store.d.ts.map +1 -0
- package/dist/local/local-org-store.js +132 -0
- package/dist/local/local-org-store.js.map +1 -0
- package/dist/local/local-org.d.ts +389 -0
- package/dist/local/local-org.d.ts.map +1 -0
- package/dist/local/local-org.js +855 -0
- package/dist/local/local-org.js.map +1 -0
- package/dist/local/media-upload.d.ts +5 -0
- package/dist/local/media-upload.d.ts.map +1 -0
- package/dist/local/media-upload.js +41 -0
- package/dist/local/media-upload.js.map +1 -0
- package/dist/local/operation.d.ts +155 -0
- package/dist/local/operation.d.ts.map +1 -0
- package/dist/local/operation.js +340 -0
- package/dist/local/operation.js.map +1 -0
- package/dist/local/ownership-reader-schema.d.ts +117 -0
- package/dist/local/ownership-reader-schema.d.ts.map +1 -0
- package/dist/local/ownership-reader-schema.js +105 -0
- package/dist/local/ownership-reader-schema.js.map +1 -0
- package/dist/local/ownership-reader-worker.d.ts +2 -0
- package/dist/local/ownership-reader-worker.d.ts.map +1 -0
- package/dist/local/ownership-reader-worker.js +341 -0
- package/dist/local/ownership-reader-worker.js.map +1 -0
- package/dist/local/ownership-reader.d.ts +10 -0
- package/dist/local/ownership-reader.d.ts.map +1 -0
- package/dist/local/ownership-reader.js +93 -0
- package/dist/local/ownership-reader.js.map +1 -0
- package/dist/local/package-uses-check.d.ts +33 -0
- package/dist/local/package-uses-check.d.ts.map +1 -0
- package/dist/local/package-uses-check.js +62 -0
- package/dist/local/package-uses-check.js.map +1 -0
- package/dist/local/pending-recovery.d.ts +22 -0
- package/dist/local/pending-recovery.d.ts.map +1 -0
- package/dist/local/pending-recovery.js +171 -0
- package/dist/local/pending-recovery.js.map +1 -0
- package/dist/local/portable-commit-store.d.ts +28 -0
- package/dist/local/portable-commit-store.d.ts.map +1 -0
- package/dist/local/portable-commit-store.js +187 -0
- package/dist/local/portable-commit-store.js.map +1 -0
- package/dist/local/portable-commit.d.ts +109 -0
- package/dist/local/portable-commit.d.ts.map +1 -0
- package/dist/local/portable-commit.js +209 -0
- package/dist/local/portable-commit.js.map +1 -0
- package/dist/local/portable-remote.d.ts +432 -0
- package/dist/local/portable-remote.d.ts.map +1 -0
- package/dist/local/portable-remote.js +280 -0
- package/dist/local/portable-remote.js.map +1 -0
- package/dist/local/project-deleted.d.ts +4 -0
- package/dist/local/project-deleted.d.ts.map +1 -0
- package/dist/local/project-deleted.js +13 -0
- package/dist/local/project-deleted.js.map +1 -0
- package/dist/local/projection.d.ts +166 -0
- package/dist/local/projection.d.ts.map +1 -0
- package/dist/local/projection.js +709 -0
- package/dist/local/projection.js.map +1 -0
- package/dist/local/read-operation.d.ts +3 -0
- package/dist/local/read-operation.d.ts.map +1 -0
- package/dist/local/read-operation.js +19 -0
- package/dist/local/read-operation.js.map +1 -0
- package/dist/local/rebuild.d.ts +11 -0
- package/dist/local/rebuild.d.ts.map +1 -0
- package/dist/local/rebuild.js +42 -0
- package/dist/local/rebuild.js.map +1 -0
- package/dist/local/remote-base.d.ts +25 -0
- package/dist/local/remote-base.d.ts.map +1 -0
- package/dist/local/remote-base.js +68 -0
- package/dist/local/remote-base.js.map +1 -0
- package/dist/local/save-layout-worker.d.ts +19 -0
- package/dist/local/save-layout-worker.d.ts.map +1 -0
- package/dist/local/save-layout-worker.js +28 -0
- package/dist/local/save-layout-worker.js.map +1 -0
- package/dist/local/save-layout.d.ts +84 -0
- package/dist/local/save-layout.d.ts.map +1 -0
- package/dist/local/save-layout.js +221 -0
- package/dist/local/save-layout.js.map +1 -0
- package/dist/local/scope-impact.d.ts +31 -0
- package/dist/local/scope-impact.d.ts.map +1 -0
- package/dist/local/scope-impact.js +32 -0
- package/dist/local/scope-impact.js.map +1 -0
- package/dist/local/source-evidence/filesystem-worker.d.ts +2 -0
- package/dist/local/source-evidence/filesystem-worker.d.ts.map +1 -0
- package/dist/local/source-evidence/filesystem-worker.js +139 -0
- package/dist/local/source-evidence/filesystem-worker.js.map +1 -0
- package/dist/local/source-evidence/processes.d.ts +20 -0
- package/dist/local/source-evidence/processes.d.ts.map +1 -0
- package/dist/local/source-evidence/processes.js +133 -0
- package/dist/local/source-evidence/processes.js.map +1 -0
- package/dist/local/source-evidence/protocol.d.ts +52 -0
- package/dist/local/source-evidence/protocol.d.ts.map +1 -0
- package/dist/local/source-evidence/protocol.js +72 -0
- package/dist/local/source-evidence/protocol.js.map +1 -0
- package/dist/local/source-evidence/reader.d.ts +14 -0
- package/dist/local/source-evidence/reader.d.ts.map +1 -0
- package/dist/local/source-evidence/reader.js +308 -0
- package/dist/local/source-evidence/reader.js.map +1 -0
- package/dist/local/source-evidence/schema.d.ts +2504 -0
- package/dist/local/source-evidence/schema.d.ts.map +1 -0
- package/dist/local/source-evidence/schema.js +99 -0
- package/dist/local/source-evidence/schema.js.map +1 -0
- package/dist/local/source-policy/loader.d.ts +29 -0
- package/dist/local/source-policy/loader.d.ts.map +1 -0
- package/dist/local/source-policy/loader.js +209 -0
- package/dist/local/source-policy/loader.js.map +1 -0
- package/dist/local/source-policy/process.d.ts +7 -0
- package/dist/local/source-policy/process.d.ts.map +1 -0
- package/dist/local/source-policy/process.js +53 -0
- package/dist/local/source-policy/process.js.map +1 -0
- package/dist/local/source-policy/protocol.d.ts +27 -0
- package/dist/local/source-policy/protocol.d.ts.map +1 -0
- package/dist/local/source-policy/protocol.js +48 -0
- package/dist/local/source-policy/protocol.js.map +1 -0
- package/dist/local/source-policy/worker.d.ts +2 -0
- package/dist/local/source-policy/worker.d.ts.map +1 -0
- package/dist/local/source-policy/worker.js +100 -0
- package/dist/local/source-policy/worker.js.map +1 -0
- package/dist/local/state-directory.d.ts +17 -0
- package/dist/local/state-directory.d.ts.map +1 -0
- package/dist/local/state-directory.js +68 -0
- package/dist/local/state-directory.js.map +1 -0
- package/dist/local/store-database.d.ts +13 -0
- package/dist/local/store-database.d.ts.map +1 -0
- package/dist/local/store-database.js +187 -0
- package/dist/local/store-database.js.map +1 -0
- package/dist/local/store.d.ts +181 -0
- package/dist/local/store.d.ts.map +1 -0
- package/dist/local/store.js +585 -0
- package/dist/local/store.js.map +1 -0
- package/dist/local/sync.d.ts +47 -0
- package/dist/local/sync.d.ts.map +1 -0
- package/dist/local/sync.js +518 -0
- package/dist/local/sync.js.map +1 -0
- package/dist/local/task-context-inspection.d.ts +23 -0
- package/dist/local/task-context-inspection.d.ts.map +1 -0
- package/dist/local/task-context-inspection.js +165 -0
- package/dist/local/task-context-inspection.js.map +1 -0
- package/dist/local/task-context-observations.d.ts +9553 -0
- package/dist/local/task-context-observations.d.ts.map +1 -0
- package/dist/local/task-context-observations.js +232 -0
- package/dist/local/task-context-observations.js.map +1 -0
- package/dist/local/task-context-provider.d.ts +18 -0
- package/dist/local/task-context-provider.d.ts.map +1 -0
- package/dist/local/task-context-provider.js +231 -0
- package/dist/local/task-context-provider.js.map +1 -0
- package/dist/local/task-context-schema.d.ts +847 -0
- package/dist/local/task-context-schema.d.ts.map +1 -0
- package/dist/local/task-context-schema.js +305 -0
- package/dist/local/task-context-schema.js.map +1 -0
- package/dist/local/task-context-source.d.ts +16 -0
- package/dist/local/task-context-source.d.ts.map +1 -0
- package/dist/local/task-context-source.js +45 -0
- package/dist/local/task-context-source.js.map +1 -0
- package/dist/local/task-context.d.ts +14 -0
- package/dist/local/task-context.d.ts.map +1 -0
- package/dist/local/task-context.js +570 -0
- package/dist/local/task-context.js.map +1 -0
- package/dist/local/test-commands.d.ts +71 -0
- package/dist/local/test-commands.d.ts.map +1 -0
- package/dist/local/test-commands.js +292 -0
- package/dist/local/test-commands.js.map +1 -0
- package/dist/local/tree-save.d.ts +117 -0
- package/dist/local/tree-save.d.ts.map +1 -0
- package/dist/local/tree-save.js +615 -0
- package/dist/local/tree-save.js.map +1 -0
- package/dist/local/variants.d.ts +125 -0
- package/dist/local/variants.d.ts.map +1 -0
- package/dist/local/variants.js +267 -0
- package/dist/local/variants.js.map +1 -0
- package/dist/local/workspace-admission.d.ts +61 -0
- package/dist/local/workspace-admission.d.ts.map +1 -0
- package/dist/local/workspace-admission.js +112 -0
- package/dist/local/workspace-admission.js.map +1 -0
- package/dist/local/workspace-authority-guard.d.ts +18 -0
- package/dist/local/workspace-authority-guard.d.ts.map +1 -0
- package/dist/local/workspace-authority-guard.js +69 -0
- package/dist/local/workspace-authority-guard.js.map +1 -0
- package/dist/local/workspace-authority.d.ts +33 -0
- package/dist/local/workspace-authority.d.ts.map +1 -0
- package/dist/local/workspace-authority.js +33 -0
- package/dist/local/workspace-authority.js.map +1 -0
- package/dist/local/workspace-branch-runtime.d.ts +61 -0
- package/dist/local/workspace-branch-runtime.d.ts.map +1 -0
- package/dist/local/workspace-branch-runtime.js +216 -0
- package/dist/local/workspace-branch-runtime.js.map +1 -0
- package/dist/local/workspace-built-content.d.ts +137 -0
- package/dist/local/workspace-built-content.d.ts.map +1 -0
- package/dist/local/workspace-built-content.js +393 -0
- package/dist/local/workspace-built-content.js.map +1 -0
- package/dist/local/workspace-claim-status-read.d.ts +53 -0
- package/dist/local/workspace-claim-status-read.d.ts.map +1 -0
- package/dist/local/workspace-claim-status-read.js +118 -0
- package/dist/local/workspace-claim-status-read.js.map +1 -0
- package/dist/local/workspace-claim-status.d.ts +172 -0
- package/dist/local/workspace-claim-status.d.ts.map +1 -0
- package/dist/local/workspace-claim-status.js +721 -0
- package/dist/local/workspace-claim-status.js.map +1 -0
- package/dist/local/workspace-claim-views.d.ts +45 -0
- package/dist/local/workspace-claim-views.d.ts.map +1 -0
- package/dist/local/workspace-claim-views.js +45 -0
- package/dist/local/workspace-claim-views.js.map +1 -0
- package/dist/local/workspace-cli.d.ts +46 -0
- package/dist/local/workspace-cli.d.ts.map +1 -0
- package/dist/local/workspace-cli.js +1524 -0
- package/dist/local/workspace-cli.js.map +1 -0
- package/dist/local/workspace-commit-resolver.d.ts +19 -0
- package/dist/local/workspace-commit-resolver.d.ts.map +1 -0
- package/dist/local/workspace-commit-resolver.js +47 -0
- package/dist/local/workspace-commit-resolver.js.map +1 -0
- package/dist/local/workspace-decision-store.d.ts +184 -0
- package/dist/local/workspace-decision-store.d.ts.map +1 -0
- package/dist/local/workspace-decision-store.js +510 -0
- package/dist/local/workspace-decision-store.js.map +1 -0
- package/dist/local/workspace-environment-runtime.d.ts +107 -0
- package/dist/local/workspace-environment-runtime.d.ts.map +1 -0
- package/dist/local/workspace-environment-runtime.js +135 -0
- package/dist/local/workspace-environment-runtime.js.map +1 -0
- package/dist/local/workspace-evidence-drop.d.ts +21 -0
- package/dist/local/workspace-evidence-drop.d.ts.map +1 -0
- package/dist/local/workspace-evidence-drop.js +58 -0
- package/dist/local/workspace-evidence-drop.js.map +1 -0
- package/dist/local/workspace-evidence-sign-tool.d.ts +20 -0
- package/dist/local/workspace-evidence-sign-tool.d.ts.map +1 -0
- package/dist/local/workspace-evidence-sign-tool.js +85 -0
- package/dist/local/workspace-evidence-sign-tool.js.map +1 -0
- package/dist/local/workspace-evidence-status.d.ts +89 -0
- package/dist/local/workspace-evidence-status.d.ts.map +1 -0
- package/dist/local/workspace-evidence-status.js +141 -0
- package/dist/local/workspace-evidence-status.js.map +1 -0
- package/dist/local/workspace-evidence.d.ts +145 -0
- package/dist/local/workspace-evidence.d.ts.map +1 -0
- package/dist/local/workspace-evidence.js +347 -0
- package/dist/local/workspace-evidence.js.map +1 -0
- package/dist/local/workspace-graph-store.d.ts +32 -0
- package/dist/local/workspace-graph-store.d.ts.map +1 -0
- package/dist/local/workspace-graph-store.js +249 -0
- package/dist/local/workspace-graph-store.js.map +1 -0
- package/dist/local/workspace-handoff.d.ts +32 -0
- package/dist/local/workspace-handoff.d.ts.map +1 -0
- package/dist/local/workspace-handoff.js +144 -0
- package/dist/local/workspace-handoff.js.map +1 -0
- package/dist/local/workspace-history-journal.d.ts +70 -0
- package/dist/local/workspace-history-journal.d.ts.map +1 -0
- package/dist/local/workspace-history-journal.js +131 -0
- package/dist/local/workspace-history-journal.js.map +1 -0
- package/dist/local/workspace-history-store.d.ts +98 -0
- package/dist/local/workspace-history-store.d.ts.map +1 -0
- package/dist/local/workspace-history-store.js +632 -0
- package/dist/local/workspace-history-store.js.map +1 -0
- package/dist/local/workspace-history-types.d.ts +307 -0
- package/dist/local/workspace-history-types.d.ts.map +1 -0
- package/dist/local/workspace-history-types.js +2 -0
- package/dist/local/workspace-history-types.js.map +1 -0
- package/dist/local/workspace-integration-runtime.d.ts +48 -0
- package/dist/local/workspace-integration-runtime.d.ts.map +1 -0
- package/dist/local/workspace-integration-runtime.js +419 -0
- package/dist/local/workspace-integration-runtime.js.map +1 -0
- package/dist/local/workspace-lock.d.ts +7 -0
- package/dist/local/workspace-lock.d.ts.map +1 -0
- package/dist/local/workspace-lock.js +211 -0
- package/dist/local/workspace-lock.js.map +1 -0
- package/dist/local/workspace-merge.d.ts +77 -0
- package/dist/local/workspace-merge.d.ts.map +1 -0
- package/dist/local/workspace-merge.js +703 -0
- package/dist/local/workspace-merge.js.map +1 -0
- package/dist/local/workspace-mixed-history.d.ts +33 -0
- package/dist/local/workspace-mixed-history.d.ts.map +1 -0
- package/dist/local/workspace-mixed-history.js +107 -0
- package/dist/local/workspace-mixed-history.js.map +1 -0
- package/dist/local/workspace-overlap-allocation.d.ts +33 -0
- package/dist/local/workspace-overlap-allocation.d.ts.map +1 -0
- package/dist/local/workspace-overlap-allocation.js +69 -0
- package/dist/local/workspace-overlap-allocation.js.map +1 -0
- package/dist/local/workspace-overlap-impact.d.ts +46 -0
- package/dist/local/workspace-overlap-impact.d.ts.map +1 -0
- package/dist/local/workspace-overlap-impact.js +162 -0
- package/dist/local/workspace-overlap-impact.js.map +1 -0
- package/dist/local/workspace-overlap.d.ts +109 -0
- package/dist/local/workspace-overlap.d.ts.map +1 -0
- package/dist/local/workspace-overlap.js +327 -0
- package/dist/local/workspace-overlap.js.map +1 -0
- package/dist/local/workspace-paths.d.ts +4 -0
- package/dist/local/workspace-paths.d.ts.map +1 -0
- package/dist/local/workspace-paths.js +8 -0
- package/dist/local/workspace-paths.js.map +1 -0
- package/dist/local/workspace-pick-runtime.d.ts +70 -0
- package/dist/local/workspace-pick-runtime.d.ts.map +1 -0
- package/dist/local/workspace-pick-runtime.js +177 -0
- package/dist/local/workspace-pick-runtime.js.map +1 -0
- package/dist/local/workspace-pick-store.d.ts +33 -0
- package/dist/local/workspace-pick-store.d.ts.map +1 -0
- package/dist/local/workspace-pick-store.js +43 -0
- package/dist/local/workspace-pick-store.js.map +1 -0
- package/dist/local/workspace-pick.d.ts +73 -0
- package/dist/local/workspace-pick.d.ts.map +1 -0
- package/dist/local/workspace-pick.js +253 -0
- package/dist/local/workspace-pick.js.map +1 -0
- package/dist/local/workspace-portable-authoring.d.ts +43 -0
- package/dist/local/workspace-portable-authoring.d.ts.map +1 -0
- package/dist/local/workspace-portable-authoring.js +128 -0
- package/dist/local/workspace-portable-authoring.js.map +1 -0
- package/dist/local/workspace-prune.d.ts +63 -0
- package/dist/local/workspace-prune.d.ts.map +1 -0
- package/dist/local/workspace-prune.js +267 -0
- package/dist/local/workspace-prune.js.map +1 -0
- package/dist/local/workspace-remote-fetch.d.ts +82 -0
- package/dist/local/workspace-remote-fetch.d.ts.map +1 -0
- package/dist/local/workspace-remote-fetch.js +409 -0
- package/dist/local/workspace-remote-fetch.js.map +1 -0
- package/dist/local/workspace-remote-provider.d.ts +97 -0
- package/dist/local/workspace-remote-provider.d.ts.map +1 -0
- package/dist/local/workspace-remote-provider.js +400 -0
- package/dist/local/workspace-remote-provider.js.map +1 -0
- package/dist/local/workspace-remote-pull-request-journal.d.ts +49 -0
- package/dist/local/workspace-remote-pull-request-journal.d.ts.map +1 -0
- package/dist/local/workspace-remote-pull-request-journal.js +63 -0
- package/dist/local/workspace-remote-pull-request-journal.js.map +1 -0
- package/dist/local/workspace-remote-pull-request.d.ts +36 -0
- package/dist/local/workspace-remote-pull-request.d.ts.map +1 -0
- package/dist/local/workspace-remote-pull-request.js +158 -0
- package/dist/local/workspace-remote-pull-request.js.map +1 -0
- package/dist/local/workspace-remote-push.d.ts +88 -0
- package/dist/local/workspace-remote-push.d.ts.map +1 -0
- package/dist/local/workspace-remote-push.js +297 -0
- package/dist/local/workspace-remote-push.js.map +1 -0
- package/dist/local/workspace-remote-topic-journal.d.ts +56 -0
- package/dist/local/workspace-remote-topic-journal.d.ts.map +1 -0
- package/dist/local/workspace-remote-topic-journal.js +121 -0
- package/dist/local/workspace-remote-topic-journal.js.map +1 -0
- package/dist/local/workspace-remote-topic.d.ts +45 -0
- package/dist/local/workspace-remote-topic.d.ts.map +1 -0
- package/dist/local/workspace-remote-topic.js +204 -0
- package/dist/local/workspace-remote-topic.js.map +1 -0
- package/dist/local/workspace-remote-transfer.d.ts +76 -0
- package/dist/local/workspace-remote-transfer.d.ts.map +1 -0
- package/dist/local/workspace-remote-transfer.js +270 -0
- package/dist/local/workspace-remote-transfer.js.map +1 -0
- package/dist/local/workspace-resolution.d.ts +145 -0
- package/dist/local/workspace-resolution.d.ts.map +1 -0
- package/dist/local/workspace-resolution.js +479 -0
- package/dist/local/workspace-resolution.js.map +1 -0
- package/dist/local/workspace-resolver-provider.d.ts +72 -0
- package/dist/local/workspace-resolver-provider.d.ts.map +1 -0
- package/dist/local/workspace-resolver-provider.js +312 -0
- package/dist/local/workspace-resolver-provider.js.map +1 -0
- package/dist/local/workspace-runtime-handoff.d.ts +52 -0
- package/dist/local/workspace-runtime-handoff.d.ts.map +1 -0
- package/dist/local/workspace-runtime-handoff.js +237 -0
- package/dist/local/workspace-runtime-handoff.js.map +1 -0
- package/dist/local/workspace-runtime-lease.d.ts +26 -0
- package/dist/local/workspace-runtime-lease.d.ts.map +1 -0
- package/dist/local/workspace-runtime-lease.js +123 -0
- package/dist/local/workspace-runtime-lease.js.map +1 -0
- package/dist/local/workspace-runtime.d.ts +690 -0
- package/dist/local/workspace-runtime.d.ts.map +1 -0
- package/dist/local/workspace-runtime.js +2124 -0
- package/dist/local/workspace-runtime.js.map +1 -0
- package/dist/local/workspace-scope.d.ts +70 -0
- package/dist/local/workspace-scope.d.ts.map +1 -0
- package/dist/local/workspace-scope.js +206 -0
- package/dist/local/workspace-scope.js.map +1 -0
- package/dist/local/workspace-sources.d.ts +159 -0
- package/dist/local/workspace-sources.d.ts.map +1 -0
- package/dist/local/workspace-sources.js +570 -0
- package/dist/local/workspace-sources.js.map +1 -0
- package/dist/local/workspace-store-database.d.ts +5 -0
- package/dist/local/workspace-store-database.d.ts.map +1 -0
- package/dist/local/workspace-store-database.js +726 -0
- package/dist/local/workspace-store-database.js.map +1 -0
- package/dist/local/workspace-store.d.ts +261 -0
- package/dist/local/workspace-store.d.ts.map +1 -0
- package/dist/local/workspace-store.js +831 -0
- package/dist/local/workspace-store.js.map +1 -0
- package/dist/local/workspace-topology-runtime.d.ts +27 -0
- package/dist/local/workspace-topology-runtime.d.ts.map +1 -0
- package/dist/local/workspace-topology-runtime.js +396 -0
- package/dist/local/workspace-topology-runtime.js.map +1 -0
- package/dist/local/workspace-topology.d.ts +140 -0
- package/dist/local/workspace-topology.d.ts.map +1 -0
- package/dist/local/workspace-topology.js +359 -0
- package/dist/local/workspace-topology.js.map +1 -0
- package/dist/local/workspace-upstream-inspection.d.ts +60 -0
- package/dist/local/workspace-upstream-inspection.d.ts.map +1 -0
- package/dist/local/workspace-upstream-inspection.js +189 -0
- package/dist/local/workspace-upstream-inspection.js.map +1 -0
- package/dist/local/workspace-upstream-runtime.d.ts +91 -0
- package/dist/local/workspace-upstream-runtime.d.ts.map +1 -0
- package/dist/local/workspace-upstream-runtime.js +270 -0
- package/dist/local/workspace-upstream-runtime.js.map +1 -0
- package/dist/local/workspace-upstream-store.d.ts +51 -0
- package/dist/local/workspace-upstream-store.d.ts.map +1 -0
- package/dist/local/workspace-upstream-store.js +475 -0
- package/dist/local/workspace-upstream-store.js.map +1 -0
- package/dist/local/workspace-viewer-server.d.ts +136 -0
- package/dist/local/workspace-viewer-server.d.ts.map +1 -0
- package/dist/local/workspace-viewer-server.js +1097 -0
- package/dist/local/workspace-viewer-server.js.map +1 -0
- package/dist/local/workspace-viewer-snapshot.d.ts +49 -0
- package/dist/local/workspace-viewer-snapshot.d.ts.map +1 -0
- package/dist/local/workspace-viewer-snapshot.js +91 -0
- package/dist/local/workspace-viewer-snapshot.js.map +1 -0
- package/dist/local/worktree-projection.d.ts +76 -0
- package/dist/local/worktree-projection.d.ts.map +1 -0
- package/dist/local/worktree-projection.js +470 -0
- package/dist/local/worktree-projection.js.map +1 -0
- package/dist/mcp/client-identity.d.ts +8 -0
- package/dist/mcp/client-identity.d.ts.map +1 -0
- package/dist/mcp/client-identity.js +33 -0
- package/dist/mcp/client-identity.js.map +1 -0
- package/dist/mcp/graph-to-code.d.ts +53 -0
- package/dist/mcp/graph-to-code.d.ts.map +1 -0
- package/dist/mcp/graph-to-code.js +1624 -0
- package/dist/mcp/graph-to-code.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +3 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/stdio/graph-to-code.d.ts +3 -0
- package/dist/mcp/stdio/graph-to-code.d.ts.map +1 -0
- package/dist/mcp/stdio/graph-to-code.js +55 -0
- package/dist/mcp/stdio/graph-to-code.js.map +1 -0
- package/dist/mcp/stdio/worktree.d.ts +3 -0
- package/dist/mcp/stdio/worktree.d.ts.map +1 -0
- package/dist/mcp/stdio/worktree.js +67 -0
- package/dist/mcp/stdio/worktree.js.map +1 -0
- package/dist/mcp/worktree-claim-status.d.ts +162 -0
- package/dist/mcp/worktree-claim-status.d.ts.map +1 -0
- package/dist/mcp/worktree-claim-status.js +113 -0
- package/dist/mcp/worktree-claim-status.js.map +1 -0
- package/dist/mcp/worktree-dispatch.d.ts +13 -0
- package/dist/mcp/worktree-dispatch.d.ts.map +1 -0
- package/dist/mcp/worktree-dispatch.js +52 -0
- package/dist/mcp/worktree-dispatch.js.map +1 -0
- package/dist/mcp/worktree-errors.d.ts +15 -0
- package/dist/mcp/worktree-errors.d.ts.map +1 -0
- package/dist/mcp/worktree-errors.js +17 -0
- package/dist/mcp/worktree-errors.js.map +1 -0
- package/dist/mcp/worktree-health.d.ts +12 -0
- package/dist/mcp/worktree-health.d.ts.map +1 -0
- package/dist/mcp/worktree-health.js +32 -0
- package/dist/mcp/worktree-health.js.map +1 -0
- package/dist/mcp/worktree-results.d.ts +15 -0
- package/dist/mcp/worktree-results.d.ts.map +1 -0
- package/dist/mcp/worktree-results.js +12 -0
- package/dist/mcp/worktree-results.js.map +1 -0
- package/dist/mcp/worktree-task-context.d.ts +57 -0
- package/dist/mcp/worktree-task-context.d.ts.map +1 -0
- package/dist/mcp/worktree-task-context.js +45 -0
- package/dist/mcp/worktree-task-context.js.map +1 -0
- package/dist/mcp/worktree-tools.d.ts +2648 -0
- package/dist/mcp/worktree-tools.d.ts.map +1 -0
- package/dist/mcp/worktree-tools.js +192 -0
- package/dist/mcp/worktree-tools.js.map +1 -0
- package/dist/mcp/worktree.d.ts +33 -0
- package/dist/mcp/worktree.d.ts.map +1 -0
- package/dist/mcp/worktree.js +551 -0
- package/dist/mcp/worktree.js.map +1 -0
- package/dist/own-package.d.ts +13 -0
- package/dist/own-package.d.ts.map +1 -0
- package/dist/own-package.js +32 -0
- package/dist/own-package.js.map +1 -0
- package/dist/packages-browse.d.ts +107 -0
- package/dist/packages-browse.d.ts.map +1 -0
- package/dist/packages-browse.js +646 -0
- package/dist/packages-browse.js.map +1 -0
- package/dist/packages-cli.d.ts +8 -0
- package/dist/packages-cli.d.ts.map +1 -0
- package/dist/packages-cli.js +184 -0
- package/dist/packages-cli.js.map +1 -0
- package/dist/packages-uses.d.ts +46 -0
- package/dist/packages-uses.d.ts.map +1 -0
- package/dist/packages-uses.js +737 -0
- package/dist/packages-uses.js.map +1 -0
- package/dist/portable.d.ts +7 -0
- package/dist/portable.d.ts.map +1 -0
- package/dist/portable.js +14 -0
- package/dist/portable.js.map +1 -0
- package/dist/quiet-warnings.d.ts +3 -0
- package/dist/quiet-warnings.d.ts.map +1 -0
- package/dist/quiet-warnings.js +21 -0
- package/dist/quiet-warnings.js.map +1 -0
- package/dist/view-seam.d.ts +62 -0
- package/dist/view-seam.d.ts.map +1 -0
- package/dist/view-seam.js +70 -0
- package/dist/view-seam.js.map +1 -0
- package/generated/graph-packages/index.json +5 -0
- package/graph-packages.lock.json +4 -0
- package/package.json +81 -0
- package/viewer/assets/index-BZKGDARF.css +1 -0
- package/viewer/assets/index-DWu0CbZZ.js +272 -0
- package/viewer/index.html +13 -0
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, readFile, readdir, rename, rm, rmdir, stat, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, sep } from 'node:path';
|
|
4
|
+
import { encodeEvidenceMeta, isEvidenceBoundaryEnabled, markEvidenceFormatUpgrade, upgradeGraphEvidenceFormat, portable_graph_edge_schema, portable_graph_node_schema, portable_graph_path_relation_schema, portable_graph_path_schema, portable_graph_schema, withoutEvidenceTransientState } from '@software-dlc/graph/schema';
|
|
5
|
+
import { validateBuiltGraph } from '@software-dlc/graph/validator';
|
|
6
|
+
import { diffPortableGraphs } from '@software-dlc/graph/computation';
|
|
7
|
+
import { canonicalizePortableGraph, stringifyCanonicalGraph, stringifyCanonicalJson } from './canonical.js';
|
|
8
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
9
|
+
export const DEFAULT_PROJECTION_DIRECTORY_NAME = 'sdlc';
|
|
10
|
+
/** The graph's package uses (graph-packages.md, Use), only while it has some. */
|
|
11
|
+
export const PACKAGE_USES_FILE = 'package-uses.json';
|
|
12
|
+
const ENTITY_CONFIG = {
|
|
13
|
+
node: {
|
|
14
|
+
directory: 'nodes',
|
|
15
|
+
graph_key: 'nodes',
|
|
16
|
+
safe_parse: (value) => portable_graph_node_schema.safeParse(value)
|
|
17
|
+
},
|
|
18
|
+
edge: {
|
|
19
|
+
directory: 'edges',
|
|
20
|
+
graph_key: 'edges',
|
|
21
|
+
safe_parse: (value) => portable_graph_edge_schema.safeParse(value)
|
|
22
|
+
},
|
|
23
|
+
path: {
|
|
24
|
+
directory: 'paths',
|
|
25
|
+
graph_key: 'paths',
|
|
26
|
+
safe_parse: (value) => portable_graph_path_schema.safeParse(value)
|
|
27
|
+
},
|
|
28
|
+
path_relation: {
|
|
29
|
+
directory: 'path-relations',
|
|
30
|
+
graph_key: 'path_relations',
|
|
31
|
+
safe_parse: (value) => portable_graph_path_relation_schema.safeParse(value)
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/** Every invalid entity file of a projection, reported together instead of the first one found. */
|
|
35
|
+
export class ProjectionEntityErrors extends Error {
|
|
36
|
+
errors;
|
|
37
|
+
constructor(errors) {
|
|
38
|
+
super([
|
|
39
|
+
`The projection has ${errors.length} invalid entity ${errors.length === 1 ? 'field' : 'fields'}:`,
|
|
40
|
+
...errors.map((error) => ` ${error.relative_path} (${error.entity_kind} ${error.entity_id})${error.field_path ? ` ${error.field_path}` : ''}: ${error.message}`)
|
|
41
|
+
].join('\n'));
|
|
42
|
+
this.name = 'ProjectionEntityErrors';
|
|
43
|
+
this.errors = errors;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const ENTITY_KINDS = Object.keys(ENTITY_CONFIG);
|
|
47
|
+
function entityRelativePath(kind, id) {
|
|
48
|
+
return `${ENTITY_CONFIG[kind].directory}/${id}.json`;
|
|
49
|
+
}
|
|
50
|
+
function graphEntities(graph, kind) {
|
|
51
|
+
const key = ENTITY_CONFIG[kind].graph_key;
|
|
52
|
+
return (graph[key] ?? []);
|
|
53
|
+
}
|
|
54
|
+
function parseJson(value, source) {
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(value);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60
|
+
throw new Error(`Invalid JSON in ${source}: ${message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function pathExists(path) {
|
|
64
|
+
try {
|
|
65
|
+
await stat(path);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export async function writeJsonAtomically(path, value) {
|
|
76
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
77
|
+
const temporary_path = `${path}.tmp-${randomUUID()}`;
|
|
78
|
+
try {
|
|
79
|
+
await writeFile(temporary_path, `${stringifyCanonicalJson(value, 2)}\n`, {
|
|
80
|
+
encoding: 'utf8',
|
|
81
|
+
mode: 0o600,
|
|
82
|
+
flag: 'wx'
|
|
83
|
+
});
|
|
84
|
+
await rename(temporary_path, path);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
await rm(temporary_path, { force: true });
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async function assertManagedDirectoryEntries(directory) {
|
|
92
|
+
if (!(await pathExists(directory)))
|
|
93
|
+
return;
|
|
94
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
95
|
+
if (!entry.isFile() || !entry.name.endsWith('.json')) {
|
|
96
|
+
throw new Error(`Managed projection directory contains unsupported entry: ${join(directory, entry.name)}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function materializeEntityKind(input) {
|
|
101
|
+
const directory = join(input.projection_dir, ENTITY_CONFIG[input.kind].directory);
|
|
102
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
103
|
+
await assertManagedDirectoryEntries(directory);
|
|
104
|
+
const desired_names = new Set();
|
|
105
|
+
for (const entity of input.entities) {
|
|
106
|
+
input.check?.();
|
|
107
|
+
const name = `${entity.id}.json`;
|
|
108
|
+
desired_names.add(name);
|
|
109
|
+
await writeJsonAtomically(join(directory, name), entity);
|
|
110
|
+
}
|
|
111
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
112
|
+
if (entry.isFile() &&
|
|
113
|
+
entry.name.endsWith('.json') &&
|
|
114
|
+
!desired_names.has(entry.name)) {
|
|
115
|
+
input.check?.();
|
|
116
|
+
await rm(join(directory, entry.name));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export function resolveProjectionDirectory(input) {
|
|
121
|
+
return (input.override ??
|
|
122
|
+
join(input.repository_root, DEFAULT_PROJECTION_DIRECTORY_NAME));
|
|
123
|
+
}
|
|
124
|
+
export async function projectionHasManagedContent(projection_dir) {
|
|
125
|
+
if (await pathExists(join(projection_dir, 'tags.json')))
|
|
126
|
+
return true;
|
|
127
|
+
if (await pathExists(join(projection_dir, PACKAGE_USES_FILE)))
|
|
128
|
+
return true;
|
|
129
|
+
for (const kind of ENTITY_KINDS) {
|
|
130
|
+
const directory = join(projection_dir, ENTITY_CONFIG[kind].directory);
|
|
131
|
+
if (!(await pathExists(directory)))
|
|
132
|
+
continue;
|
|
133
|
+
if ((await readdir(directory)).some((name) => name.endsWith('.json'))) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Undo an empty projection written into a directory that held no managed
|
|
141
|
+
* content: remove tags.json and the managed directories while they are still
|
|
142
|
+
* empty, and the projection directory itself only when nothing else is left.
|
|
143
|
+
*/
|
|
144
|
+
export async function removeEmptyGraphProjection(projection_dir) {
|
|
145
|
+
await rm(join(projection_dir, 'tags.json'), { force: true });
|
|
146
|
+
await rm(join(projection_dir, PACKAGE_USES_FILE), { force: true });
|
|
147
|
+
await rm(join(projection_dir, PROJECTION_MANIFEST_FILE), { force: true });
|
|
148
|
+
for (const name of [
|
|
149
|
+
...ENTITY_KINDS.map((kind) => ENTITY_CONFIG[kind].directory),
|
|
150
|
+
'scratch'
|
|
151
|
+
]) {
|
|
152
|
+
await removeEmptyDirectory(join(projection_dir, name));
|
|
153
|
+
}
|
|
154
|
+
await removeEmptyDirectory(projection_dir);
|
|
155
|
+
}
|
|
156
|
+
async function removeEmptyDirectory(path) {
|
|
157
|
+
if (!(await pathExists(path)))
|
|
158
|
+
return;
|
|
159
|
+
if ((await readdir(path)).length > 0)
|
|
160
|
+
return;
|
|
161
|
+
await rmdir(path);
|
|
162
|
+
}
|
|
163
|
+
/** Comparison authority belongs to the server, never editable projection metadata. */
|
|
164
|
+
function withoutWorktreeBuildOverride(meta) {
|
|
165
|
+
if (!meta || !('worktree_build_override' in meta))
|
|
166
|
+
return meta;
|
|
167
|
+
const { worktree_build_override: _override, ...retained } = meta;
|
|
168
|
+
return retained;
|
|
169
|
+
}
|
|
170
|
+
/** Strips in-memory evidence and comparison markers from entities. */
|
|
171
|
+
function withoutGraphEvidenceTransientState(graph) {
|
|
172
|
+
return {
|
|
173
|
+
...graph,
|
|
174
|
+
nodes: graph.nodes.map((node) => ({
|
|
175
|
+
...node,
|
|
176
|
+
data: {
|
|
177
|
+
...node.data,
|
|
178
|
+
meta: withoutWorktreeBuildOverride(withoutEvidenceTransientState(node.data.meta))
|
|
179
|
+
}
|
|
180
|
+
})),
|
|
181
|
+
edges: graph.edges.map((edge) => edge.data
|
|
182
|
+
? {
|
|
183
|
+
...edge,
|
|
184
|
+
data: {
|
|
185
|
+
...edge.data,
|
|
186
|
+
meta: withoutEvidenceTransientState(edge.data.meta)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
: edge)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Evidence as storage holds it: a decoded legacy value is presented as the
|
|
194
|
+
* legacy value alone and current evidence without its decode marker, so
|
|
195
|
+
* unchanged entities never differ from their stored form.
|
|
196
|
+
*/
|
|
197
|
+
function storedGraphEvidence(graph) {
|
|
198
|
+
if (!isEvidenceBoundaryEnabled())
|
|
199
|
+
return graph;
|
|
200
|
+
return {
|
|
201
|
+
...graph,
|
|
202
|
+
nodes: graph.nodes.map((node) => ({
|
|
203
|
+
...node,
|
|
204
|
+
data: {
|
|
205
|
+
...node.data,
|
|
206
|
+
meta: node.data.meta && encodeEvidenceMeta(node.data.meta)
|
|
207
|
+
}
|
|
208
|
+
})),
|
|
209
|
+
edges: graph.edges.map((edge) => edge.data
|
|
210
|
+
? {
|
|
211
|
+
...edge,
|
|
212
|
+
data: {
|
|
213
|
+
...edge.data,
|
|
214
|
+
meta: edge.data.meta && encodeEvidenceMeta(edge.data.meta)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
: edge)
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Projection files show evidence as stored. `--upgrade-evidence` converts
|
|
222
|
+
* every legacy entity to the latest contract as one reviewable change;
|
|
223
|
+
* without it, legacy evidence is shown and saved unchanged.
|
|
224
|
+
*/
|
|
225
|
+
function presentProjectionEvidence(input_graph, upgrade_evidence) {
|
|
226
|
+
const graph = isEvidenceBoundaryEnabled() && upgrade_evidence
|
|
227
|
+
? upgradeGraphEvidenceFormat(input_graph).graph
|
|
228
|
+
: storedGraphEvidence(input_graph);
|
|
229
|
+
return withoutGraphEvidenceTransientState(graph);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* The local projection is current-format by construction, so every save
|
|
233
|
+
* states the explicit upgrade intent; the server keeps untouched legacy
|
|
234
|
+
* evidence only for clients that cannot retain it.
|
|
235
|
+
*/
|
|
236
|
+
export function prepareProjectionEvidenceForSave(graph) {
|
|
237
|
+
return isEvidenceBoundaryEnabled() ? markEvidenceFormatUpgrade(graph) : graph;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Present only in a scoped projection (workspace attach): the entities it
|
|
241
|
+
* holds. Every other entity is read from the workspace head.
|
|
242
|
+
*/
|
|
243
|
+
export const PROJECTION_MANIFEST_FILE = 'projection.json';
|
|
244
|
+
function emptyProjectionScope() {
|
|
245
|
+
return { node: [], edge: [], path: [], path_relation: [] };
|
|
246
|
+
}
|
|
247
|
+
/** The entities a task scope names, whichever of their fields it covers. */
|
|
248
|
+
export function projectionScopeOfTaskScope(task_scope) {
|
|
249
|
+
const scope = emptyProjectionScope();
|
|
250
|
+
for (const rule of task_scope.rules) {
|
|
251
|
+
if (!ENTITY_KINDS.includes(rule.entity_kind))
|
|
252
|
+
continue;
|
|
253
|
+
scope[rule.entity_kind].push(rule.entity_id);
|
|
254
|
+
}
|
|
255
|
+
return scope;
|
|
256
|
+
}
|
|
257
|
+
function mergeProjectionScopes(...scopes) {
|
|
258
|
+
const merged = emptyProjectionScope();
|
|
259
|
+
for (const kind of ENTITY_KINDS) {
|
|
260
|
+
merged[kind] = [...new Set(scopes.flatMap((scope) => scope[kind]))].sort();
|
|
261
|
+
}
|
|
262
|
+
return merged;
|
|
263
|
+
}
|
|
264
|
+
async function readProjectionManifest(projection_dir, access) {
|
|
265
|
+
// Found by listing, as package-uses.json is: an access may refuse a missing path.
|
|
266
|
+
if (!(await access.exists(projection_dir)))
|
|
267
|
+
return null;
|
|
268
|
+
const present = (await access.entries(projection_dir)).some((entry) => entry.is_file && entry.name === PROJECTION_MANIFEST_FILE);
|
|
269
|
+
if (!present)
|
|
270
|
+
return null;
|
|
271
|
+
const manifest = parseJson(await access.read(join(projection_dir, PROJECTION_MANIFEST_FILE)), PROJECTION_MANIFEST_FILE);
|
|
272
|
+
if (manifest?.version !== 1 ||
|
|
273
|
+
!manifest.scope ||
|
|
274
|
+
ENTITY_KINDS.some((kind) => !Array.isArray(manifest.scope?.[kind]))) {
|
|
275
|
+
throw new Error(`Unsupported ${PROJECTION_MANIFEST_FILE}.`);
|
|
276
|
+
}
|
|
277
|
+
return manifest;
|
|
278
|
+
}
|
|
279
|
+
async function projectionEntityIdsOnDisk(projection_dir) {
|
|
280
|
+
const scope = emptyProjectionScope();
|
|
281
|
+
for (const kind of ENTITY_KINDS) {
|
|
282
|
+
const directory = join(projection_dir, ENTITY_CONFIG[kind].directory);
|
|
283
|
+
if (!(await pathExists(directory)))
|
|
284
|
+
continue;
|
|
285
|
+
scope[kind] = (await readdir(directory))
|
|
286
|
+
.filter((name) => name.endsWith('.json'))
|
|
287
|
+
.map((name) => basename(name, '.json'));
|
|
288
|
+
}
|
|
289
|
+
return scope;
|
|
290
|
+
}
|
|
291
|
+
/** Whether the projection holds only a scope (workspace attach) instead of the whole graph. */
|
|
292
|
+
export async function isScopedProjection(projection_dir) {
|
|
293
|
+
return ((await readProjectionManifest(projection_dir, DEFAULT_READ_ACCESS)) !== null);
|
|
294
|
+
}
|
|
295
|
+
function presentValidatedGraph(input_graph, upgrade_evidence) {
|
|
296
|
+
const graph = presentProjectionEvidence(canonicalizePortableGraph(portable_graph_schema.parse(input_graph)), upgrade_evidence);
|
|
297
|
+
const validation = validateProjectionGraph(graph);
|
|
298
|
+
if (!validation.is_valid) {
|
|
299
|
+
throw new Error(`Remote worktree graph failed local validation: ${validation.issues
|
|
300
|
+
.filter((issue) => issue.status === 'broken')
|
|
301
|
+
.map((issue) => `${issue.code}: ${issue.message}`)
|
|
302
|
+
.join('; ')}`);
|
|
303
|
+
}
|
|
304
|
+
return graph;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Writes the graph's projection. With `scope`, only those entities are
|
|
308
|
+
* written, with tags and package uses, and projection.json lists them. A
|
|
309
|
+
* projection that already holds a scope keeps it, with any entity the
|
|
310
|
+
* projection added, unless `full` asks for the whole graph again.
|
|
311
|
+
*/
|
|
312
|
+
export async function materializeGraphProjection(input) {
|
|
313
|
+
const graph = presentValidatedGraph(input.graph, input.upgrade_evidence === true);
|
|
314
|
+
let scope = input.scope
|
|
315
|
+
? mergeProjectionScopes(input.scope)
|
|
316
|
+
: null;
|
|
317
|
+
if (!scope && !input.full) {
|
|
318
|
+
const existing = await readProjectionManifest(input.projection_dir, DEFAULT_READ_ACCESS);
|
|
319
|
+
if (existing) {
|
|
320
|
+
scope = mergeProjectionScopes(existing.scope, await projectionEntityIdsOnDisk(input.projection_dir));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
input.check?.();
|
|
324
|
+
await mkdir(input.projection_dir, { recursive: true, mode: 0o700 });
|
|
325
|
+
for (const kind of ENTITY_KINDS) {
|
|
326
|
+
input.check?.();
|
|
327
|
+
const selected = scope ? new Set(scope[kind]) : null;
|
|
328
|
+
// The manifest keeps every scoped id, present in the graph or not, so a
|
|
329
|
+
// scoped entity created later still reads from its file, and its
|
|
330
|
+
// deletion as a deletion.
|
|
331
|
+
const entities = graphEntities(graph, kind).filter((entity) => !selected || selected.has(entity.id));
|
|
332
|
+
await materializeEntityKind({
|
|
333
|
+
projection_dir: input.projection_dir,
|
|
334
|
+
kind,
|
|
335
|
+
entities,
|
|
336
|
+
check: input.check
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
if (scope) {
|
|
340
|
+
await writeJsonAtomically(join(input.projection_dir, PROJECTION_MANIFEST_FILE), {
|
|
341
|
+
version: 1,
|
|
342
|
+
scope
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
await rm(join(input.projection_dir, PROJECTION_MANIFEST_FILE), {
|
|
347
|
+
force: true
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
input.check?.();
|
|
351
|
+
await writeJsonAtomically(join(input.projection_dir, 'tags.json'), graph.tags ?? []);
|
|
352
|
+
// Present only while the graph uses a package, as the graph's key is.
|
|
353
|
+
if (graph.package_uses?.length) {
|
|
354
|
+
await writeJsonAtomically(join(input.projection_dir, PACKAGE_USES_FILE), graph.package_uses);
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
await rm(join(input.projection_dir, PACKAGE_USES_FILE), { force: true });
|
|
358
|
+
}
|
|
359
|
+
await mkdir(join(input.projection_dir, 'scratch'), {
|
|
360
|
+
recursive: true,
|
|
361
|
+
mode: 0o700
|
|
362
|
+
});
|
|
363
|
+
return graph;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Adds entities to a scoped projection when its task scope grows: writes the
|
|
367
|
+
* file of each newly scoped entity the graph has and the projection lacks,
|
|
368
|
+
* leaving every existing file, edited or not, as it is.
|
|
369
|
+
*/
|
|
370
|
+
export async function extendScopedProjection(input) {
|
|
371
|
+
const manifest = await readProjectionManifest(input.projection_dir, DEFAULT_READ_ACCESS);
|
|
372
|
+
if (!manifest)
|
|
373
|
+
throw new Error('The projection holds the whole graph.');
|
|
374
|
+
// Presented as materializing writes it, but not validated as a whole: the
|
|
375
|
+
// graph may carry uncommitted edits, which only a commit validates.
|
|
376
|
+
const graph = presentProjectionEvidence(canonicalizePortableGraph(portable_graph_schema.parse(input.graph)), false);
|
|
377
|
+
const on_disk = await projectionEntityIdsOnDisk(input.projection_dir);
|
|
378
|
+
const added = emptyProjectionScope();
|
|
379
|
+
for (const kind of ENTITY_KINDS) {
|
|
380
|
+
// A listed entity whose file is missing was deleted; never restore it.
|
|
381
|
+
const held = new Set([...on_disk[kind], ...manifest.scope[kind]]);
|
|
382
|
+
const wanted = new Set(input.scope[kind]);
|
|
383
|
+
for (const entity of graphEntities(graph, kind)) {
|
|
384
|
+
if (!wanted.has(entity.id) || held.has(entity.id))
|
|
385
|
+
continue;
|
|
386
|
+
await writeJsonAtomically(join(input.projection_dir, entityRelativePath(kind, entity.id)), entity);
|
|
387
|
+
added[kind].push(entity.id);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
// Every newly scoped id is listed, written or not, as materializing lists it.
|
|
391
|
+
await writeJsonAtomically(join(input.projection_dir, PROJECTION_MANIFEST_FILE), {
|
|
392
|
+
version: 1,
|
|
393
|
+
scope: mergeProjectionScopes(manifest.scope, input.scope, on_disk)
|
|
394
|
+
});
|
|
395
|
+
return added;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Lists in a scoped projection's manifest every entity file it holds, so an
|
|
399
|
+
* entity created in the projection and committed reads as deleted, not as
|
|
400
|
+
* the head has it, once its file is removed. A whole projection is left as
|
|
401
|
+
* it is.
|
|
402
|
+
*/
|
|
403
|
+
export async function recordScopedProjectionFiles(projection_dir) {
|
|
404
|
+
const manifest = await readProjectionManifest(projection_dir, DEFAULT_READ_ACCESS);
|
|
405
|
+
if (!manifest)
|
|
406
|
+
return;
|
|
407
|
+
await writeJsonAtomically(join(projection_dir, PROJECTION_MANIFEST_FILE), {
|
|
408
|
+
version: 1,
|
|
409
|
+
scope: mergeProjectionScopes(manifest.scope, await projectionEntityIdsOnDisk(projection_dir))
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
/** Whether a projection.json is present, readable or not. */
|
|
413
|
+
export async function hasProjectionManifest(projection_dir) {
|
|
414
|
+
return pathExists(join(projection_dir, PROJECTION_MANIFEST_FILE));
|
|
415
|
+
}
|
|
416
|
+
const DEFAULT_READ_ACCESS = {
|
|
417
|
+
exists: pathExists,
|
|
418
|
+
read: (path) => readFile(path, 'utf8'),
|
|
419
|
+
entries: async (path) => (await readdir(path, { withFileTypes: true })).map((entry) => ({
|
|
420
|
+
name: entry.name,
|
|
421
|
+
is_file: entry.isFile()
|
|
422
|
+
}))
|
|
423
|
+
};
|
|
424
|
+
async function readProjectionEntities(input) {
|
|
425
|
+
const config = ENTITY_CONFIG[input.kind];
|
|
426
|
+
const directory = join(input.projection_dir, config.directory);
|
|
427
|
+
if (!(await input.access.exists(directory))) {
|
|
428
|
+
throw new Error(`Managed projection directory is missing: ${config.directory}`);
|
|
429
|
+
}
|
|
430
|
+
const entries = await input.access.entries(directory);
|
|
431
|
+
if (entries.some((entry) => !entry.is_file || !entry.name.endsWith('.json')))
|
|
432
|
+
throw new Error('Unsupported projection entry.');
|
|
433
|
+
const entities = [];
|
|
434
|
+
const errors = [];
|
|
435
|
+
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
436
|
+
const id = basename(entry.name, '.json');
|
|
437
|
+
if (!UUID_PATTERN.test(id)) {
|
|
438
|
+
throw new Error(`Projection filename must be a stable UUID: ${entry.name}`);
|
|
439
|
+
}
|
|
440
|
+
const relative_path = entityRelativePath(input.kind, id);
|
|
441
|
+
const fileError = (field_path, message) => errors.push({
|
|
442
|
+
entity_kind: input.kind,
|
|
443
|
+
entity_id: id,
|
|
444
|
+
relative_path,
|
|
445
|
+
field_path,
|
|
446
|
+
message
|
|
447
|
+
});
|
|
448
|
+
let value;
|
|
449
|
+
try {
|
|
450
|
+
value = parseJson(await input.access.read(join(directory, entry.name)), relative_path);
|
|
451
|
+
}
|
|
452
|
+
catch (error) {
|
|
453
|
+
if (!(error instanceof Error) ||
|
|
454
|
+
!error.message.startsWith('Invalid JSON'))
|
|
455
|
+
throw error;
|
|
456
|
+
fileError('', error.message);
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
const parsed = config.safe_parse(value);
|
|
460
|
+
if (!parsed.success) {
|
|
461
|
+
// The schema can check one field more than once; a field that fails
|
|
462
|
+
// the same way twice is one invalid field.
|
|
463
|
+
const reported = new Set();
|
|
464
|
+
for (const issue of parsed.error.issues) {
|
|
465
|
+
const field_path = issue.path.map(String).join('.');
|
|
466
|
+
const key = JSON.stringify([field_path, issue.message]);
|
|
467
|
+
if (reported.has(key))
|
|
468
|
+
continue;
|
|
469
|
+
reported.add(key);
|
|
470
|
+
fileError(field_path, issue.message);
|
|
471
|
+
}
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
if (parsed.data.id !== id) {
|
|
475
|
+
fileError('id', `Projection entity id ${parsed.data.id} does not match filename ${entry.name}.`);
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
entities.push(parsed.data);
|
|
479
|
+
}
|
|
480
|
+
return { entities, errors };
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Composes the projection's files into one graph. A scoped projection
|
|
484
|
+
* (projection.json) composes only over `base`, its workspace's head: the
|
|
485
|
+
* entities it lists or holds come from their files, a listed entity whose
|
|
486
|
+
* file is gone reads as deleted, and every other entity comes from the base.
|
|
487
|
+
*/
|
|
488
|
+
export async function composeGraphProjection(projection_dir, access = DEFAULT_READ_ACCESS, options = {}) {
|
|
489
|
+
const tags_path = join(projection_dir, 'tags.json');
|
|
490
|
+
if (!(await access.exists(tags_path))) {
|
|
491
|
+
throw new Error('Managed projection tags.json is missing.');
|
|
492
|
+
}
|
|
493
|
+
const manifest = await readProjectionManifest(projection_dir, access);
|
|
494
|
+
if (manifest && !options.base) {
|
|
495
|
+
throw new Error(`This projection holds only its workspace's task scope (${PROJECTION_MANIFEST_FILE}); read it through its workspace, for example sdlc workspace status.`);
|
|
496
|
+
}
|
|
497
|
+
const base = manifest && options.base ? await options.base() : null;
|
|
498
|
+
const entity_results = await Promise.allSettled(ENTITY_KINDS.map((kind) => readProjectionEntities({ projection_dir, kind, access }).then((read) => ({
|
|
499
|
+
kind,
|
|
500
|
+
...read
|
|
501
|
+
}))));
|
|
502
|
+
const entity_groups = entity_results.map((result) => {
|
|
503
|
+
if (result.status === 'rejected')
|
|
504
|
+
throw result.reason;
|
|
505
|
+
return result.value;
|
|
506
|
+
});
|
|
507
|
+
const entity_errors = entity_groups.flatMap((group) => group.errors);
|
|
508
|
+
if (entity_errors.length > 0)
|
|
509
|
+
throw new ProjectionEntityErrors(entity_errors);
|
|
510
|
+
const graph_input = {
|
|
511
|
+
nodes: [],
|
|
512
|
+
edges: [],
|
|
513
|
+
paths: [],
|
|
514
|
+
path_relations: [],
|
|
515
|
+
tags: parseJson(await access.read(tags_path), 'tags.json')
|
|
516
|
+
};
|
|
517
|
+
// The file is optional, so it is found by listing the folder: an access may treat a
|
|
518
|
+
// missing path it is asked about as an incomplete projection (health inspection does).
|
|
519
|
+
const package_uses_path = join(projection_dir, PACKAGE_USES_FILE);
|
|
520
|
+
const has_package_uses = (await access.entries(projection_dir)).some((entry) => entry.is_file && entry.name === PACKAGE_USES_FILE);
|
|
521
|
+
if (has_package_uses) {
|
|
522
|
+
graph_input.package_uses = parseJson(await access.read(package_uses_path), PACKAGE_USES_FILE);
|
|
523
|
+
}
|
|
524
|
+
for (const group of entity_groups) {
|
|
525
|
+
if (manifest && base) {
|
|
526
|
+
const held = new Set([
|
|
527
|
+
...manifest.scope[group.kind],
|
|
528
|
+
...group.entities.map((entity) => entity.id)
|
|
529
|
+
]);
|
|
530
|
+
group.entities = [
|
|
531
|
+
...graphEntities(base, group.kind).filter((entity) => !held.has(entity.id)),
|
|
532
|
+
...group.entities
|
|
533
|
+
];
|
|
534
|
+
}
|
|
535
|
+
if (group.kind === 'node')
|
|
536
|
+
graph_input.nodes = group.entities;
|
|
537
|
+
if (group.kind === 'edge')
|
|
538
|
+
graph_input.edges = group.entities;
|
|
539
|
+
if (group.kind === 'path')
|
|
540
|
+
graph_input.paths = group.entities;
|
|
541
|
+
if (group.kind === 'path_relation') {
|
|
542
|
+
graph_input.path_relations =
|
|
543
|
+
group.entities;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
const graph = canonicalizePortableGraph(portable_graph_schema.parse({
|
|
547
|
+
...graph_input,
|
|
548
|
+
nodes: graph_input.nodes.map((node) => ({
|
|
549
|
+
...node,
|
|
550
|
+
data: {
|
|
551
|
+
...node.data,
|
|
552
|
+
meta: withoutWorktreeBuildOverride(node.data.meta)
|
|
553
|
+
}
|
|
554
|
+
}))
|
|
555
|
+
}));
|
|
556
|
+
const graph_json = stringifyCanonicalGraph(graph);
|
|
557
|
+
return {
|
|
558
|
+
graph,
|
|
559
|
+
graph_json,
|
|
560
|
+
graph_hash: createHash('sha256').update(graph_json).digest('hex')
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* With `node_parents`, every node's parent is checked as a hosted apply of the
|
|
565
|
+
* whole graph checks it; local workspace commits ask for it, while a graph
|
|
566
|
+
* pulled from or bound to a hosted branch keeps the hosted save's rules.
|
|
567
|
+
*/
|
|
568
|
+
export function validateProjectionGraph(graph, options = {}) {
|
|
569
|
+
const validation = validateBuiltGraph(graph, { id_policy: 'uuid', node_parents: options.node_parents });
|
|
570
|
+
return { is_valid: validation.is_valid, issues: validation.issues };
|
|
571
|
+
}
|
|
572
|
+
function entityMap(graph, kind) {
|
|
573
|
+
return new Map(graphEntities(graph, kind).map((entity) => [entity.id, entity]));
|
|
574
|
+
}
|
|
575
|
+
export function graphHasProjectionEntity(graph, intent) {
|
|
576
|
+
return entityMap(graph, intent.entity_kind).has(intent.entity_id);
|
|
577
|
+
}
|
|
578
|
+
export function restoreMissingProjectionEntities(input) {
|
|
579
|
+
const current_graph = canonicalizePortableGraph(portable_graph_schema.parse(input.current_graph));
|
|
580
|
+
const source_graph = canonicalizePortableGraph(portable_graph_schema.parse(input.source_graph));
|
|
581
|
+
const restored_graph = {
|
|
582
|
+
...current_graph,
|
|
583
|
+
nodes: [...current_graph.nodes],
|
|
584
|
+
edges: [...current_graph.edges],
|
|
585
|
+
paths: [...(current_graph.paths ?? [])],
|
|
586
|
+
path_relations: [...(current_graph.path_relations ?? [])]
|
|
587
|
+
};
|
|
588
|
+
for (const kind of ENTITY_KINDS) {
|
|
589
|
+
const current_entities = entityMap(current_graph, kind);
|
|
590
|
+
const source_entities = entityMap(source_graph, kind);
|
|
591
|
+
for (const entry of input.entries) {
|
|
592
|
+
if (entry.entity_kind !== kind || current_entities.has(entry.entity_id)) {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
const source_entity = source_entities.get(entry.entity_id);
|
|
596
|
+
if (!source_entity) {
|
|
597
|
+
throw new Error(`Recovery source is missing ${entry.entity_kind} ${entry.entity_id}.`);
|
|
598
|
+
}
|
|
599
|
+
current_entities.set(entry.entity_id, source_entity);
|
|
600
|
+
}
|
|
601
|
+
const restored_entities = [...current_entities.values()];
|
|
602
|
+
if (kind === 'node') {
|
|
603
|
+
restored_graph.nodes = restored_entities;
|
|
604
|
+
}
|
|
605
|
+
else if (kind === 'edge') {
|
|
606
|
+
restored_graph.edges = restored_entities;
|
|
607
|
+
}
|
|
608
|
+
else if (kind === 'path') {
|
|
609
|
+
restored_graph.paths = restored_entities;
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
restored_graph.path_relations =
|
|
613
|
+
restored_entities;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return canonicalizePortableGraph(portable_graph_schema.parse(restored_graph));
|
|
617
|
+
}
|
|
618
|
+
function deletionKey(intent) {
|
|
619
|
+
return `${intent.entity_kind}:${intent.entity_id}`;
|
|
620
|
+
}
|
|
621
|
+
export function diffProjectionGraphs(input) {
|
|
622
|
+
// The decode marker is in-memory state, never a projection change.
|
|
623
|
+
const semantic_diff = diffPortableGraphs({
|
|
624
|
+
...input,
|
|
625
|
+
base_graph: withoutGraphEvidenceTransientState(storedGraphEvidence(input.base_graph)),
|
|
626
|
+
current_graph: withoutGraphEvidenceTransientState(input.current_graph)
|
|
627
|
+
});
|
|
628
|
+
const deleted = [];
|
|
629
|
+
const missing_unrecorded = [];
|
|
630
|
+
const deletion_keys = new Set((input.deletion_intents ?? []).map(deletionKey));
|
|
631
|
+
const projectionEntry = (entry) => ({
|
|
632
|
+
...entry,
|
|
633
|
+
relative_path: entityRelativePath(entry.entity_kind, entry.entity_id)
|
|
634
|
+
});
|
|
635
|
+
for (const semantic_entry of semantic_diff.deleted) {
|
|
636
|
+
const entry = projectionEntry(semantic_entry);
|
|
637
|
+
if (deletion_keys.has(deletionKey(entry)))
|
|
638
|
+
deleted.push(entry);
|
|
639
|
+
else
|
|
640
|
+
missing_unrecorded.push(entry);
|
|
641
|
+
}
|
|
642
|
+
const sort_entries = (entries) => entries.sort((left, right) => left.relative_path.localeCompare(right.relative_path));
|
|
643
|
+
return {
|
|
644
|
+
added: sort_entries(semantic_diff.added.map(projectionEntry)),
|
|
645
|
+
modified: sort_entries(semantic_diff.modified.map(projectionEntry)),
|
|
646
|
+
deleted: sort_entries(deleted),
|
|
647
|
+
missing_unrecorded: sort_entries(missing_unrecorded),
|
|
648
|
+
tags_changed: semantic_diff.tags_changed,
|
|
649
|
+
...(semantic_diff.package_uses_changed
|
|
650
|
+
? { package_uses_changed: true }
|
|
651
|
+
: {})
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
export function projectionDiffHasChanges(diff) {
|
|
655
|
+
return (diff.added.length > 0 ||
|
|
656
|
+
diff.modified.length > 0 ||
|
|
657
|
+
diff.deleted.length > 0 ||
|
|
658
|
+
diff.missing_unrecorded.length > 0 ||
|
|
659
|
+
diff.tags_changed ||
|
|
660
|
+
diff.package_uses_changed === true);
|
|
661
|
+
}
|
|
662
|
+
export function parseProjectionEntityPath(input) {
|
|
663
|
+
if (isAbsolute(input.path)) {
|
|
664
|
+
throw new Error('Projection entity path must be relative to sdlc/.');
|
|
665
|
+
}
|
|
666
|
+
const normalized = input.path.split('/').join(sep);
|
|
667
|
+
const absolute_path = join(input.projection_dir, normalized);
|
|
668
|
+
const relative_path = relative(input.projection_dir, absolute_path)
|
|
669
|
+
.split(sep)
|
|
670
|
+
.join('/');
|
|
671
|
+
if (relative_path.startsWith('../') || relative_path === '..') {
|
|
672
|
+
throw new Error('Projection entity path must stay inside sdlc/.');
|
|
673
|
+
}
|
|
674
|
+
for (const kind of ENTITY_KINDS) {
|
|
675
|
+
const match = relative_path.match(new RegExp(`^${ENTITY_CONFIG[kind].directory}/([0-9a-f-]+)\\.json$`, 'i'));
|
|
676
|
+
if (!match)
|
|
677
|
+
continue;
|
|
678
|
+
const entity_id = match[1] ?? '';
|
|
679
|
+
if (!UUID_PATTERN.test(entity_id)) {
|
|
680
|
+
throw new Error('Projection entity path must use a stable UUID filename.');
|
|
681
|
+
}
|
|
682
|
+
return { entity_kind: kind, entity_id, relative_path };
|
|
683
|
+
}
|
|
684
|
+
throw new Error('Projection entity path must identify a JSON file under nodes, edges, paths, or path-relations.');
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Removes one entity file. A file already deleted by hand is accepted when
|
|
688
|
+
* the projection holds its entity (a scoped projection holds only its
|
|
689
|
+
* manifest's scope; compose fills the rest from the base) and `allow_missing`
|
|
690
|
+
* says the entity is still in the base, so the caller can record the deletion
|
|
691
|
+
* the commit or save asks for.
|
|
692
|
+
*/
|
|
693
|
+
export async function removeProjectionEntity(input) {
|
|
694
|
+
const entry = parseProjectionEntityPath({
|
|
695
|
+
projection_dir: input.projection_dir,
|
|
696
|
+
path: input.relative_path
|
|
697
|
+
});
|
|
698
|
+
const path = join(input.projection_dir, entry.relative_path);
|
|
699
|
+
if (!(await pathExists(path))) {
|
|
700
|
+
const manifest = await readProjectionManifest(input.projection_dir, DEFAULT_READ_ACCESS);
|
|
701
|
+
const held = !manifest || manifest.scope[entry.entity_kind].includes(entry.entity_id);
|
|
702
|
+
if (held && input.allow_missing?.(entry))
|
|
703
|
+
return entry;
|
|
704
|
+
throw new Error(`Projection entity does not exist: ${entry.relative_path}`);
|
|
705
|
+
}
|
|
706
|
+
await rm(path);
|
|
707
|
+
return entry;
|
|
708
|
+
}
|
|
709
|
+
//# sourceMappingURL=projection.js.map
|