@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,855 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { accountablePerson, checkBinding, checkHold, checkRelease, escalate, gateBoundPosts, governingPosts, mayGovern, positionLines, readOrgStructure, reportingLine, resolveSlot, resolveSlots, slotBinding, slotBindings } from '@software-dlc/graph/computation';
|
|
6
|
+
import { validateGovernanceNodes } from '@software-dlc/graph/validator';
|
|
7
|
+
import { gitCommonDir, locateRepository } from './app-shell-readers.js';
|
|
8
|
+
import { LocalWorkspaceGraphStore, resolveLocalRepositoryStateDirectory } from './workspace-graph-store.js';
|
|
9
|
+
import { LocalWorkspaceStore } from './workspace-store.js';
|
|
10
|
+
/**
|
|
11
|
+
* The local org (org-structure-and-access.md, Local org without an org
|
|
12
|
+
* connection; osa-local-org): a workspace with no org connection plans a
|
|
13
|
+
* theoretical org whose posts its local person and local agents hold. Its
|
|
14
|
+
* definitions are a governance graph in the repository store, never a project
|
|
15
|
+
* graph, and its holders are rows beside it (local-org-store.ts). Every
|
|
16
|
+
* answer comes from the shared resolution in @software-dlc/graph/computation,
|
|
17
|
+
* so local and hosted orgs cannot disagree.
|
|
18
|
+
*/
|
|
19
|
+
/** The local Home's pseudo-org id (app-shell-readers.ts); one local org per repository store. */
|
|
20
|
+
export const LOCAL_ORG_ID = 'local';
|
|
21
|
+
/** The person running locally, as workflow.json names them. */
|
|
22
|
+
export const LOCAL_PERSON = { id: 'user', kind: 'person' };
|
|
23
|
+
const KEY = /^[a-z][a-z0-9_-]{0,63}$/;
|
|
24
|
+
const MEMBER_ID = /^[a-z][a-z0-9_-]{0,63}$/;
|
|
25
|
+
function isRecord(value) {
|
|
26
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
27
|
+
}
|
|
28
|
+
/** The roles, holders and gates of a workflow.json (scripts/agent-coordination/workflow.json). */
|
|
29
|
+
export function parseWorkflowRoles(value) {
|
|
30
|
+
if (!isRecord(value) || !Array.isArray(value.roles)) {
|
|
31
|
+
throw new Error('The workflow has no roles list.');
|
|
32
|
+
}
|
|
33
|
+
const roles = value.roles.map((role) => {
|
|
34
|
+
if (!isRecord(role) ||
|
|
35
|
+
typeof role.key !== 'string' ||
|
|
36
|
+
!KEY.test(role.key)) {
|
|
37
|
+
throw new Error(`The workflow role ${JSON.stringify(role)} has no valid key.`);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
key: role.key,
|
|
41
|
+
name: typeof role.name === 'string' && role.name.trim()
|
|
42
|
+
? role.name
|
|
43
|
+
: role.key,
|
|
44
|
+
...(typeof role.description === 'string'
|
|
45
|
+
? { description: role.description }
|
|
46
|
+
: {})
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
const holders = {};
|
|
50
|
+
const holder_kinds = {};
|
|
51
|
+
if (isRecord(value.holders)) {
|
|
52
|
+
for (const [role, list] of Object.entries(value.holders)) {
|
|
53
|
+
if (!Array.isArray(list))
|
|
54
|
+
continue;
|
|
55
|
+
holder_kinds[role] = list.flatMap((holder) => isRecord(holder) && typeof holder.kind === 'string' ? [holder.kind] : []);
|
|
56
|
+
holders[role] = list.flatMap((holder) => isRecord(holder) &&
|
|
57
|
+
(holder.kind === 'person' || holder.kind === 'agent') &&
|
|
58
|
+
typeof holder.id === 'string'
|
|
59
|
+
? [{ id: holder.id, kind: holder.kind }]
|
|
60
|
+
: []);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const gates = (Array.isArray(value.phases) ? value.phases : []).flatMap((phase) => isRecord(phase) && Array.isArray(phase.gates)
|
|
64
|
+
? phase.gates.flatMap((gate) => isRecord(gate) &&
|
|
65
|
+
typeof gate.gate === 'string' &&
|
|
66
|
+
typeof gate.role === 'string'
|
|
67
|
+
? [{ gate: gate.gate, role: gate.role }]
|
|
68
|
+
: [])
|
|
69
|
+
: []);
|
|
70
|
+
return { roles, holders, holder_kinds, gates };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The roles whose gates need a person: a role that holds a gate and has a
|
|
74
|
+
* holder other than an agent (a person or a team), the rule
|
|
75
|
+
* planning_gate.derive_approvals gives the user a gate by.
|
|
76
|
+
*/
|
|
77
|
+
export function personGateRoles(workflow) {
|
|
78
|
+
return new Set(workflow.gates
|
|
79
|
+
.map((gate) => gate.role)
|
|
80
|
+
.filter((role) => (workflow.holder_kinds[role] ?? []).some((kind) => kind !== 'agent')));
|
|
81
|
+
}
|
|
82
|
+
/** A role held only by people or teams, whose seeded function requires a person. */
|
|
83
|
+
function heldByPeopleOnly(workflow, role) {
|
|
84
|
+
const kinds = workflow.holder_kinds[role] ?? [];
|
|
85
|
+
return kinds.length > 0 && kinds.every((kind) => kind !== 'agent');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The holder rules a local org checks: the gate slots are the slots keyed by
|
|
89
|
+
* a person-gate role, and the posts the project's overrides bind to one
|
|
90
|
+
* decide that gate too (osa_slots_ac_4).
|
|
91
|
+
*/
|
|
92
|
+
export function localOrgRules(graph, workflow, overrides = []) {
|
|
93
|
+
const roles = workflow ? personGateRoles(workflow) : new Set();
|
|
94
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
95
|
+
const gate_slot_ids = new Set([...structure.slots.values()]
|
|
96
|
+
.filter((slot) => roles.has(slot.key))
|
|
97
|
+
.map((slot) => slot.id));
|
|
98
|
+
const gate_post_ids = gateBoundPosts(overrides, { gate_slot_ids });
|
|
99
|
+
return gate_post_ids.size
|
|
100
|
+
? { gate_slot_ids, gate_post_ids }
|
|
101
|
+
: { gate_slot_ids };
|
|
102
|
+
}
|
|
103
|
+
/** A governance key made from a name: lowercase, dashes for other characters, starting with a letter. */
|
|
104
|
+
export function keyFromName(name) {
|
|
105
|
+
const key = name
|
|
106
|
+
.toLowerCase()
|
|
107
|
+
.replace(/[^a-z0-9_-]+/g, '-')
|
|
108
|
+
.replace(/^[^a-z]+/, '')
|
|
109
|
+
.replace(/-+$/, '')
|
|
110
|
+
.slice(0, 64);
|
|
111
|
+
return KEY.test(key) ? key : 'org';
|
|
112
|
+
}
|
|
113
|
+
function definitionNode(type, input, data = {}) {
|
|
114
|
+
return {
|
|
115
|
+
id: randomUUID(),
|
|
116
|
+
type,
|
|
117
|
+
...(input.parent_id ? { parentId: input.parent_id } : {}),
|
|
118
|
+
data: {
|
|
119
|
+
data: {
|
|
120
|
+
label: input.label,
|
|
121
|
+
...(input.description ? { description: input.description } : {}),
|
|
122
|
+
[type]: { key: input.key, ...data }
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function relationship(source, target, type) {
|
|
128
|
+
return {
|
|
129
|
+
id: randomUUID(),
|
|
130
|
+
source,
|
|
131
|
+
target,
|
|
132
|
+
data: { data: { type } }
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function keyOf(node) {
|
|
136
|
+
const domain = node.data
|
|
137
|
+
?.data;
|
|
138
|
+
const data = domain?.[node.type];
|
|
139
|
+
return isRecord(data) && typeof data.key === 'string' ? data.key : undefined;
|
|
140
|
+
}
|
|
141
|
+
function labelOf(node) {
|
|
142
|
+
const label = node?.data?.data
|
|
143
|
+
?.label;
|
|
144
|
+
return typeof label === 'string' ? label : '';
|
|
145
|
+
}
|
|
146
|
+
function findByKey(graph, type, key) {
|
|
147
|
+
return graph.nodes.find((node) => node.type === type && keyOf(node) === key);
|
|
148
|
+
}
|
|
149
|
+
const NOUN = {
|
|
150
|
+
team: 'team',
|
|
151
|
+
job_function: 'job function',
|
|
152
|
+
slot: 'slot'
|
|
153
|
+
};
|
|
154
|
+
function requireByKey(graph, type, key) {
|
|
155
|
+
const node = findByKey(graph, type, key);
|
|
156
|
+
if (!node)
|
|
157
|
+
throw new Error(`The local org has no ${NOUN[type]} ${key}.`);
|
|
158
|
+
return node;
|
|
159
|
+
}
|
|
160
|
+
/** Refuses a graph the governance validator reports broken, naming each problem. */
|
|
161
|
+
function checked(graph) {
|
|
162
|
+
const broken = validateGovernanceNodes(graph.nodes, graph.edges).filter((issue) => issue.status === 'broken');
|
|
163
|
+
if (broken.length) {
|
|
164
|
+
throw new Error(`The local org would be invalid: ${broken.map((issue) => issue.message).join('; ')}.`);
|
|
165
|
+
}
|
|
166
|
+
return graph;
|
|
167
|
+
}
|
|
168
|
+
function withDefinition(graph, type, key, build) {
|
|
169
|
+
if (!KEY.test(key)) {
|
|
170
|
+
throw new Error(`${key} is not a key: use lowercase letters, digits, _ and -, starting with a letter.`);
|
|
171
|
+
}
|
|
172
|
+
if (findByKey(graph, type, key))
|
|
173
|
+
throw new Error(`The local org already has a ${NOUN[type]} ${key}.`);
|
|
174
|
+
const added = build();
|
|
175
|
+
return checked({
|
|
176
|
+
...graph,
|
|
177
|
+
nodes: [...graph.nodes, ...added.nodes],
|
|
178
|
+
edges: [...graph.edges, ...added.edges]
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
export function addTeam(graph, input) {
|
|
182
|
+
return withDefinition(graph, 'team', input.key, () => {
|
|
183
|
+
const parent_id = input.parent
|
|
184
|
+
? requireByKey(graph, 'team', input.parent).id
|
|
185
|
+
: undefined;
|
|
186
|
+
return {
|
|
187
|
+
nodes: [
|
|
188
|
+
definitionNode('team', {
|
|
189
|
+
...input,
|
|
190
|
+
label: input.label ?? input.key,
|
|
191
|
+
parent_id
|
|
192
|
+
})
|
|
193
|
+
],
|
|
194
|
+
edges: []
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
export function addJobFunction(graph, input) {
|
|
199
|
+
return withDefinition(graph, 'job_function', input.key, () => {
|
|
200
|
+
const parent_id = input.parent
|
|
201
|
+
? requireByKey(graph, 'job_function', input.parent).id
|
|
202
|
+
: undefined;
|
|
203
|
+
const slots = [...new Set(input.fills ?? [])].map((key) => requireByKey(graph, 'slot', key));
|
|
204
|
+
const node = definitionNode('job_function', { ...input, label: input.label ?? input.key, parent_id }, {
|
|
205
|
+
...(input.requires_person ? { requires_person: true } : {}),
|
|
206
|
+
...(input.escalable === false ? { escalable: false } : {})
|
|
207
|
+
});
|
|
208
|
+
return {
|
|
209
|
+
nodes: [node],
|
|
210
|
+
edges: slots.map((slot) => relationship(node.id, slot.id, 'fills'))
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
export function addSlot(graph, input) {
|
|
215
|
+
return withDefinition(graph, 'slot', input.key, () => ({
|
|
216
|
+
nodes: [
|
|
217
|
+
definitionNode('slot', { ...input, label: input.label ?? input.key })
|
|
218
|
+
],
|
|
219
|
+
edges: []
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
/** A post's name: its team's key and its job function's key, `team/function`. */
|
|
223
|
+
export function postName(graph, structure, post_id) {
|
|
224
|
+
const post = structure.posts.get(post_id);
|
|
225
|
+
if (!post)
|
|
226
|
+
return post_id;
|
|
227
|
+
return `${structure.teams.get(post.team_id)?.key}/${structure.functions.get(post.function_id)?.key}`;
|
|
228
|
+
}
|
|
229
|
+
function splitPostName(name) {
|
|
230
|
+
const parts = name.split('/');
|
|
231
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
232
|
+
throw new Error(`${name} is not a post: name it <team>/<function>.`);
|
|
233
|
+
}
|
|
234
|
+
return [parts[0], parts[1]];
|
|
235
|
+
}
|
|
236
|
+
/** The post a name means; an unknown team, function or post is refused. */
|
|
237
|
+
export function postIdOf(graph, structure, name) {
|
|
238
|
+
const [team_key, function_key] = splitPostName(name);
|
|
239
|
+
const team = requireByKey(graph, 'team', team_key);
|
|
240
|
+
const job = requireByKey(graph, 'job_function', function_key);
|
|
241
|
+
const post = [...structure.posts.values()].find((entry) => entry.team_id === team.id && entry.function_id === job.id);
|
|
242
|
+
if (!post)
|
|
243
|
+
throw new Error(`The local org has no post ${name}: add it with sdlc org add post ${name}.`);
|
|
244
|
+
return post.id;
|
|
245
|
+
}
|
|
246
|
+
export function addPost(graph, input) {
|
|
247
|
+
const [team_key, function_key] = splitPostName(input.name);
|
|
248
|
+
const team = requireByKey(graph, 'team', team_key);
|
|
249
|
+
const job = requireByKey(graph, 'job_function', function_key);
|
|
250
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
251
|
+
if ([...structure.posts.values()].some((post) => post.team_id === team.id && post.function_id === job.id)) {
|
|
252
|
+
throw new Error(`The local org already has a post ${input.name}.`);
|
|
253
|
+
}
|
|
254
|
+
const node = {
|
|
255
|
+
id: randomUUID(),
|
|
256
|
+
type: 'post',
|
|
257
|
+
parentId: team.id,
|
|
258
|
+
data: {
|
|
259
|
+
data: { label: input.label ?? `${labelOf(job)} (${labelOf(team)})` }
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
return checked({
|
|
263
|
+
...graph,
|
|
264
|
+
nodes: [...graph.nodes, node],
|
|
265
|
+
edges: [...graph.edges, relationship(node.id, job.id, 'instantiates')]
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function emptyGraph() {
|
|
269
|
+
return {
|
|
270
|
+
nodes: [],
|
|
271
|
+
edges: [],
|
|
272
|
+
tags: [],
|
|
273
|
+
paths: [],
|
|
274
|
+
path_relations: []
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
function refusalText(graph, structure, post_id, refusal) {
|
|
278
|
+
const name = postName(graph, structure, post_id);
|
|
279
|
+
if (refusal === 'person_required')
|
|
280
|
+
return `${name} needs a person: its job function requires one`;
|
|
281
|
+
if (refusal === 'gate_needs_person')
|
|
282
|
+
return `${name} decides a gate, so a person must hold it beside any agent`;
|
|
283
|
+
return `${name} already has a holder: a post with reports has one holder per team`;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Throws, naming each reason, unless `member` may take the post: the shared
|
|
287
|
+
* holder rules, and one id per member across people and agents.
|
|
288
|
+
*/
|
|
289
|
+
export function assertMayHold(graph, holders, post_id, member, rules) {
|
|
290
|
+
if (!MEMBER_ID.test(member.id)) {
|
|
291
|
+
throw new Error(`${member.id} is not a member id: use lowercase letters, digits, _ and -, starting with a letter.`);
|
|
292
|
+
}
|
|
293
|
+
const other = holders.find((holder) => holder.member.id === member.id && holder.member.kind !== member.kind);
|
|
294
|
+
if (other) {
|
|
295
|
+
throw new Error(`${member.id} already holds a post as ${other.member.kind === 'person' ? 'a person' : 'an agent'}.`);
|
|
296
|
+
}
|
|
297
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
298
|
+
const refusals = checkHold(structure, holders, post_id, member, rules);
|
|
299
|
+
if (refusals.length) {
|
|
300
|
+
throw new Error(`Refused: ${refusals.map((refusal) => refusalText(graph, structure, post_id, refusal)).join('; ')}.`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
export function assertMayRelease(graph, holders, post_id, member, rules) {
|
|
304
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
305
|
+
if (!holders.some((holder) => holder.post_id === post_id &&
|
|
306
|
+
holder.member.id === member.id &&
|
|
307
|
+
holder.member.kind === member.kind)) {
|
|
308
|
+
throw new Error(`${member.id} does not hold ${postName(graph, structure, post_id)}.`);
|
|
309
|
+
}
|
|
310
|
+
const refusals = checkRelease(structure, holders, post_id, member.id, rules);
|
|
311
|
+
if (refusals.length) {
|
|
312
|
+
throw new Error(`Refused: ${refusals.map((refusal) => refusalText(graph, structure, post_id, refusal)).join('; ')}.`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Throws, naming each post, when a post whose function has child functions
|
|
317
|
+
* has more than one holder: a graph edit, not only a hold, can make one so.
|
|
318
|
+
*/
|
|
319
|
+
export function assertOneHolderWithReports(graph, holders) {
|
|
320
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
321
|
+
const parents = new Set([...structure.functions.values()].flatMap((job) => job.parent_id ? [job.parent_id] : []));
|
|
322
|
+
const crowded = [...structure.posts.values()].filter((post) => parents.has(post.function_id) &&
|
|
323
|
+
new Set(holders
|
|
324
|
+
.filter((holder) => holder.post_id === post.id)
|
|
325
|
+
.map((holder) => `${holder.member.kind}:${holder.member.id}`)).size > 1);
|
|
326
|
+
if (crowded.length) {
|
|
327
|
+
throw new Error(`Refused: a post with reports has one holder per team, and ${crowded
|
|
328
|
+
.map((post) => postName(graph, structure, post.id))
|
|
329
|
+
.join(', ')} would have reports with several holders; release all but one first.`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/** The seeded org's top job function, which the local person holds. */
|
|
333
|
+
export const ORG_LEAD = 'org-lead';
|
|
334
|
+
/**
|
|
335
|
+
* A local org planned from a workflow's roles (osa_local_ac_1): a root team
|
|
336
|
+
* named for the org; an org lead function, held by the local person, so each
|
|
337
|
+
* agent's line reaches a person (OSA-07); for each role a slot and a job
|
|
338
|
+
* function filling it under the org lead, with a post in the root team; and
|
|
339
|
+
* the workflow's people and agents holding those posts. A role held only by
|
|
340
|
+
* people or teams seeds a function that requires a person.
|
|
341
|
+
*/
|
|
342
|
+
export function seedLocalOrg(workflow, org, held_since = new Date().toISOString()) {
|
|
343
|
+
if (workflow.roles.some((role) => role.key === ORG_LEAD)) {
|
|
344
|
+
throw new Error(`The workflow has a role ${ORG_LEAD}, which the seed keeps for the org's top function; rename it to seed.`);
|
|
345
|
+
}
|
|
346
|
+
const team = keyFromName(org.name);
|
|
347
|
+
let graph = addTeam(emptyGraph(), { key: team, label: org.name });
|
|
348
|
+
graph = addJobFunction(graph, {
|
|
349
|
+
key: ORG_LEAD,
|
|
350
|
+
label: 'Org lead',
|
|
351
|
+
description: 'Accountable for the local org; every role reports here.',
|
|
352
|
+
requires_person: true
|
|
353
|
+
});
|
|
354
|
+
graph = addPost(graph, { name: `${team}/${ORG_LEAD}` });
|
|
355
|
+
for (const role of workflow.roles) {
|
|
356
|
+
graph = addSlot(graph, {
|
|
357
|
+
key: role.key,
|
|
358
|
+
label: role.name,
|
|
359
|
+
description: role.description
|
|
360
|
+
});
|
|
361
|
+
graph = addJobFunction(graph, {
|
|
362
|
+
key: role.key,
|
|
363
|
+
label: role.name,
|
|
364
|
+
description: role.description,
|
|
365
|
+
parent: ORG_LEAD,
|
|
366
|
+
fills: [role.key],
|
|
367
|
+
requires_person: heldByPeopleOnly(workflow, role.key)
|
|
368
|
+
});
|
|
369
|
+
graph = addPost(graph, { name: `${team}/${role.key}` });
|
|
370
|
+
}
|
|
371
|
+
const rules = localOrgRules(graph, workflow);
|
|
372
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
373
|
+
const holders = [
|
|
374
|
+
{
|
|
375
|
+
post_id: postIdOf(graph, structure, `${team}/${ORG_LEAD}`),
|
|
376
|
+
member: LOCAL_PERSON,
|
|
377
|
+
held_since
|
|
378
|
+
}
|
|
379
|
+
];
|
|
380
|
+
// People first, so a gate post an agent shares already has its person.
|
|
381
|
+
for (const kind of ['person', 'agent']) {
|
|
382
|
+
for (const role of workflow.roles) {
|
|
383
|
+
const post_id = postIdOf(graph, structure, `${team}/${role.key}`);
|
|
384
|
+
for (const member of workflow.holders[role.key] ?? []) {
|
|
385
|
+
if (member.kind !== kind)
|
|
386
|
+
continue;
|
|
387
|
+
if (holders.some((holder) => holder.post_id === post_id && holder.member.id === member.id))
|
|
388
|
+
continue;
|
|
389
|
+
assertMayHold(graph, holders, post_id, member, rules);
|
|
390
|
+
holders.push({ post_id, member, held_since });
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return { graph, holders };
|
|
395
|
+
}
|
|
396
|
+
function lineName(graph, structure, line) {
|
|
397
|
+
if (line.kind === 'top')
|
|
398
|
+
return 'top';
|
|
399
|
+
if (line.kind === 'post')
|
|
400
|
+
return postName(graph, structure, line.post_id);
|
|
401
|
+
return {
|
|
402
|
+
vacant: structure.functions.get(line.function_id)?.key ?? line.function_id
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function slotSummary(graph, structure, resolution) {
|
|
406
|
+
const slot = structure.slots.get(resolution.slot_id)?.key ?? resolution.slot_id;
|
|
407
|
+
if (resolution.status === 'uncovered')
|
|
408
|
+
return { slot, status: resolution.status };
|
|
409
|
+
if (resolution.status === 'vacant') {
|
|
410
|
+
return {
|
|
411
|
+
slot,
|
|
412
|
+
status: resolution.status,
|
|
413
|
+
posts: resolution.post_ids.map((id) => postName(graph, structure, id))
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
return {
|
|
417
|
+
slot,
|
|
418
|
+
status: resolution.status,
|
|
419
|
+
posts: resolution.posts.map((entry) => ({
|
|
420
|
+
post: postName(graph, structure, entry.post_id),
|
|
421
|
+
holders: entry.holders
|
|
422
|
+
})),
|
|
423
|
+
...(resolution.needs_person ? { needs_person: true } : {})
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
/** How each slot resolves (osa_local_ac_3), or one slot by key; an unknown slot or team is refused. */
|
|
427
|
+
export function resolveLocalSlots(graph, holders, rules, input = {}) {
|
|
428
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
429
|
+
const team_id = input.team
|
|
430
|
+
? requireByKey(graph, 'team', input.team).id
|
|
431
|
+
: undefined;
|
|
432
|
+
const resolutions = input.slot
|
|
433
|
+
? [
|
|
434
|
+
resolveSlot(structure, holders, requireByKey(graph, 'slot', input.slot).id, team_id, rules)
|
|
435
|
+
]
|
|
436
|
+
: resolveSlots(structure, holders, team_id, rules);
|
|
437
|
+
return resolutions.map((resolution) => slotSummary(graph, structure, resolution));
|
|
438
|
+
}
|
|
439
|
+
/** The whole local org: definitions, posts with their holders and lines, members' positions, and slots. */
|
|
440
|
+
export function describeLocalOrg(graph, holders, rules) {
|
|
441
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
442
|
+
const nodes = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
443
|
+
const keyFor = (id) => id ? (keyOf(nodes.get(id)) ?? id) : null;
|
|
444
|
+
const members = new Map();
|
|
445
|
+
for (const holder of holders)
|
|
446
|
+
members.set(`${holder.member.kind}:${holder.member.id}`, holder.member);
|
|
447
|
+
return {
|
|
448
|
+
teams: [...structure.teams.values()].map((team) => ({
|
|
449
|
+
key: team.key,
|
|
450
|
+
label: labelOf(nodes.get(team.id)),
|
|
451
|
+
parent: keyFor(team.parent_id)
|
|
452
|
+
})),
|
|
453
|
+
job_functions: [...structure.functions.values()].map((job) => ({
|
|
454
|
+
key: job.key,
|
|
455
|
+
label: labelOf(nodes.get(job.id)),
|
|
456
|
+
parent: keyFor(job.parent_id),
|
|
457
|
+
fills: job.fills.map((id) => structure.slots.get(id)?.key ?? id),
|
|
458
|
+
requires_person: job.requires_person,
|
|
459
|
+
escalable: job.escalable
|
|
460
|
+
})),
|
|
461
|
+
slots: [...structure.slots.values()].map((slot) => ({
|
|
462
|
+
key: slot.key,
|
|
463
|
+
label: labelOf(nodes.get(slot.id)),
|
|
464
|
+
gate: rules.gate_slot_ids?.has(slot.id) ?? false
|
|
465
|
+
})),
|
|
466
|
+
posts: [...structure.posts.values()].map((post) => ({
|
|
467
|
+
post: postName(graph, structure, post.id),
|
|
468
|
+
label: labelOf(nodes.get(post.id)),
|
|
469
|
+
reports_to: lineName(graph, structure, reportingLine(structure, post.id)),
|
|
470
|
+
holders: holders
|
|
471
|
+
.filter((holder) => holder.post_id === post.id)
|
|
472
|
+
.map((holder) => ({ ...holder.member, held_since: holder.held_since }))
|
|
473
|
+
})),
|
|
474
|
+
members: [...members.values()]
|
|
475
|
+
.sort((a, b) => a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id))
|
|
476
|
+
.map((member) => {
|
|
477
|
+
const own = holders.filter((holder) => holder.member.kind === member.kind);
|
|
478
|
+
const lines = positionLines(structure, own, member.id);
|
|
479
|
+
const accountable = member.kind === 'agent'
|
|
480
|
+
? accountablePerson(structure, holders, member.id)
|
|
481
|
+
: null;
|
|
482
|
+
return {
|
|
483
|
+
...member,
|
|
484
|
+
posts: lines.map((line) => ({
|
|
485
|
+
post: postName(graph, structure, line.post_id),
|
|
486
|
+
reports_to: lineName(graph, structure, line.reports_to),
|
|
487
|
+
primary: line.primary,
|
|
488
|
+
dotted: line.dotted
|
|
489
|
+
})),
|
|
490
|
+
...(member.kind === 'agent'
|
|
491
|
+
? { accountable_person: accountable }
|
|
492
|
+
: {})
|
|
493
|
+
};
|
|
494
|
+
}),
|
|
495
|
+
slot_resolution: resolveSlots(structure, holders, undefined, rules).map((resolution) => slotSummary(graph, structure, resolution))
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
export async function openLocalOrgRepository(input) {
|
|
499
|
+
const common = await gitCommonDir(input.cwd);
|
|
500
|
+
if (!common)
|
|
501
|
+
throw new Error('sdlc org runs in a Git repository.');
|
|
502
|
+
const state_dir = resolveLocalRepositoryStateDirectory({
|
|
503
|
+
git_common_dir: common,
|
|
504
|
+
override: input.state_dir
|
|
505
|
+
});
|
|
506
|
+
const location = await locateRepository(common);
|
|
507
|
+
const checkout = await gitTopLevel(input.cwd);
|
|
508
|
+
const store = await LocalWorkspaceStore.open({
|
|
509
|
+
state_dir,
|
|
510
|
+
git_common_dir: common
|
|
511
|
+
});
|
|
512
|
+
return {
|
|
513
|
+
store,
|
|
514
|
+
graphs: new LocalWorkspaceGraphStore(state_dir),
|
|
515
|
+
name: 'name' in location && location.name ? location.name : 'repository',
|
|
516
|
+
checkout
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
/** The checkout at `cwd`, or null with no work tree (a bare repository, or inside .git). */
|
|
520
|
+
function gitTopLevel(cwd) {
|
|
521
|
+
return new Promise((done) => {
|
|
522
|
+
execFile('git', ['rev-parse', '--show-toplevel'], { cwd, encoding: 'utf8', timeout: 10_000 }, (error, stdout) => done(error ? null : String(stdout).trim() || null));
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
export async function readWorkflowRoles(path) {
|
|
526
|
+
let text;
|
|
527
|
+
try {
|
|
528
|
+
text = await readFile(path, 'utf8');
|
|
529
|
+
}
|
|
530
|
+
catch (error) {
|
|
531
|
+
if (error.code === 'ENOENT')
|
|
532
|
+
return null;
|
|
533
|
+
throw error;
|
|
534
|
+
}
|
|
535
|
+
return parseWorkflowRoles(JSON.parse(text));
|
|
536
|
+
}
|
|
537
|
+
/** Where workflow.json is read by default; null with no work tree, which has no default workflow. */
|
|
538
|
+
export function defaultWorkflowPath(repository) {
|
|
539
|
+
return repository.checkout
|
|
540
|
+
? join(repository.checkout, 'scripts', 'agent-coordination', 'workflow.json')
|
|
541
|
+
: null;
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* The org's graph, holders, and its project's stored owning team and slot
|
|
545
|
+
* overrides, or null when it has no graph yet.
|
|
546
|
+
*/
|
|
547
|
+
export async function readLocalOrg(repository) {
|
|
548
|
+
const root = repository.store.org.root(LOCAL_ORG_ID);
|
|
549
|
+
if (!root)
|
|
550
|
+
return null;
|
|
551
|
+
return {
|
|
552
|
+
root,
|
|
553
|
+
graph: await repository.graphs.readGraph(root),
|
|
554
|
+
holders: repository.store.org.holders(LOCAL_ORG_ID),
|
|
555
|
+
project_team: repository.store.org.projectTeam(LOCAL_ORG_ID),
|
|
556
|
+
overrides: repository.store.org.overrides(LOCAL_ORG_ID)
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
const NO_ORG = 'This repository has no local org yet: plan one with sdlc org seed, or start one with sdlc org add team <key>.';
|
|
560
|
+
/**
|
|
561
|
+
* Changes the org's graph: writes the new graph object, then moves the root
|
|
562
|
+
* from the one read with a check-and-set, under the object store lock so a
|
|
563
|
+
* prune cannot remove the object in between. `seed` writes holders too, and
|
|
564
|
+
* only into an org with no graph.
|
|
565
|
+
*/
|
|
566
|
+
export async function changeLocalOrg(repository, change) {
|
|
567
|
+
return repository.graphs.withObjectStoreLock('local-org', async () => {
|
|
568
|
+
const before = repository.store.org.root(LOCAL_ORG_ID);
|
|
569
|
+
const next = change(before ? await repository.graphs.readGraph(before) : null);
|
|
570
|
+
const root = await repository.graphs.writeGraph(next.graph);
|
|
571
|
+
repository.store.org.write(() => {
|
|
572
|
+
repository.store.org.setRoot(LOCAL_ORG_ID, before, root);
|
|
573
|
+
for (const holder of next.holders ?? [])
|
|
574
|
+
repository.store.org.addHolder(LOCAL_ORG_ID, holder);
|
|
575
|
+
// A definition change can give a held post reports: check the
|
|
576
|
+
// holders as they stand, in the same transaction (osa_structure_ac_3).
|
|
577
|
+
assertOneHolderWithReports(next.graph, repository.store.org.holders(LOCAL_ORG_ID));
|
|
578
|
+
});
|
|
579
|
+
return { root, graph: next.graph };
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
/** Adds to an existing org's graph, or starts one with its first team. */
|
|
583
|
+
export function onOrg(graph, starts_org) {
|
|
584
|
+
if (graph)
|
|
585
|
+
return graph;
|
|
586
|
+
if (!starts_org)
|
|
587
|
+
throw new Error(NO_ORG);
|
|
588
|
+
return emptyGraph();
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Changes who holds a post: checks the post and the rules against the graph
|
|
592
|
+
* and holders as they stand, inside one write transaction, so two holds
|
|
593
|
+
* cannot both pass a one-holder rule.
|
|
594
|
+
*/
|
|
595
|
+
export async function changeLocalHolder(repository, input) {
|
|
596
|
+
const root = repository.store.org.root(LOCAL_ORG_ID);
|
|
597
|
+
if (!root)
|
|
598
|
+
throw new Error(NO_ORG);
|
|
599
|
+
const graph = await repository.graphs.readGraph(root);
|
|
600
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
601
|
+
const post_id = postIdOf(graph, structure, input.post);
|
|
602
|
+
return repository.store.org.write(() => {
|
|
603
|
+
if (repository.store.org.root(LOCAL_ORG_ID) !== root) {
|
|
604
|
+
throw new Error('The local org changed while this command ran; run it again.');
|
|
605
|
+
}
|
|
606
|
+
const holders = repository.store.org.holders(LOCAL_ORG_ID);
|
|
607
|
+
const rules = localOrgRules(graph, input.workflow, repository.store.org.overrides(LOCAL_ORG_ID));
|
|
608
|
+
if (input.action === 'hold') {
|
|
609
|
+
if (holders.some((holder) => holder.post_id === post_id &&
|
|
610
|
+
holder.member.id === input.member.id &&
|
|
611
|
+
holder.member.kind === input.member.kind)) {
|
|
612
|
+
return { post: input.post, member: input.member, changed: false };
|
|
613
|
+
}
|
|
614
|
+
assertMayHold(graph, holders, post_id, input.member, rules);
|
|
615
|
+
repository.store.org.addHolder(LOCAL_ORG_ID, {
|
|
616
|
+
post_id,
|
|
617
|
+
member: input.member,
|
|
618
|
+
held_since: new Date().toISOString()
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
assertMayRelease(graph, holders, post_id, input.member, rules);
|
|
623
|
+
repository.store.org.removeHolder(LOCAL_ORG_ID, post_id, input.member);
|
|
624
|
+
}
|
|
625
|
+
return { post: input.post, member: input.member, changed: true };
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* The repository's owning team (osa-slots): the repository is its local
|
|
630
|
+
* org's one project, owned by the team sdlc org own named, or else by the
|
|
631
|
+
* org's only root team.
|
|
632
|
+
*/
|
|
633
|
+
export function projectTeamId(structure, stored) {
|
|
634
|
+
const owner = projectOwner(structure, stored);
|
|
635
|
+
if ('team_id' in owner)
|
|
636
|
+
return owner.team_id;
|
|
637
|
+
throw new Error(owner.roots.length
|
|
638
|
+
? `The local org has several root teams (${owner.roots.join(', ')}): name the repository's owning team with sdlc org own <team>.`
|
|
639
|
+
: 'The local org has no team yet: add one with sdlc org add team <key>.');
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* The owning team, or, when none owns the project, the root team keys
|
|
643
|
+
* sdlc org own chooses from (none when the org has no team).
|
|
644
|
+
*/
|
|
645
|
+
export function projectOwner(structure, stored) {
|
|
646
|
+
if (stored && structure.teams.has(stored))
|
|
647
|
+
return { team_id: stored };
|
|
648
|
+
const roots = [...structure.teams.values()].filter((team) => team.parent_id === null);
|
|
649
|
+
if (roots.length === 1)
|
|
650
|
+
return { team_id: roots[0].id };
|
|
651
|
+
return { roots: roots.map((team) => team.key).sort() };
|
|
652
|
+
}
|
|
653
|
+
/** A member named as `person:<id>` or `agent:<id>`. */
|
|
654
|
+
export function parseMember(text) {
|
|
655
|
+
const [kind, id, ...rest] = text.split(':');
|
|
656
|
+
if ((kind !== 'person' && kind !== 'agent') || !id || rest.length) {
|
|
657
|
+
throw new Error(`${text} is not a member: name it person:<id> or agent:<id>.`);
|
|
658
|
+
}
|
|
659
|
+
return { id, kind };
|
|
660
|
+
}
|
|
661
|
+
function memberText(member) {
|
|
662
|
+
return `${member.kind}:${member.id}`;
|
|
663
|
+
}
|
|
664
|
+
function describeBinding(graph, structure, binding) {
|
|
665
|
+
return {
|
|
666
|
+
slot: structure.slots.get(binding.slot_id)?.key ?? binding.slot_id,
|
|
667
|
+
source: binding.source,
|
|
668
|
+
status: binding.status,
|
|
669
|
+
posts: binding.posts.map((entry) => ({
|
|
670
|
+
post: postName(graph, structure, entry.post_id),
|
|
671
|
+
holders: entry.holders,
|
|
672
|
+
...(entry.off_description ? { off_description: true } : {})
|
|
673
|
+
})),
|
|
674
|
+
...(binding.needs_person ? { needs_person: true } : {}),
|
|
675
|
+
...(binding.reason !== undefined
|
|
676
|
+
? {
|
|
677
|
+
reason: binding.reason,
|
|
678
|
+
...(binding.set_by ? { set_by: memberText(binding.set_by) } : {}),
|
|
679
|
+
...(binding.set_at ? { set_at: binding.set_at } : {})
|
|
680
|
+
}
|
|
681
|
+
: {}),
|
|
682
|
+
...(binding.stale_post_ids
|
|
683
|
+
? { stale_posts: binding.stale_post_ids.length }
|
|
684
|
+
: {})
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* The repository project's owning team and each slot's binding, or one slot
|
|
689
|
+
* by key (osa_slots_ac_1 to ac_3, ac_9); an unknown slot is refused.
|
|
690
|
+
*/
|
|
691
|
+
export function describeLocalProject(org, rules, input = {}) {
|
|
692
|
+
const structure = readOrgStructure(org.graph.nodes, org.graph.edges);
|
|
693
|
+
const team_id = projectTeamId(structure, org.project_team);
|
|
694
|
+
return describeProjectOf(org, structure, team_id, rules, input);
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* The org chart's project (osa-slots-viewer, osa_slots_ac_10): its owning
|
|
698
|
+
* team and each slot's binding, or the root teams to choose an owner from.
|
|
699
|
+
*/
|
|
700
|
+
export function describeLocalProjectOrOwners(org, rules) {
|
|
701
|
+
const structure = readOrgStructure(org.graph.nodes, org.graph.edges);
|
|
702
|
+
const owner = projectOwner(structure, org.project_team);
|
|
703
|
+
if ('roots' in owner)
|
|
704
|
+
return { team: null, roots: owner.roots };
|
|
705
|
+
return describeProjectOf(org, structure, owner.team_id, rules);
|
|
706
|
+
}
|
|
707
|
+
function describeProjectOf(org, structure, team_id, rules, input = {}) {
|
|
708
|
+
const bindings = input.slot
|
|
709
|
+
? [
|
|
710
|
+
slotBinding(structure, org.holders, requireByKey(org.graph, 'slot', input.slot).id, team_id, org.overrides, rules)
|
|
711
|
+
]
|
|
712
|
+
: slotBindings(structure, org.holders, team_id, org.overrides, rules);
|
|
713
|
+
return {
|
|
714
|
+
team: structure.teams.get(team_id).key,
|
|
715
|
+
slots: bindings.map((binding) => describeBinding(org.graph, structure, binding))
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
/** Who decides a slot's gate when its holders are absent or the author (osa_slots_ac_5). */
|
|
719
|
+
export function escalateLocalSlot(org, rules, input) {
|
|
720
|
+
const structure = readOrgStructure(org.graph.nodes, org.graph.edges);
|
|
721
|
+
const team_id = projectTeamId(structure, org.project_team);
|
|
722
|
+
const slot_id = requireByKey(org.graph, 'slot', input.slot).id;
|
|
723
|
+
const binding = slotBinding(structure, org.holders, slot_id, team_id, org.overrides, rules);
|
|
724
|
+
const result = escalate(structure, org.holders, binding, input, rules);
|
|
725
|
+
const names = (ids) => ids.map((id) => postName(org.graph, structure, id));
|
|
726
|
+
if (result.kind === 'decides') {
|
|
727
|
+
return {
|
|
728
|
+
slot: input.slot,
|
|
729
|
+
decides: {
|
|
730
|
+
post: postName(org.graph, structure, result.post_id),
|
|
731
|
+
members: result.members,
|
|
732
|
+
escalated: result.escalated,
|
|
733
|
+
path: names(result.path)
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
if (result.kind === 'waits') {
|
|
738
|
+
return {
|
|
739
|
+
slot: input.slot,
|
|
740
|
+
waits_for: structure.functions.get(result.function_id)?.key,
|
|
741
|
+
why: 'its job function is not escalable, so only a holder of that function decides'
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
return {
|
|
745
|
+
slot: input.slot,
|
|
746
|
+
unresolved: true,
|
|
747
|
+
path: names(result.path),
|
|
748
|
+
why: binding.status === 'uncovered'
|
|
749
|
+
? 'no post fills the slot'
|
|
750
|
+
: 'nobody eligible holds a post up the reporting line'
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
/** Throws unless `actor` holds a post governing the team's projects (osa_slots_ac_8). */
|
|
754
|
+
function assertMayGovern(graph, structure, holders, team_id, actor) {
|
|
755
|
+
if (mayGovern(structure, holders, team_id, actor))
|
|
756
|
+
return;
|
|
757
|
+
const posts = governingPosts(structure, team_id).map((id) => postName(graph, structure, id));
|
|
758
|
+
throw new Error(`Refused: ${memberText(actor)} holds no post that governs team ${structure.teams.get(team_id)?.key}'s projects; ${posts.length
|
|
759
|
+
? `a holder of ${posts.join(' or ')} decides`
|
|
760
|
+
: 'the team and its parents have no post to govern them'}.`);
|
|
761
|
+
}
|
|
762
|
+
function bindingRefusalText(slot, refusal) {
|
|
763
|
+
return refusal === 'no_posts'
|
|
764
|
+
? `name at least one post to bind ${slot} to`
|
|
765
|
+
: `${slot} holds a gate that needs a person, and one of those posts is held only by agents`;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Overrides a slot's binding with posts and a reason, or clears it back to
|
|
769
|
+
* the baseline, as `actor` (osa_slots_ac_2, ac_4, ac_8). Checked against the
|
|
770
|
+
* graph, holders and overrides as they stand, inside one write transaction.
|
|
771
|
+
*/
|
|
772
|
+
export async function changeLocalBinding(repository, input) {
|
|
773
|
+
const root = repository.store.org.root(LOCAL_ORG_ID);
|
|
774
|
+
if (!root)
|
|
775
|
+
throw new Error(NO_ORG);
|
|
776
|
+
const graph = await repository.graphs.readGraph(root);
|
|
777
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
778
|
+
const slot_id = requireByKey(graph, 'slot', input.slot).id;
|
|
779
|
+
const post_ids = input.posts?.map((name) => postIdOf(graph, structure, name));
|
|
780
|
+
const reason = input.reason?.trim();
|
|
781
|
+
if (post_ids && !reason) {
|
|
782
|
+
throw new Error('Give the reason for the override with --reason <text>: an override is reported with it.');
|
|
783
|
+
}
|
|
784
|
+
return repository.store.org.write(() => {
|
|
785
|
+
if (repository.store.org.root(LOCAL_ORG_ID) !== root) {
|
|
786
|
+
throw new Error('The local org changed while this command ran; run it again.');
|
|
787
|
+
}
|
|
788
|
+
const holders = repository.store.org.holders(LOCAL_ORG_ID);
|
|
789
|
+
const project_team = repository.store.org.projectTeam(LOCAL_ORG_ID);
|
|
790
|
+
const team_id = projectTeamId(structure, project_team);
|
|
791
|
+
assertMayGovern(graph, structure, holders, team_id, input.actor);
|
|
792
|
+
const rules = localOrgRules(graph, input.workflow);
|
|
793
|
+
let changed;
|
|
794
|
+
if (post_ids) {
|
|
795
|
+
const refusals = checkBinding(structure, holders, slot_id, post_ids, rules);
|
|
796
|
+
if (refusals.length) {
|
|
797
|
+
throw new Error(`Refused: ${refusals.map((refusal) => bindingRefusalText(input.slot, refusal)).join('; ')}.`);
|
|
798
|
+
}
|
|
799
|
+
repository.store.org.setOverride(LOCAL_ORG_ID, {
|
|
800
|
+
slot_id,
|
|
801
|
+
post_ids,
|
|
802
|
+
reason: reason,
|
|
803
|
+
set_by: input.actor,
|
|
804
|
+
set_at: new Date().toISOString()
|
|
805
|
+
});
|
|
806
|
+
changed = true;
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
changed = repository.store.org.clearOverride(LOCAL_ORG_ID, slot_id);
|
|
810
|
+
}
|
|
811
|
+
const org = {
|
|
812
|
+
graph,
|
|
813
|
+
holders,
|
|
814
|
+
project_team,
|
|
815
|
+
overrides: repository.store.org.overrides(LOCAL_ORG_ID)
|
|
816
|
+
};
|
|
817
|
+
return {
|
|
818
|
+
changed,
|
|
819
|
+
...describeLocalProject(org, localOrgRules(graph, input.workflow, org.overrides), { slot: input.slot })
|
|
820
|
+
};
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Names the team that owns the repository's project, as `actor`, who must
|
|
825
|
+
* govern both the team that owns it now and the new one (osa_slots_ac_8).
|
|
826
|
+
*/
|
|
827
|
+
export async function setLocalProjectTeam(repository, input) {
|
|
828
|
+
const root = repository.store.org.root(LOCAL_ORG_ID);
|
|
829
|
+
if (!root)
|
|
830
|
+
throw new Error(NO_ORG);
|
|
831
|
+
const graph = await repository.graphs.readGraph(root);
|
|
832
|
+
const structure = readOrgStructure(graph.nodes, graph.edges);
|
|
833
|
+
const team_id = requireByKey(graph, 'team', input.team).id;
|
|
834
|
+
return repository.store.org.write(() => {
|
|
835
|
+
if (repository.store.org.root(LOCAL_ORG_ID) !== root) {
|
|
836
|
+
throw new Error('The local org changed while this command ran; run it again.');
|
|
837
|
+
}
|
|
838
|
+
const holders = repository.store.org.holders(LOCAL_ORG_ID);
|
|
839
|
+
const stored = repository.store.org.projectTeam(LOCAL_ORG_ID);
|
|
840
|
+
let current = null;
|
|
841
|
+
try {
|
|
842
|
+
current = projectTeamId(structure, stored);
|
|
843
|
+
}
|
|
844
|
+
catch {
|
|
845
|
+
// Several root teams and no owner yet: only the new team governs.
|
|
846
|
+
}
|
|
847
|
+
if (current)
|
|
848
|
+
assertMayGovern(graph, structure, holders, current, input.actor);
|
|
849
|
+
assertMayGovern(graph, structure, holders, team_id, input.actor);
|
|
850
|
+
repository.store.org.setProjectTeam(LOCAL_ORG_ID, team_id);
|
|
851
|
+
return { team: input.team, changed: current !== team_id };
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
export { NO_ORG as LOCAL_ORG_MISSING };
|
|
855
|
+
//# sourceMappingURL=local-org.js.map
|