@unbrained/pm-cli 2026.9.6 → 2026.9.8
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/.agents/skills/pm-developer/SKILL.md +12 -4
- package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +19 -10
- package/.agents/skills/pm-extensions/SKILL.md +6 -0
- package/.agents/skills/pm-sdk/SKILL.md +11 -2
- package/.agents/skills/pm-user/SKILL.md +5 -0
- package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +218 -182
- package/dist/cli/after-command-context-usage.js +1 -48
- package/dist/cli/argv-utils.js +1 -40
- package/dist/cli/bootstrap-args.js +1 -9
- package/dist/cli/bundle-integrity.js +2 -110
- package/dist/cli/commander-usage.js +11 -771
- package/dist/cli/commands/activity.js +1 -9
- package/dist/cli/commands/aggregate.js +1 -5
- package/dist/cli/commands/append.js +1 -5
- package/dist/cli/commands/claim.js +1 -5
- package/dist/cli/commands/close-many.js +1 -5
- package/dist/cli/commands/close.js +1 -9
- package/dist/cli/commands/comments.js +1 -5
- package/dist/cli/commands/config.js +1 -9
- package/dist/cli/commands/context.js +1 -9
- package/dist/cli/commands/contracts.js +1 -5
- package/dist/cli/commands/copy.js +1 -9
- package/dist/cli/commands/create.js +1 -9
- package/dist/cli/commands/delete.js +1 -9
- package/dist/cli/commands/deps.js +1 -9
- package/dist/cli/commands/docs.js +1 -9
- package/dist/cli/commands/duplicates.js +1 -9
- package/dist/cli/commands/eval.js +1 -9
- package/dist/cli/commands/extension/describe.js +1 -5
- package/dist/cli/commands/extension/scaffold.js +1 -5
- package/dist/cli/commands/extension/shared.js +1 -5
- package/dist/cli/commands/extension.js +1 -9
- package/dist/cli/commands/files.js +1 -9
- package/dist/cli/commands/focus.js +1 -9
- package/dist/cli/commands/gc.js +1 -9
- package/dist/cli/commands/get.js +1 -9
- package/dist/cli/commands/graph.js +1 -10
- package/dist/cli/commands/health.js +1 -9
- package/dist/cli/commands/history-compact.js +1 -10
- package/dist/cli/commands/history-redact.js +1 -11
- package/dist/cli/commands/history-repair.js +1 -10
- package/dist/cli/commands/history.js +1 -5
- package/dist/cli/commands/index.js +1 -58
- package/dist/cli/commands/init-agent-guidance.js +1 -9
- package/dist/cli/commands/init.js +1 -9
- package/dist/cli/commands/learnings.js +1 -5
- package/dist/cli/commands/lifecycle-transitions.js +1 -5
- package/dist/cli/commands/list.js +1 -9
- package/dist/cli/commands/merge.js +1 -11
- package/dist/cli/commands/next.js +1 -9
- package/dist/cli/commands/notes.js +1 -5
- package/dist/cli/commands/plan.js +1 -9
- package/dist/cli/commands/profile.js +1 -9
- package/dist/cli/commands/restore.js +1 -9
- package/dist/cli/commands/scheduling-shortcuts.js +1 -9
- package/dist/cli/commands/schema.js +1 -10
- package/dist/cli/commands/search.js +1 -9
- package/dist/cli/commands/stats.js +1 -9
- package/dist/cli/commands/telemetry.js +1 -9
- package/dist/cli/commands/test-all.js +1 -9
- package/dist/cli/commands/test-runs.js +1 -9
- package/dist/cli/commands/test.js +1 -9
- package/dist/cli/commands/update-many.js +1 -5
- package/dist/cli/commands/update.js +1 -9
- package/dist/cli/commands/upgrade.js +1 -5
- package/dist/cli/commands/validate.js +1 -15
- package/dist/cli/context-intent-invocation.js +1 -20
- package/dist/cli/description-stdin.js +1 -17
- package/dist/cli/error-guidance.js +1 -1353
- package/dist/cli/extension-command-help.js +5 -636
- package/dist/cli/extension-command-options.js +1 -427
- package/dist/cli/extension-recovery.js +1 -126
- package/dist/cli/help-content.js +2 -1001
- package/dist/cli/help-json-payload.js +4 -570
- package/dist/cli/main.d.ts +4 -0
- package/dist/cli/main.js +5 -2573
- package/dist/cli/migration-gates.js +1 -289
- package/dist/cli/public.js +1 -20
- package/dist/cli/register-annotations.js +1 -270
- package/dist/cli/register-assurance.js +1 -62
- package/dist/cli/register-files-lookup.js +1 -56
- package/dist/cli/register-history-activity.d.ts +8 -0
- package/dist/cli/register-history-activity.js +2 -0
- package/dist/cli/register-history-author.js +1 -38
- package/dist/cli/register-history-maintenance.d.ts +9 -0
- package/dist/cli/register-history-maintenance.js +2 -0
- package/dist/cli/register-list-query.js +10 -943
- package/dist/cli/register-mutation-options.js +1 -9
- package/dist/cli/register-mutation.js +19 -1893
- package/dist/cli/register-operations.js +1 -920
- package/dist/cli/register-setup.js +1 -716
- package/dist/cli/register-structured-mutation.js +1 -196
- package/dist/cli/registration-helpers.js +1 -5
- package/dist/cli/runtime-compatibility-boundary.js +4 -42
- package/dist/cli/schema-registration-helpers.js +1 -73
- package/dist/cli/search-refresh.js +1 -13
- package/dist/cli/stats-analytics-json.js +1 -68
- package/dist/cli/telemetry-flush.js +1 -10
- package/dist/cli-bundle/bundle-manifest.json +164 -156
- package/dist/cli-bundle/chunks/chunk-3BZZA6A3.js +5 -0
- package/dist/cli-bundle/chunks/chunk-AMRDVX36.js +235 -0
- package/dist/cli-bundle/chunks/chunk-DAM4CBBR.js +2202 -0
- package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-FLDWYEND.js +77 -0
- package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-G5ADGQ2D.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-JAAEYHUA.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-JX4DH4WC.js → chunk-KR3RP4FH.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-LEZOUXG6.js +2 -0
- package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
- package/dist/cli-bundle/chunks/chunk-QOEKOECV.js +29 -0
- package/dist/cli-bundle/chunks/chunk-RHSFOMHU.js +2 -0
- package/dist/cli-bundle/chunks/chunk-XOD2PCB6.js +20 -0
- package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-YVEQ2AMO.js} +4 -4
- package/dist/cli-bundle/chunks/register-list-query-KSK3R63M.js +11 -0
- package/dist/cli-bundle/chunks/register-mutation-IQ5C7U6O.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-I5W3KMGB.js → register-operations-DWVHR2NC.js} +2 -2
- package/dist/cli-bundle/chunks/register-setup-BQ5SVD4B.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-3WRPWLA7.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-7MBUII7U.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-COPBO5HW.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-DUN4IXYN.js +20 -0
- package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-EE5QSM4Z.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-HJVARYM3.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-IAUOUGVR.js +177 -0
- package/dist/cli-bundle/focused-chunks/chunk-KOOMJ54F.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-MZDXX7JY.js +56 -0
- package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-OPFHFGDD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-QHNETP77.js +9 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-RMWES4M6.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-RXT4P5QH.js +10 -0
- package/dist/cli-bundle/focused-chunks/chunk-SDOL6FM2.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-SQV4AAUC.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-PEFABF7E.js → chunk-WE3IUNIW.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-YALOUBWJ.js +2 -0
- package/dist/cli-bundle/main.js +20 -20
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +29 -29
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +42 -42
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +11 -11
- package/dist/cli.js +1 -104
- package/dist/core/checkpoint/checkpoint-gc.js +1 -169
- package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
- package/dist/core/config/nested-settings.js +1 -534
- package/dist/core/config/positional-value.js +1 -109
- package/dist/core/diagnostics/remediation.js +1 -506
- package/dist/core/extensions/activation-summary-markdown.js +2 -145
- package/dist/core/extensions/activation-summary.js +1 -92
- package/dist/core/extensions/activation-transaction.js +1 -46
- package/dist/core/extensions/capability-usage.js +1 -173
- package/dist/core/extensions/command-hook-context.js +1 -13
- package/dist/core/extensions/command-metadata-contract.js +1 -22
- package/dist/core/extensions/command-visibility-tier.js +1 -29
- package/dist/core/extensions/contribution-inventory.js +1 -173
- package/dist/core/extensions/exporter-output-contract.js +1 -66
- package/dist/core/extensions/extension-candidate.js +1 -18
- package/dist/core/extensions/extension-capability-aliases.js +1 -158
- package/dist/core/extensions/extension-hook-runtime.js +1 -699
- package/dist/core/extensions/extension-policy.js +1 -599
- package/dist/core/extensions/extension-registries.js +1 -62
- package/dist/core/extensions/extension-runtime-helpers.js +1 -33
- package/dist/core/extensions/extension-types.js +1 -102
- package/dist/core/extensions/flag-definition-validation.js +1 -52
- package/dist/core/extensions/flag-value-types.js +1 -64
- package/dist/core/extensions/index.js +1 -526
- package/dist/core/extensions/item-field-types.js +1 -39
- package/dist/core/extensions/item-fields.js +1 -261
- package/dist/core/extensions/loader.js +1 -2223
- package/dist/core/extensions/manifest-schema.js +1 -69
- package/dist/core/extensions/module-graph-snapshot.js +1 -33
- package/dist/core/extensions/preflight-ownership.js +1 -41
- package/dist/core/extensions/registration-validation.js +1 -82
- package/dist/core/extensions/registration-values.js +1 -209
- package/dist/core/extensions/reserved-host-flags.js +1 -36
- package/dist/core/extensions/runtime-registrations.js +1 -67
- package/dist/core/extensions/service-ownership.js +1 -19
- package/dist/core/extensions/version-compat.js +1 -216
- package/dist/core/fs/fs-utils.js +2 -158
- package/dist/core/fs/host-environment-errors.js +1 -141
- package/dist/core/fs/index.js +1 -9
- package/dist/core/fs/path-utils.js +1 -17
- package/dist/core/governance/content-fields.js +1 -160
- package/dist/core/governance/issue-codes.js +1 -151
- package/dist/core/governance/metadata-coverage.js +1 -358
- package/dist/core/history/drift-cache.js +3 -72
- package/dist/core/history/drift-scan.js +1 -342
- package/dist/core/history/event-classification.js +1 -109
- package/dist/core/history/event-index.js +8 -784
- package/dist/core/history/history-compact-bulk.js +1 -104
- package/dist/core/history/history-diff.js +1 -158
- package/dist/core/history/history-rewrite.d.ts +6 -1
- package/dist/core/history/history-rewrite.js +1 -107
- package/dist/core/history/history-storage-stats.js +1 -102
- package/dist/core/history/history-stream-policy.js +1 -62
- package/dist/core/history/history.js +2 -617
- package/dist/core/history/identity.js +1 -30
- package/dist/core/history/index.js +1 -9
- package/dist/core/history/projection.js +1 -196
- package/dist/core/history/read.d.ts +9 -0
- package/dist/core/history/read.js +1 -57
- package/dist/core/history/replay.js +2 -439
- package/dist/core/history/version-address.js +1 -32
- package/dist/core/history/workspace-history.js +2 -433
- package/dist/core/io/body-file.js +1 -62
- package/dist/core/io/bulk-ids-input.js +1 -112
- package/dist/core/item/actionability.js +1 -327
- package/dist/core/item/dependency-reference.js +1 -20
- package/dist/core/item/id.js +1 -112
- package/dist/core/item/index.js +1 -12
- package/dist/core/item/item-format-version.js +1 -78
- package/dist/core/item/item-format.js +5 -1473
- package/dist/core/item/item-record.js +1 -23
- package/dist/core/item/item-type-definition.js +1 -133
- package/dist/core/item/parent-reference-policy.js +1 -57
- package/dist/core/item/parse.js +2 -603
- package/dist/core/item/plan-lifecycle.js +1 -19
- package/dist/core/item/priority.js +1 -61
- package/dist/core/item/sprint-release-format.js +1 -38
- package/dist/core/item/status-filter.js +1 -115
- package/dist/core/item/status.js +1 -43
- package/dist/core/item/toon-decode.js +1 -29
- package/dist/core/item/type-registry.js +1 -715
- package/dist/core/item/type-synonyms.js +1 -38
- package/dist/core/lock/index.js +1 -9
- package/dist/core/lock/lock-gc.js +1 -240
- package/dist/core/lock/lock.js +3 -590
- package/dist/core/output/mutation-projection.js +1 -217
- package/dist/core/output/output-control.js +1 -25
- package/dist/core/output/output.js +11 -494
- package/dist/core/output/query-summary.js +1 -58
- package/dist/core/output/tabular.js +1 -77
- package/dist/core/packages/manifest.js +1 -244
- package/dist/core/packages/root.js +1 -84
- package/dist/core/profile/profile-describe.js +1 -83
- package/dist/core/profile/profile-lint.js +1 -415
- package/dist/core/profile/profile-plan.js +0 -0
- package/dist/core/profile/profile-presets.js +1 -370
- package/dist/core/reproducibility/context.js +1 -82
- package/dist/core/schema/fields-file.js +2 -288
- package/dist/core/schema/item-types-file.js +2 -296
- package/dist/core/schema/runtime-field-filters.js +1 -49
- package/dist/core/schema/runtime-field-values.js +1 -313
- package/dist/core/schema/runtime-schema.js +2 -826
- package/dist/core/schema/status-defs-file.js +2 -227
- package/dist/core/schema/status-token.js +1 -31
- package/dist/core/schema/type-inference.js +1 -95
- package/dist/core/schema/type-presets.js +1 -87
- package/dist/core/schema/type-workflows.js +1 -104
- package/dist/core/search/background-refresh.js +2 -286
- package/dist/core/search/bm25.js +1 -146
- package/dist/core/search/cache.js +2 -534
- package/dist/core/search/corpus.js +1 -311
- package/dist/core/search/embedding-batches.js +1 -163
- package/dist/core/search/eval.js +1 -225
- package/dist/core/search/http-client.js +1 -75
- package/dist/core/search/providers.js +1 -242
- package/dist/core/search/relevance.js +1 -244
- package/dist/core/search/semantic-defaults.js +1 -199
- package/dist/core/search/staleness.js +1 -30
- package/dist/core/search/vector-stores.js +2 -664
- package/dist/core/search/vectorization-metadata.js +1 -81
- package/dist/core/sentry/helpers.js +1 -272
- package/dist/core/sentry/instrument.js +1 -387
- package/dist/core/session/session-state.js +1 -260
- package/dist/core/shared/agent-session-context.js +1 -133
- package/dist/core/shared/author.js +1 -1172
- package/dist/core/shared/command-types.js +1 -4
- package/dist/core/shared/conflict-markers.js +1 -31
- package/dist/core/shared/constants.js +1 -405
- package/dist/core/shared/errors.js +1 -20
- package/dist/core/shared/html-entity-decode.js +1 -131
- package/dist/core/shared/index.js +1 -12
- package/dist/core/shared/item-metadata-contract.js +1 -89
- package/dist/core/shared/lazy-module.js +1 -16
- package/dist/core/shared/levenshtein.js +1 -61
- package/dist/core/shared/memo.js +1 -19
- package/dist/core/shared/numeric-parsers.js +1 -20
- package/dist/core/shared/option-alias-visibility.js +1 -67
- package/dist/core/shared/primitives.js +1 -127
- package/dist/core/shared/serial-queue.js +1 -79
- package/dist/core/shared/serialization.js +1 -210
- package/dist/core/shared/split-comma-list.js +1 -30
- package/dist/core/shared/text-normalization.js +1 -38
- package/dist/core/shared/time.js +1 -306
- package/dist/core/store/index.js +1 -12
- package/dist/core/store/item-format-migration.js +1 -125
- package/dist/core/store/item-metadata-cache.js +1 -1116
- package/dist/core/store/item-metadata-query-index.js +9 -394
- package/dist/core/store/item-metadata-read-work.js +1 -43
- package/dist/core/store/item-store.js +1 -693
- package/dist/core/store/paths.d.ts +1 -1
- package/dist/core/store/paths.js +1 -214
- package/dist/core/store/settings-read-cache.js +1 -85
- package/dist/core/store/settings-validator.js +1 -421
- package/dist/core/store/settings.js +3 -1309
- package/dist/core/store/tracker-preflight.js +1 -141
- package/dist/core/telemetry/consent.js +5 -108
- package/dist/core/telemetry/observability.js +1 -246
- package/dist/core/telemetry/runtime.js +4 -1988
- package/dist/core/test/background-runs.js +4 -945
- package/dist/core/test/item-test-run-tracking.js +1 -63
- package/dist/core/test/run-selectors.js +1 -120
- package/dist/core/validate/estimate-defaults.js +1 -89
- package/dist/core/validate/fix-planning.js +1 -189
- package/dist/core/validate/linked-artifact-reference.js +1 -36
- package/dist/core/validate/missing-by-type.js +1 -34
- package/dist/core/validate/missing-link-owners.js +1 -95
- package/dist/core/validate/stale-file-classification.js +1 -82
- package/dist/mcp/http-server.js +5 -448
- package/dist/mcp/legacy-adapter.js +1 -77
- package/dist/mcp/runtime-capabilities.js +1 -200
- package/dist/mcp/server.js +4 -1233
- package/dist/mcp/tool-definitions.js +1 -804
- package/dist/sdk/actionability.js +1 -13
- package/dist/sdk/agent/closed-domain-contracts.js +1 -161
- package/dist/sdk/agent/command-recovery.js +1 -59
- package/dist/sdk/agent/command-suggestions.js +1 -66
- package/dist/sdk/agent/create-option-policy.js +1 -31
- package/dist/sdk/agent/identity-config.js +1 -106
- package/dist/sdk/agent/item-addressing.js +1 -207
- package/dist/sdk/agent/refusal-closure-census.js +1 -151
- package/dist/sdk/agent/refusal-closure.js +1 -133
- package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
- package/dist/sdk/agent/refusal-reachability.js +1 -593
- package/dist/sdk/agent/subcommand-recovery.js +1 -83
- package/dist/sdk/agent/task-transcript-contracts.js +1 -197
- package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
- package/dist/sdk/agent-capability-contracts.js +1 -428
- package/dist/sdk/agent-session-context.js +1 -9
- package/dist/sdk/annotations.js +1 -448
- package/dist/sdk/author-attribution.js +1 -468
- package/dist/sdk/authoring.js +1 -20
- package/dist/sdk/cli-bootstrap.js +1 -838
- package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
- package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
- package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
- package/dist/sdk/cli-contracts/command-aliases.js +1 -107
- package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
- package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
- package/dist/sdk/cli-contracts/commander-types.js +1 -159
- package/dist/sdk/cli-contracts/completeness.js +1 -393
- package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
- package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
- package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
- package/dist/sdk/cli-contracts/string-lists.js +1 -16
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
- package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
- package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +1 -17
- package/dist/sdk/cli-program.js +1 -49
- package/dist/sdk/command-line.d.ts +2 -5
- package/dist/sdk/command-line.js +1 -78
- package/dist/sdk/comments.js +1 -133
- package/dist/sdk/compile-cache.js +1 -73
- package/dist/sdk/completion.js +157 -837
- package/dist/sdk/compose.js +1 -1090
- package/dist/sdk/config.js +1 -1204
- package/dist/sdk/context/recency.js +1 -33
- package/dist/sdk/context/semantic-session-attribution.js +1 -82
- package/dist/sdk/context/usage-egress.js +1 -29
- package/dist/sdk/context/usage-ledger.js +3 -185
- package/dist/sdk/context-intent-contracts.js +1 -709
- package/dist/sdk/context-intent-runtime.js +1 -115
- package/dist/sdk/context-packing.js +1 -218
- package/dist/sdk/context-relevance.js +1 -503
- package/dist/sdk/context-signal-store.js +2 -426
- package/dist/sdk/context-usage.js +1 -367
- package/dist/sdk/contracts.js +1 -23
- package/dist/sdk/core-governance.js +1 -14
- package/dist/sdk/core.js +1 -14
- package/dist/sdk/corpus-shape.js +1 -401
- package/dist/sdk/define.js +1 -220
- package/dist/sdk/dependencies.js +1 -718
- package/dist/sdk/dependency-flag-validation.js +1 -156
- package/dist/sdk/dependency-provenance.js +1 -135
- package/dist/sdk/docs.js +1 -14
- package/dist/sdk/duplicates.js +1 -40
- package/dist/sdk/environment/agent-environment.js +1 -466
- package/dist/sdk/environment/host-environment-errors.js +1 -8
- package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
- package/dist/sdk/environment/source-context.js +1 -28
- package/dist/sdk/environment/tracker-preflight.js +1 -9
- package/dist/sdk/error-code-catalog.js +1 -153
- package/dist/sdk/error-runtime.js +1 -58
- package/dist/sdk/errors.js +1 -58
- package/dist/sdk/eval.js +1 -190
- package/dist/sdk/extension/author-manifest.js +1 -92
- package/dist/sdk/extension/bundled-catalog.js +1 -332
- package/dist/sdk/extension/concurrency.js +1 -25
- package/dist/sdk/extension/copy-scope.d.ts +2 -0
- package/dist/sdk/extension/copy-scope.js +2 -0
- package/dist/sdk/extension/custom-field-collisions.js +1 -30
- package/dist/sdk/extension/describe.js +3 -189
- package/dist/sdk/extension/doctor.js +1 -606
- package/dist/sdk/extension/install-plan.d.ts +69 -0
- package/dist/sdk/extension/install-plan.js +2 -0
- package/dist/sdk/extension/install-receipts.d.ts +7 -0
- package/dist/sdk/extension/install-receipts.js +2 -0
- package/dist/sdk/extension/install-runtime.js +3 -313
- package/dist/sdk/extension/install-snapshot.js +1 -66
- package/dist/sdk/extension/install-sources.js +5 -1057
- package/dist/sdk/extension/managed-state.js +2 -252
- package/dist/sdk/extension/migrations.js +2 -174
- package/dist/sdk/extension/output-ownership.js +1 -25
- package/dist/sdk/extension/runtime-summary.js +1 -18
- package/dist/sdk/extension/scaffold.js +4 -2308
- package/dist/sdk/extension/shared.js +1 -147
- package/dist/sdk/extension/source-resolution.js +1 -65
- package/dist/sdk/extension/update-check.js +1 -67
- package/dist/sdk/extension-command-context.js +1 -44
- package/dist/sdk/extension-contracts.js +1 -73
- package/dist/sdk/extension.d.ts +7 -2
- package/dist/sdk/extension.js +1 -2196
- package/dist/sdk/files.js +1 -535
- package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
- package/dist/sdk/flag-invocation-contracts.js +1 -344
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
- package/dist/sdk/generated-error-code-catalog.js +1 -16
- package/dist/sdk/governance/assurance-action-contracts.js +1 -4
- package/dist/sdk/governance/assurance-action.js +1 -411
- package/dist/sdk/governance/assurance-limits.js +1 -10
- package/dist/sdk/governance/assurance-mutation-error.js +1 -81
- package/dist/sdk/governance/assurance-presets.js +1 -135
- package/dist/sdk/governance/assurance-runtime.js +1 -238
- package/dist/sdk/governance/assurance.js +4 -1182
- package/dist/sdk/governance/boundary-fixtures.js +1 -200
- package/dist/sdk/governance/coverage-assurance.js +1 -60
- package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
- package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
- package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
- package/dist/sdk/governance/defect-recurrence.js +1 -623
- package/dist/sdk/governance/extension-host-version.js +1 -115
- package/dist/sdk/governance/gc.js +1 -368
- package/dist/sdk/governance/health.js +1 -2367
- package/dist/sdk/governance/hierarchy-validation.js +1 -108
- package/dist/sdk/governance/linked-file-report.js +1 -71
- package/dist/sdk/governance/merge-receipt-history.js +1 -206
- package/dist/sdk/governance/provenance-health.js +1 -282
- package/dist/sdk/governance/reindex.js +4 -761
- package/dist/sdk/governance/stale-work.js +1 -82
- package/dist/sdk/governance/status-role-diagnostics.js +1 -35
- package/dist/sdk/governance/storage-integrity.js +1 -280
- package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
- package/dist/sdk/governance/upgrade.js +2 -327
- package/dist/sdk/governance/validate-history-drift.js +1 -81
- package/dist/sdk/governance/validate-item-reader.js +1 -17
- package/dist/sdk/governance/validate-normalization.js +1 -36
- package/dist/sdk/governance/validate.js +1 -2261
- package/dist/sdk/governance/workspace-position.js +1 -163
- package/dist/sdk/governance.d.ts +1 -0
- package/dist/sdk/governance.js +1 -31
- package/dist/sdk/graph/adapter.js +1 -181
- package/dist/sdk/graph/analytics.js +1 -474
- package/dist/sdk/graph/assembly.js +1 -377
- package/dist/sdk/graph/cache.js +1 -160
- package/dist/sdk/graph/centrality.js +1 -258
- package/dist/sdk/graph/conformance.js +1 -130
- package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
- package/dist/sdk/graph/deadline-scheduling.js +2 -0
- package/dist/sdk/graph/durable-cache.d.ts +1 -1
- package/dist/sdk/graph/durable-cache.js +1 -361
- package/dist/sdk/graph/governance-contracts.js +1 -34
- package/dist/sdk/graph/governance.d.ts +13 -1
- package/dist/sdk/graph/governance.js +1 -735
- package/dist/sdk/graph/hierarchy-integrity.js +1 -310
- package/dist/sdk/graph/index.d.ts +3 -2
- package/dist/sdk/graph/index.js +1 -26
- package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
- package/dist/sdk/graph/lifecycle-coverage.js +2 -0
- package/dist/sdk/graph/mutation-advisory.js +1 -176
- package/dist/sdk/graph/remediation.js +1 -197
- package/dist/sdk/graph/run.d.ts +15 -1
- package/dist/sdk/graph/run.js +1 -768
- package/dist/sdk/graph/scheduling.js +1 -124
- package/dist/sdk/graph/traversal.js +1 -284
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
- package/dist/sdk/graph.js +1 -15
- package/dist/sdk/guide-topics.js +1 -707
- package/dist/sdk/guide.js +1 -279
- package/dist/sdk/history/maintenance.d.ts +71 -0
- package/dist/sdk/history/maintenance.js +2 -0
- package/dist/sdk/history/salvage.js +2 -247
- package/dist/sdk/history/subject.d.ts +19 -0
- package/dist/sdk/history/subject.js +2 -0
- package/dist/sdk/history-analytics.js +1 -282
- package/dist/sdk/history-compact.js +1 -527
- package/dist/sdk/history-mcp.js +1 -68
- package/dist/sdk/history-provenance.js +1 -182
- package/dist/sdk/history-read.js +1 -96
- package/dist/sdk/history-redact.d.ts +1 -14
- package/dist/sdk/history-redact.js +1 -643
- package/dist/sdk/history-repair.d.ts +5 -0
- package/dist/sdk/history-repair.js +1 -657
- package/dist/sdk/improvement-ledger-validation.js +1 -62
- package/dist/sdk/improvement-ledger.js +2 -257
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.js +1 -183
- package/dist/sdk/init-agent-guidance.js +2 -496
- package/dist/sdk/init.js +2 -820
- package/dist/sdk/invocation-author.js +1 -39
- package/dist/sdk/item-children.js +1 -90
- package/dist/sdk/item-metadata-index.js +1 -15
- package/dist/sdk/item-schedule.js +1 -27
- package/dist/sdk/item-transaction.js +1 -396
- package/dist/sdk/learnings.js +1 -29
- package/dist/sdk/lifecycle/append.js +2 -53
- package/dist/sdk/lifecycle/claim.d.ts +2 -0
- package/dist/sdk/lifecycle/claim.js +1 -242
- package/dist/sdk/lifecycle/close-many.js +1 -438
- package/dist/sdk/lifecycle/close.js +1 -468
- package/dist/sdk/lifecycle/copy.js +1 -212
- package/dist/sdk/lifecycle/create.js +1 -1949
- package/dist/sdk/lifecycle/delete.js +1 -45
- package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
- package/dist/sdk/lifecycle/focus.js +1 -91
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
- package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
- package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
- package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
- package/dist/sdk/lifecycle/mcp-actions.js +1 -51
- package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
- package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
- package/dist/sdk/lifecycle/plan.js +1 -1606
- package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
- package/dist/sdk/lifecycle/reopen.js +1 -68
- package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
- package/dist/sdk/lifecycle/restore.d.ts +1 -0
- package/dist/sdk/lifecycle/restore.js +1 -330
- package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
- package/dist/sdk/lifecycle/update-many.js +1 -861
- package/dist/sdk/lifecycle/update.js +1 -2136
- package/dist/sdk/lifecycle-completion.js +1 -92
- package/dist/sdk/lifecycle-policy.js +1 -120
- package/dist/sdk/linked-artifacts.js +1 -530
- package/dist/sdk/mcp/apps.js +4 -133
- package/dist/sdk/mcp/authorization.js +1 -404
- package/dist/sdk/mcp/discovery.js +1 -494
- package/dist/sdk/mcp/interactions.js +1 -336
- package/dist/sdk/mcp/protocol.d.ts +7 -0
- package/dist/sdk/mcp/protocol.js +1 -184
- package/dist/sdk/mcp/skills.js +1 -389
- package/dist/sdk/mcp/subscriptions.js +1 -211
- package/dist/sdk/mcp/tasks.js +2 -430
- package/dist/sdk/mcp/transport.js +1 -260
- package/dist/sdk/merge/abandoned-receipts.js +1 -46
- package/dist/sdk/merge/driver.js +1 -212
- package/dist/sdk/merge/index.js +1 -16
- package/dist/sdk/merge/install.js +3 -561
- package/dist/sdk/merge/receipt-file-boundary.js +1 -46
- package/dist/sdk/merge/receipt-operation.js +1 -96
- package/dist/sdk/merge/receipt-schema.js +1 -397
- package/dist/sdk/merge/receipts.js +4 -525
- package/dist/sdk/merge/reconcile.js +1 -352
- package/dist/sdk/merge/three-way.js +3 -775
- package/dist/sdk/merge.js +1 -10
- package/dist/sdk/mutation-events.js +1 -292
- package/dist/sdk/mutation-guard.js +1 -216
- package/dist/sdk/notes.js +1 -139
- package/dist/sdk/output-contracts.js +1 -172
- package/dist/sdk/output-projection.js +1 -430
- package/dist/sdk/output-token-accounting.js +1 -140
- package/dist/sdk/output.js +1 -64
- package/dist/sdk/ownership-source.js +1 -21
- package/dist/sdk/package-import-adapters.js +1 -442
- package/dist/sdk/package-migrations.js +1 -20
- package/dist/sdk/package-runtime-options.js +1 -80
- package/dist/sdk/pagination.js +1 -162
- package/dist/sdk/profile.js +1 -454
- package/dist/sdk/provenance.js +1 -258
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/activity.js +1 -401
- package/dist/sdk/query/aggregate.d.ts +16 -0
- package/dist/sdk/query/aggregate.js +1 -390
- package/dist/sdk/query/calendar.js +1 -964
- package/dist/sdk/query/complete-list.js +1 -215
- package/dist/sdk/query/context.js +1 -1702
- package/dist/sdk/query/duplicate-candidates.js +1 -70
- package/dist/sdk/query/get.js +1 -450
- package/dist/sdk/query/history.js +1 -186
- package/dist/sdk/query/item-filter-options.js +1 -9
- package/dist/sdk/query/light-metadata.js +1 -18
- package/dist/sdk/query/list-filter-shared.js +1 -81
- package/dist/sdk/query/list.js +1 -1304
- package/dist/sdk/query/multi-value-filters.js +1 -78
- package/dist/sdk/query/next.js +1 -513
- package/dist/sdk/query/parsers.js +1 -44
- package/dist/sdk/query/projection-contracts.js +1 -184
- package/dist/sdk/query/search-contracts.js +1 -230
- package/dist/sdk/query/search-pagination.js +1 -35
- package/dist/sdk/query/search-rendering.js +1 -105
- package/dist/sdk/query/search.js +2 -1987
- package/dist/sdk/query.js +1 -35
- package/dist/sdk/read-output/continuation.js +1 -194
- package/dist/sdk/read-output-budget.js +1 -135
- package/dist/sdk/read-output-contracts.js +1 -1225
- package/dist/sdk/read-output-rows.js +1 -186
- package/dist/sdk/read-output-session.js +1 -208
- package/dist/sdk/relationship-analytics.js +1 -410
- package/dist/sdk/relationship-context.js +1 -284
- package/dist/sdk/relationship-history.js +4 -519
- package/dist/sdk/relationship-kinds/contract.js +1 -22
- package/dist/sdk/relationship-migration.js +1 -77
- package/dist/sdk/relationships.js +1 -579
- package/dist/sdk/reproducibility/process.js +1 -87
- package/dist/sdk/runtime-action-aliases.js +1 -59
- package/dist/sdk/runtime-extended-actions.js +1 -177
- package/dist/sdk/runtime-input.js +1 -614
- package/dist/sdk/runtime-primitives.js +1 -84
- package/dist/sdk/runtime-public-contracts.js +1 -4
- package/dist/sdk/runtime-stats-options.js +1 -38
- package/dist/sdk/runtime.js +1 -1928
- package/dist/sdk/scheduling-shortcuts.js +1 -63
- package/dist/sdk/schema-migration.js +3 -856
- package/dist/sdk/schema.js +1 -1376
- package/dist/sdk/search-refresh-worker.js +1 -18
- package/dist/sdk/similarity-scoring.js +1 -53
- package/dist/sdk/similarity.js +1 -326
- package/dist/sdk/start-task-status.js +1 -14
- package/dist/sdk/stats.js +1 -270
- package/dist/sdk/structured-mutations.js +1 -580
- package/dist/sdk/telemetry-flush.js +1 -13
- package/dist/sdk/telemetry.js +1 -405
- package/dist/sdk/templates.js +2 -292
- package/dist/sdk/test/batch.js +2 -509
- package/dist/sdk/test/entry.js +1 -70
- package/dist/sdk/test/execution.js +6 -2211
- package/dist/sdk/test/linked-command-detection.js +1 -546
- package/dist/sdk/test/measurements.js +1 -91
- package/dist/sdk/test/parsers.js +1 -545
- package/dist/sdk/test/runs.js +1 -193
- package/dist/sdk/test/trust.js +2 -206
- package/dist/sdk/testing.js +4 -1391
- package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
- package/dist/sdk/traceability/source-traceability.js +1 -292
- package/dist/sdk/tracker-root-discovery.js +1 -9
- package/dist/sdk/workspace-contracts-cache.js +1 -28
- package/dist/sdk/workspace-contracts.js +1 -33
- package/dist/sdk/workspace-memory.js +2 -318
- package/dist/sdk/workspace-recipe.js +1 -71
- package/dist/sdk/workspace-snapshot.js +4 -613
- package/dist/sdk/workspace-transaction-gc.js +1 -149
- package/dist/sdk/workspace-transaction.js +2 -363
- package/dist/sdk/workspace.js +3 -127
- package/dist/types/index.js +1 -9
- package/dist/types.js +1 -245
- package/docs/AGENT_GUIDE.md +1 -1
- package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
- package/docs/EXTENSIONS.md +1 -0
- package/docs/HISTORY_MAINTENANCE.md +125 -0
- package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
- package/docs/PACKAGE_EVIDENCE.md +92 -0
- package/docs/PLANNING_MEASUREMENTS.md +183 -0
- package/docs/README.md +3 -0
- package/docs/RELEASING.md +1 -0
- package/docs/SCRIPTING.md +21 -0
- package/docs/TESTING.md +23 -0
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +5 -5
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +2 -2
- package/marketplace.json +2 -2
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/scripts/finalize-build.mjs +45 -3
- package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
- package/dist/cli-bundle/chunks/chunk-BAX2BYUW.js +0 -2111
- package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
- package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
- package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
- package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
- package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
- package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
- package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
- package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
- package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
- package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
- package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
- package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
- package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
|
@@ -1,520 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* optimistic concurrency, deterministic replay, snapshots, and cursor pages.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="bb5dfa6f-b60f-55f2-ae17-3dbcaaff1b47")}catch(e){}}();
|
|
9
|
-
import { createQueryFingerprint, decodeQueryCursorState, paginateQueryRows, } from "./pagination.js";
|
|
10
|
-
import { constants } from "node:fs";
|
|
11
|
-
import { lstat, mkdir, open } from "node:fs/promises";
|
|
12
|
-
import path from "node:path";
|
|
13
|
-
import { acquireLock } from "../core/lock/lock.js";
|
|
14
|
-
import { isFileMissingError, writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
15
|
-
import { stableStringify } from "../core/shared/serialization.js";
|
|
16
|
-
import { RelationshipGraph, createRelationshipKindRegistry, } from "./relationships.js";
|
|
17
|
-
function requiredText(value, field) {
|
|
18
|
-
if (typeof value !== "string" || value.trim().length === 0)
|
|
19
|
-
throw new TypeError(`Relationship event ${field} must be non-empty`);
|
|
20
|
-
return value.trim();
|
|
21
|
-
}
|
|
22
|
-
function edgeIdentity(edge, registry) {
|
|
23
|
-
const definition = registry.require(edge.kind);
|
|
24
|
-
const endpoints = definition.direction === "undirected"
|
|
25
|
-
? [edge.source, edge.target].sort().join("\u0000")
|
|
26
|
-
: `${edge.source}\u0000${edge.target}`;
|
|
27
|
-
return `${definition.kind}\u0000${endpoints}`;
|
|
28
|
-
}
|
|
29
|
-
function freezeEdge(edge) {
|
|
30
|
-
return Object.freeze({
|
|
31
|
-
...edge,
|
|
32
|
-
...(edge.payload === undefined
|
|
33
|
-
? {}
|
|
34
|
-
: { payload: Object.freeze(structuredClone(edge.payload)) }),
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
function assertCardinality(candidate, excludeRelationshipId, registry, indexes) {
|
|
38
|
-
const definition = registry.require(candidate.kind);
|
|
39
|
-
const outgoingOwner = indexes.outgoingOne.get(`${definition.kind}\u0000${candidate.source}`);
|
|
40
|
-
if (outgoingOwner !== undefined && outgoingOwner !== excludeRelationshipId)
|
|
41
|
-
throw new TypeError(`Relationship outgoing cardinality exceeded for ${definition.kind}`);
|
|
42
|
-
const incomingOwner = indexes.incomingOne.get(`${definition.kind}\u0000${candidate.target}`);
|
|
43
|
-
if (incomingOwner !== undefined && incomingOwner !== excludeRelationshipId)
|
|
44
|
-
throw new TypeError(`Relationship incoming cardinality exceeded for ${definition.kind}`);
|
|
45
|
-
const identity = edgeIdentity(candidate, registry);
|
|
46
|
-
const identityOwner = indexes.identities.get(identity);
|
|
47
|
-
if (identityOwner !== undefined && identityOwner !== excludeRelationshipId)
|
|
48
|
-
throw new TypeError(`Relationship edge already active: ${identity}`);
|
|
49
|
-
}
|
|
50
|
-
function replayEvents(events) {
|
|
51
|
-
const active = new Map();
|
|
52
|
-
for (const event of events) {
|
|
53
|
-
if (event.action === "remove")
|
|
54
|
-
active.delete(event.relationshipId);
|
|
55
|
-
else
|
|
56
|
-
active.set(event.relationshipId, event.edge);
|
|
57
|
-
}
|
|
58
|
-
return active;
|
|
59
|
-
}
|
|
60
|
-
function normalizeEventHeader(input, currentVersion, eventIds) {
|
|
61
|
-
if (input.expectedVersion !== undefined &&
|
|
62
|
-
input.expectedVersion !== currentVersion)
|
|
63
|
-
throw new TypeError(`Relationship event version conflict: expected ${input.expectedVersion}, current ${currentVersion}`);
|
|
64
|
-
const eventId = requiredText(input.eventId, "eventId");
|
|
65
|
-
if (eventIds.has(eventId))
|
|
66
|
-
throw new TypeError(`Relationship event already exists: ${eventId}`);
|
|
67
|
-
if (input.action !== "add" &&
|
|
68
|
-
input.action !== "remove" &&
|
|
69
|
-
input.action !== "supersede")
|
|
70
|
-
throw new TypeError(`Unknown relationship event action: ${input.action}`);
|
|
71
|
-
if (!Number.isFinite(Date.parse(input.timestamp)))
|
|
72
|
-
throw new TypeError("Relationship event timestamp must be valid");
|
|
73
|
-
return {
|
|
74
|
-
eventId,
|
|
75
|
-
relationshipId: requiredText(input.relationshipId, "relationshipId"),
|
|
76
|
-
author: requiredText(input.author, "author"),
|
|
77
|
-
timestamp: new Date(input.timestamp).toISOString(),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function resolveMutationEdge(input, relationshipId, active, nodes, registry, indexes) {
|
|
81
|
-
const isActive = active.has(relationshipId);
|
|
82
|
-
if (input.action === "add" && isActive)
|
|
83
|
-
throw new TypeError(`Relationship is already active: ${relationshipId}`);
|
|
84
|
-
if (input.action !== "add" && !isActive)
|
|
85
|
-
throw new TypeError(`Relationship is not active: ${relationshipId}`);
|
|
86
|
-
if (input.action === "remove")
|
|
87
|
-
return undefined;
|
|
88
|
-
if (!input.edge)
|
|
89
|
-
throw new TypeError(`Relationship ${input.action} event requires an edge`);
|
|
90
|
-
const source = typeof input.edge.source === "string" ? input.edge.source.trim() : "";
|
|
91
|
-
const target = typeof input.edge.target === "string" ? input.edge.target.trim() : "";
|
|
92
|
-
if (!nodes.has(source) || !nodes.has(target))
|
|
93
|
-
throw new TypeError(`Relationship endpoint not found: ${source} -> ${target}`);
|
|
94
|
-
const canonical = new RelationshipGraph([source, target], [input.edge], registry).edges()[0];
|
|
95
|
-
assertCardinality(canonical, relationshipId, registry, indexes);
|
|
96
|
-
return freezeEdge(canonical);
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Append-only in-memory reference ledger. Durable adapters can persist the
|
|
100
|
-
* returned immutable events while reusing the same replay and validation model.
|
|
101
|
-
*/
|
|
102
|
-
export class RelationshipEventLog {
|
|
103
|
-
#nodes;
|
|
104
|
-
#registry;
|
|
105
|
-
#events = [];
|
|
106
|
-
#eventIds = new Set();
|
|
107
|
-
#active = new Map();
|
|
108
|
-
#cardinalityIndexes = {
|
|
109
|
-
identities: new Map(),
|
|
110
|
-
outgoingOne: new Map(),
|
|
111
|
-
incomingOne: new Map(),
|
|
112
|
-
};
|
|
113
|
-
/** Create an empty relationship ledger for a fixed node universe. */
|
|
114
|
-
constructor(nodes, options = {}) {
|
|
115
|
-
this.#nodes = new Set([...nodes]
|
|
116
|
-
.filter((node) => typeof node === "string")
|
|
117
|
-
.map((node) => node.trim())
|
|
118
|
-
.filter(Boolean));
|
|
119
|
-
this.#registry = options.registry ?? createRelationshipKindRegistry();
|
|
120
|
-
}
|
|
121
|
-
/** Current append sequence. */
|
|
122
|
-
get version() {
|
|
123
|
-
return this.#events.length;
|
|
124
|
-
}
|
|
125
|
-
/** Return an immutable copy of the full event stream. */
|
|
126
|
-
events() {
|
|
127
|
-
return Object.freeze([...this.#events]);
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Iterate a stable event prefix in immutable, bounded batches. Consumers can
|
|
131
|
-
* build streaming projections without copying or exposing the mutable ledger.
|
|
132
|
-
* `fromVersion === toVersion + 1` is the intentional empty checkpoint range;
|
|
133
|
-
* larger watermarks are rejected as invalid for the selected prefix.
|
|
134
|
-
*/
|
|
135
|
-
*stream(options = {}) {
|
|
136
|
-
const fromVersion = options.fromVersion ?? 1;
|
|
137
|
-
const toVersion = options.toVersion ?? this.version;
|
|
138
|
-
const batchSize = options.batchSize ?? 100;
|
|
139
|
-
if (!Number.isInteger(fromVersion) || fromVersion < 1)
|
|
140
|
-
throw new TypeError("Relationship event stream fromVersion must be positive");
|
|
141
|
-
if (!Number.isInteger(toVersion) ||
|
|
142
|
-
toVersion < 0 ||
|
|
143
|
-
toVersion > this.version)
|
|
144
|
-
throw new TypeError(`Relationship event stream toVersion out of range: ${toVersion}`);
|
|
145
|
-
if (!Number.isInteger(batchSize) || batchSize < 1)
|
|
146
|
-
throw new TypeError("Relationship event stream batchSize must be positive");
|
|
147
|
-
if (fromVersion > toVersion + 1)
|
|
148
|
-
throw new TypeError("Relationship event stream fromVersion exceeds the selected prefix");
|
|
149
|
-
for (let offset = fromVersion - 1; offset < toVersion; offset += batchSize) {
|
|
150
|
-
yield Object.freeze(this.#events.slice(offset, Math.min(offset + batchSize, toVersion)));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
/** Fold a selected immutable event prefix into caller-owned domain state. */
|
|
154
|
-
project(initialState, reducer, options = {}) {
|
|
155
|
-
if (typeof reducer !== "function")
|
|
156
|
-
throw new TypeError("Relationship event projection requires a reducer");
|
|
157
|
-
let state = initialState;
|
|
158
|
-
let processed = 0;
|
|
159
|
-
let finalEvent;
|
|
160
|
-
for (const batch of this.stream({ ...options, batchSize: 256 })) {
|
|
161
|
-
for (const event of batch) {
|
|
162
|
-
state = reducer(state, event);
|
|
163
|
-
processed += 1;
|
|
164
|
-
finalEvent = event;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return Object.freeze({
|
|
168
|
-
state,
|
|
169
|
-
version: finalEvent?.sequence ?? Math.max(0, (options.fromVersion ?? 1) - 1),
|
|
170
|
-
processed,
|
|
171
|
-
...(finalEvent === undefined ? {} : { asOf: finalEvent.timestamp }),
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
/** Add one active relationship to constant-time validation indexes. */
|
|
175
|
-
#indexActive(relationshipId, edge) {
|
|
176
|
-
const definition = this.#registry.require(edge.kind);
|
|
177
|
-
this.#cardinalityIndexes.identities.set(edgeIdentity(edge, this.#registry), relationshipId);
|
|
178
|
-
if (definition.outgoing === "one")
|
|
179
|
-
this.#cardinalityIndexes.outgoingOne.set(`${definition.kind}\u0000${edge.source}`, relationshipId);
|
|
180
|
-
if (definition.incoming === "one")
|
|
181
|
-
this.#cardinalityIndexes.incomingOne.set(`${definition.kind}\u0000${edge.target}`, relationshipId);
|
|
182
|
-
}
|
|
183
|
-
/** Remove one superseded or deleted relationship from validation indexes. */
|
|
184
|
-
#unindexActive(edge) {
|
|
185
|
-
const definition = this.#registry.require(edge.kind);
|
|
186
|
-
this.#cardinalityIndexes.identities.delete(edgeIdentity(edge, this.#registry));
|
|
187
|
-
if (definition.outgoing === "one")
|
|
188
|
-
this.#cardinalityIndexes.outgoingOne.delete(`${definition.kind}\u0000${edge.source}`);
|
|
189
|
-
if (definition.incoming === "one")
|
|
190
|
-
this.#cardinalityIndexes.incomingOne.delete(`${definition.kind}\u0000${edge.target}`);
|
|
191
|
-
}
|
|
192
|
-
/** Validate and append one attributable relationship mutation. */
|
|
193
|
-
append(input) {
|
|
194
|
-
const header = normalizeEventHeader(input, this.version, this.#eventIds);
|
|
195
|
-
const previous = this.#active.get(header.relationshipId);
|
|
196
|
-
const edge = resolveMutationEdge(input, header.relationshipId, this.#active, this.#nodes, this.#registry, this.#cardinalityIndexes);
|
|
197
|
-
const event = Object.freeze({
|
|
198
|
-
eventId: header.eventId,
|
|
199
|
-
relationshipId: header.relationshipId,
|
|
200
|
-
action: input.action,
|
|
201
|
-
...(edge === undefined ? {} : { edge }),
|
|
202
|
-
author: header.author,
|
|
203
|
-
timestamp: header.timestamp,
|
|
204
|
-
...(input.reason?.trim() ? { reason: input.reason.trim() } : {}),
|
|
205
|
-
sequence: this.version + 1,
|
|
206
|
-
});
|
|
207
|
-
this.#events.push(event);
|
|
208
|
-
this.#eventIds.add(header.eventId);
|
|
209
|
-
if (previous)
|
|
210
|
-
this.#unindexActive(previous);
|
|
211
|
-
if (input.action === "remove")
|
|
212
|
-
this.#active.delete(header.relationshipId);
|
|
213
|
-
else {
|
|
214
|
-
this.#active.set(header.relationshipId, edge);
|
|
215
|
-
this.#indexActive(header.relationshipId, edge);
|
|
216
|
-
}
|
|
217
|
-
return event;
|
|
218
|
-
}
|
|
219
|
-
/** Materialize an exact point-in-time graph without mutating the ledger. */
|
|
220
|
-
snapshot(options = {}) {
|
|
221
|
-
if (options.atVersion !== undefined && options.atTimestamp !== undefined)
|
|
222
|
-
throw new TypeError("Relationship snapshot accepts one target");
|
|
223
|
-
let included;
|
|
224
|
-
if (options.atTimestamp !== undefined) {
|
|
225
|
-
const timestamp = Date.parse(options.atTimestamp);
|
|
226
|
-
if (!Number.isFinite(timestamp))
|
|
227
|
-
throw new TypeError("Relationship snapshot timestamp must be valid");
|
|
228
|
-
included = this.#events.filter((event) => Date.parse(event.timestamp) <= timestamp);
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
const version = options.atVersion ?? this.version;
|
|
232
|
-
if (!Number.isInteger(version) || version < 0 || version > this.version)
|
|
233
|
-
throw new TypeError(`Relationship snapshot version out of range: ${version}`);
|
|
234
|
-
included = this.#events.slice(0, version);
|
|
235
|
-
}
|
|
236
|
-
const active = replayEvents(included);
|
|
237
|
-
const graph = new RelationshipGraph(this.#nodes, active.values(), this.#registry);
|
|
238
|
-
return Object.freeze({
|
|
239
|
-
version: included.at(-1)?.sequence ?? 0,
|
|
240
|
-
...(included.at(-1) ? { asOf: included.at(-1).timestamp } : {}),
|
|
241
|
-
edges: graph.edges(),
|
|
242
|
-
graph,
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
/** Page the immutable event stream with a cursor bound to this log version. */
|
|
246
|
-
page(options) {
|
|
247
|
-
if (!Number.isInteger(options.limit) || options.limit < 1)
|
|
248
|
-
throw new TypeError("Relationship event page limit must be positive");
|
|
249
|
-
const fingerprint = createQueryFingerprint("relationship-events", {
|
|
250
|
-
order: "append-sequence",
|
|
251
|
-
});
|
|
252
|
-
const snapshot = options.cursor === undefined
|
|
253
|
-
? this.version
|
|
254
|
-
: Number(decodeQueryCursorState(options.cursor, fingerprint).snapshot);
|
|
255
|
-
if (!Number.isSafeInteger(snapshot) ||
|
|
256
|
-
snapshot < 0 ||
|
|
257
|
-
snapshot > this.version)
|
|
258
|
-
throw new TypeError("Relationship event cursor snapshot version is invalid");
|
|
259
|
-
const page = paginateQueryRows(this.#events.slice(0, snapshot), {
|
|
260
|
-
cursor: options.cursor,
|
|
261
|
-
fingerprint,
|
|
262
|
-
limit: options.limit,
|
|
263
|
-
readId: (event) => event.eventId,
|
|
264
|
-
snapshot: String(snapshot),
|
|
265
|
-
});
|
|
266
|
-
return {
|
|
267
|
-
version: snapshot,
|
|
268
|
-
events: page.rows,
|
|
269
|
-
hasMore: page.has_more,
|
|
270
|
-
...(page.next_cursor ? { nextCursor: page.next_cursor } : {}),
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
const RELATIONSHIP_STORE_LOCK_ID = "relationship-event-store";
|
|
275
|
-
const RELATIONSHIP_NOFOLLOW_FLAG = constants.O_NOFOLLOW;
|
|
276
|
-
function acquireRelationshipStoreLock(pmRoot) {
|
|
277
|
-
return acquireLock(pmRoot, RELATIONSHIP_STORE_LOCK_ID, 30, `relationship-store:${process.pid}`, false, false, 3_000);
|
|
278
|
-
}
|
|
279
|
-
async function resolveRelationshipEventStorePath(pmRoot, relativePath = "relationships/events.jsonl") {
|
|
280
|
-
const root = path.resolve(pmRoot);
|
|
281
|
-
const target = path.resolve(root, relativePath);
|
|
282
|
-
const relative = path.relative(root, target);
|
|
283
|
-
if (relative.length === 0)
|
|
284
|
-
throw new TypeError("Relationship event path must name a file within the tracker root");
|
|
285
|
-
if (relative === ".." ||
|
|
286
|
-
relative.startsWith(`..${path.sep}`) ||
|
|
287
|
-
path.isAbsolute(relative))
|
|
288
|
-
throw new TypeError("Relationship event path must stay within the tracker root");
|
|
289
|
-
await mkdir(root, { recursive: true });
|
|
290
|
-
const rootStats = await lstat(root);
|
|
291
|
-
if (rootStats.isSymbolicLink())
|
|
292
|
-
throw new TypeError("Relationship event tracker root must not be a symbolic link");
|
|
293
|
-
let current = root;
|
|
294
|
-
for (const segment of relative.split(path.sep)) {
|
|
295
|
-
current = path.join(current, segment);
|
|
296
|
-
try {
|
|
297
|
-
if ((await lstat(current)).isSymbolicLink())
|
|
298
|
-
throw new TypeError("Relationship event path must not contain symbolic links");
|
|
299
|
-
}
|
|
300
|
-
catch (error) {
|
|
301
|
-
if (isFileMissingError(error))
|
|
302
|
-
break;
|
|
303
|
-
throw error;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
return target;
|
|
307
|
-
}
|
|
308
|
-
async function loadRelationshipEventLog(target, nodes, registry) {
|
|
309
|
-
const log = new RelationshipEventLog(nodes, { registry });
|
|
310
|
-
let raw;
|
|
311
|
-
let handle;
|
|
312
|
-
try {
|
|
313
|
-
handle = await open(target, constants.O_RDONLY | RELATIONSHIP_NOFOLLOW_FLAG);
|
|
314
|
-
raw = await handle.readFile("utf8");
|
|
315
|
-
}
|
|
316
|
-
catch (error) {
|
|
317
|
-
if (isFileMissingError(error))
|
|
318
|
-
return { log, raw: "" };
|
|
319
|
-
throw error;
|
|
320
|
-
}
|
|
321
|
-
finally {
|
|
322
|
-
await handle?.close();
|
|
323
|
-
}
|
|
324
|
-
const lines = raw.split("\n");
|
|
325
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
326
|
-
const line = lines[index].trim();
|
|
327
|
-
if (!line)
|
|
328
|
-
continue;
|
|
329
|
-
let stored;
|
|
330
|
-
try {
|
|
331
|
-
stored = JSON.parse(line);
|
|
332
|
-
}
|
|
333
|
-
catch {
|
|
334
|
-
throw new TypeError(`Invalid relationship event JSONL at line ${index + 1}`);
|
|
335
|
-
}
|
|
336
|
-
if (stored.sequence !== log.version + 1)
|
|
337
|
-
throw new TypeError(`Invalid relationship event sequence at line ${index + 1}`);
|
|
338
|
-
log.append({
|
|
339
|
-
eventId: stored.eventId,
|
|
340
|
-
relationshipId: stored.relationshipId,
|
|
341
|
-
action: stored.action,
|
|
342
|
-
...(stored.edge === undefined ? {} : { edge: stored.edge }),
|
|
343
|
-
author: stored.author,
|
|
344
|
-
timestamp: stored.timestamp,
|
|
345
|
-
...(stored.reason === undefined ? {} : { reason: stored.reason }),
|
|
346
|
-
expectedVersion: log.version,
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
return { log, raw };
|
|
350
|
-
}
|
|
351
|
-
/** Return whether an existing immutable event exactly represents one input. */
|
|
352
|
-
function relationshipEventMatchesInput(event, input, nodes, registry) {
|
|
353
|
-
const timestamp = Date.parse(input.timestamp);
|
|
354
|
-
let edge;
|
|
355
|
-
if (input.action !== "remove" && input.edge !== undefined)
|
|
356
|
-
edge = new RelationshipGraph(nodes, [input.edge], registry).edges()[0];
|
|
357
|
-
return (event.eventId === input.eventId.trim() &&
|
|
358
|
-
event.relationshipId === input.relationshipId.trim() &&
|
|
359
|
-
event.action === input.action &&
|
|
360
|
-
event.author === input.author.trim() &&
|
|
361
|
-
Number.isFinite(timestamp) &&
|
|
362
|
-
event.timestamp === new Date(timestamp).toISOString() &&
|
|
363
|
-
event.reason === (input.reason?.trim() || undefined) &&
|
|
364
|
-
stableStringify(event.edge) === stableStringify(edge));
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Lock-serialized durable JSONL adapter for {@link RelationshipEventLog}.
|
|
368
|
-
* Every append replays the current stream while holding the workspace lock, so
|
|
369
|
-
* independent processes share optimistic versions without lost updates.
|
|
370
|
-
*/
|
|
371
|
-
export class RelationshipEventStore {
|
|
372
|
-
#pmRoot;
|
|
373
|
-
#nodes;
|
|
374
|
-
#registry;
|
|
375
|
-
#path;
|
|
376
|
-
#log;
|
|
377
|
-
constructor(options, nodes, target, log) {
|
|
378
|
-
this.#pmRoot = options.pmRoot;
|
|
379
|
-
this.#nodes = nodes;
|
|
380
|
-
this.#registry = options.registry;
|
|
381
|
-
this.#path = target;
|
|
382
|
-
this.#log = log;
|
|
383
|
-
}
|
|
384
|
-
/** Open and validate an existing stream or create an empty store view. */
|
|
385
|
-
static async open(options) {
|
|
386
|
-
const nodes = Object.freeze([...options.nodes]);
|
|
387
|
-
const target = await resolveRelationshipEventStorePath(options.pmRoot, options.relativePath);
|
|
388
|
-
const release = await acquireRelationshipStoreLock(options.pmRoot);
|
|
389
|
-
try {
|
|
390
|
-
await resolveRelationshipEventStorePath(options.pmRoot, target);
|
|
391
|
-
const { log } = await loadRelationshipEventLog(target, nodes, options.registry);
|
|
392
|
-
return new RelationshipEventStore(options, nodes, target, log);
|
|
393
|
-
}
|
|
394
|
-
finally {
|
|
395
|
-
await release();
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
/** Absolute JSONL path, exposed for diagnostics and backup tooling. */
|
|
399
|
-
get path() {
|
|
400
|
-
return this.#path;
|
|
401
|
-
}
|
|
402
|
-
/** Refresh from durable history and return the current validated append sequence. */
|
|
403
|
-
async currentVersion() {
|
|
404
|
-
this.#log = await this.#refreshFromDurableHistory();
|
|
405
|
-
return this.#log.version;
|
|
406
|
-
}
|
|
407
|
-
/** Append one event after refreshing under the shared workspace lock. */
|
|
408
|
-
async append(input) {
|
|
409
|
-
const release = await acquireRelationshipStoreLock(this.#pmRoot);
|
|
410
|
-
try {
|
|
411
|
-
const target = await resolveRelationshipEventStorePath(this.#pmRoot, this.#path);
|
|
412
|
-
const { log: refreshed } = await loadRelationshipEventLog(target, this.#nodes, this.#registry);
|
|
413
|
-
const event = refreshed.append(input);
|
|
414
|
-
await mkdir(path.dirname(target), { recursive: true });
|
|
415
|
-
await resolveRelationshipEventStorePath(this.#pmRoot, target);
|
|
416
|
-
const handle = await open(target, constants.O_APPEND |
|
|
417
|
-
constants.O_CREAT |
|
|
418
|
-
constants.O_WRONLY |
|
|
419
|
-
RELATIONSHIP_NOFOLLOW_FLAG);
|
|
420
|
-
try {
|
|
421
|
-
await handle.appendFile(`${JSON.stringify(event)}\n`, "utf8");
|
|
422
|
-
}
|
|
423
|
-
finally {
|
|
424
|
-
await handle.close();
|
|
425
|
-
}
|
|
426
|
-
this.#log = refreshed;
|
|
427
|
-
return event;
|
|
428
|
-
}
|
|
429
|
-
finally {
|
|
430
|
-
await release();
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* Validate and publish a relationship-event batch as one durable replacement.
|
|
435
|
-
* The shared writer lock covers refresh, collision checks, full in-memory
|
|
436
|
-
* validation, and atomic rename. A validation or filesystem failure therefore
|
|
437
|
-
* leaves the previous JSONL stream byte-for-byte unchanged. This path is
|
|
438
|
-
* intended for migrations and bulk imports; latency-sensitive single events
|
|
439
|
-
* should continue to use {@link append} and its O_APPEND write.
|
|
440
|
-
*/
|
|
441
|
-
async appendBatch(inputs, options = {}) {
|
|
442
|
-
const release = await acquireRelationshipStoreLock(this.#pmRoot);
|
|
443
|
-
try {
|
|
444
|
-
const target = await resolveRelationshipEventStorePath(this.#pmRoot, this.#path);
|
|
445
|
-
const { log: refreshed, raw } = await loadRelationshipEventLog(target, this.#nodes, this.#registry);
|
|
446
|
-
const versionBefore = refreshed.version;
|
|
447
|
-
const existing = new Map(refreshed.events().map((event) => [event.eventId, event]));
|
|
448
|
-
const appended = [];
|
|
449
|
-
const skippedEventIds = [];
|
|
450
|
-
for (const input of inputs) {
|
|
451
|
-
const eventId = input.eventId.trim();
|
|
452
|
-
const stored = existing.get(eventId);
|
|
453
|
-
if (stored !== undefined) {
|
|
454
|
-
if (options.existingEventPolicy === "skip_identical" &&
|
|
455
|
-
relationshipEventMatchesInput(stored, input, this.#nodes, this.#registry)) {
|
|
456
|
-
skippedEventIds.push(stored.eventId);
|
|
457
|
-
continue;
|
|
458
|
-
}
|
|
459
|
-
if (options.existingEventPolicy === "skip_identical")
|
|
460
|
-
throw new TypeError(`Relationship event id collision with different content: ${eventId}`);
|
|
461
|
-
}
|
|
462
|
-
const event = refreshed.append(input);
|
|
463
|
-
existing.set(event.eventId, event);
|
|
464
|
-
appended.push(event);
|
|
465
|
-
}
|
|
466
|
-
if (appended.length > 0) {
|
|
467
|
-
const prefix = raw.length === 0 || raw.endsWith("\n") ? raw : `${raw}\n`;
|
|
468
|
-
await mkdir(path.dirname(target), { recursive: true });
|
|
469
|
-
await resolveRelationshipEventStorePath(this.#pmRoot, target);
|
|
470
|
-
await writeFileAtomic(target, `${prefix}${appended.map((event) => JSON.stringify(event)).join("\n")}\n`);
|
|
471
|
-
}
|
|
472
|
-
this.#log = refreshed;
|
|
473
|
-
return Object.freeze({
|
|
474
|
-
version_before: versionBefore,
|
|
475
|
-
version_after: refreshed.version,
|
|
476
|
-
appended: Object.freeze(appended),
|
|
477
|
-
skipped_event_ids: Object.freeze(skippedEventIds),
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
finally {
|
|
481
|
-
await release();
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
/** Refresh from durable history and materialize an exact validated snapshot. */
|
|
485
|
-
async snapshot(options = {}) {
|
|
486
|
-
this.#log = await this.#refreshFromDurableHistory();
|
|
487
|
-
return this.#log.snapshot(options);
|
|
488
|
-
}
|
|
489
|
-
/** Refresh from durable history and page immutable events. */
|
|
490
|
-
async page(options) {
|
|
491
|
-
this.#log = await this.#refreshFromDurableHistory();
|
|
492
|
-
return this.#log.page(options);
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* Refresh once under the shared store lock, then stream a coherent immutable
|
|
496
|
-
* prefix without holding the writer lock while the consumer processes batches.
|
|
497
|
-
*/
|
|
498
|
-
async *stream(options = {}) {
|
|
499
|
-
this.#log = await this.#refreshFromDurableHistory();
|
|
500
|
-
yield* this.#log.stream(options);
|
|
501
|
-
}
|
|
502
|
-
/** Refresh once and fold a coherent durable prefix into application state. */
|
|
503
|
-
async project(initialState, reducer, options = {}) {
|
|
504
|
-
this.#log = await this.#refreshFromDurableHistory();
|
|
505
|
-
return this.#log.project(initialState, reducer, options);
|
|
506
|
-
}
|
|
507
|
-
/** Serialize a durable refresh with writers so readers never observe a torn JSONL tail. */
|
|
508
|
-
async #refreshFromDurableHistory() {
|
|
509
|
-
const release = await acquireRelationshipStoreLock(this.#pmRoot);
|
|
510
|
-
try {
|
|
511
|
-
const target = await resolveRelationshipEventStorePath(this.#pmRoot, this.#path);
|
|
512
|
-
return (await loadRelationshipEventLog(target, this.#nodes, this.#registry)).log;
|
|
513
|
-
}
|
|
514
|
-
finally {
|
|
515
|
-
await release();
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
}
|
|
1
|
+
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e57a9bca-1190-5ffd-bb7d-d76a22fc9e57")}catch(e2){}})();import{createQueryFingerprint,decodeQueryCursorState,paginateQueryRows}from"./pagination.js";import{constants}from"node:fs";import{lstat,mkdir,open}from"node:fs/promises";import path from"node:path";import{acquireLock}from"../core/lock/lock.js";import{isFileMissingError,writeFileAtomic}from"../core/fs/fs-utils.js";import{stableStringify}from"../core/shared/serialization.js";import{RelationshipGraph,createRelationshipKindRegistry}from"./relationships.js";function requiredText(value,field){if(typeof value!=="string"||value.trim().length===0)throw new TypeError(`Relationship event ${field} must be non-empty`);return value.trim()}function edgeIdentity(edge,registry){const definition=registry.require(edge.kind);const endpoints=definition.direction==="undirected"?[edge.source,edge.target].sort().join("\0"):`${edge.source}\0${edge.target}`;return`${definition.kind}\0${endpoints}`}function freezeEdge(edge){return Object.freeze({...edge,...edge.payload===void 0?{}:{payload:Object.freeze(structuredClone(edge.payload))}})}function assertCardinality(candidate,excludeRelationshipId,registry,indexes){const definition=registry.require(candidate.kind);const outgoingOwner=indexes.outgoingOne.get(`${definition.kind}\0${candidate.source}`);if(outgoingOwner!==void 0&&outgoingOwner!==excludeRelationshipId)throw new TypeError(`Relationship outgoing cardinality exceeded for ${definition.kind}`);const incomingOwner=indexes.incomingOne.get(`${definition.kind}\0${candidate.target}`);if(incomingOwner!==void 0&&incomingOwner!==excludeRelationshipId)throw new TypeError(`Relationship incoming cardinality exceeded for ${definition.kind}`);const identity=edgeIdentity(candidate,registry);const identityOwner=indexes.identities.get(identity);if(identityOwner!==void 0&&identityOwner!==excludeRelationshipId)throw new TypeError(`Relationship edge already active: ${identity}`)}function replayEvents(events){const active=new Map;for(const event of events){if(event.action==="remove")active.delete(event.relationshipId);else active.set(event.relationshipId,event.edge)}return active}function normalizeEventHeader(input,currentVersion,eventIds){if(input.expectedVersion!==void 0&&input.expectedVersion!==currentVersion)throw new TypeError(`Relationship event version conflict: expected ${input.expectedVersion}, current ${currentVersion}`);const eventId=requiredText(input.eventId,"eventId");if(eventIds.has(eventId))throw new TypeError(`Relationship event already exists: ${eventId}`);if(input.action!=="add"&&input.action!=="remove"&&input.action!=="supersede")throw new TypeError(`Unknown relationship event action: ${input.action}`);if(!Number.isFinite(Date.parse(input.timestamp)))throw new TypeError("Relationship event timestamp must be valid");return{eventId,relationshipId:requiredText(input.relationshipId,"relationshipId"),author:requiredText(input.author,"author"),timestamp:new Date(input.timestamp).toISOString()}}function resolveMutationEdge(input,relationshipId,active,nodes,registry,indexes){const isActive=active.has(relationshipId);if(input.action==="add"&&isActive)throw new TypeError(`Relationship is already active: ${relationshipId}`);if(input.action!=="add"&&!isActive)throw new TypeError(`Relationship is not active: ${relationshipId}`);if(input.action==="remove")return void 0;if(!input.edge)throw new TypeError(`Relationship ${input.action} event requires an edge`);const source=typeof input.edge.source==="string"?input.edge.source.trim():"";const target=typeof input.edge.target==="string"?input.edge.target.trim():"";if(!nodes.has(source)||!nodes.has(target))throw new TypeError(`Relationship endpoint not found: ${source} -> ${target}`);const canonical=new RelationshipGraph([source,target],[input.edge],registry).edges()[0];assertCardinality(canonical,relationshipId,registry,indexes);return freezeEdge(canonical)}class RelationshipEventLog{#nodes;#registry;#events=[];#eventIds=new Set;#active=new Map;#cardinalityIndexes={identities:new Map,outgoingOne:new Map,incomingOne:new Map};constructor(nodes,options={}){this.#nodes=new Set([...nodes].filter(node=>typeof node==="string").map(node=>node.trim()).filter(Boolean));this.#registry=options.registry??createRelationshipKindRegistry()}get version(){return this.#events.length}events(){return Object.freeze([...this.#events])}*stream(options={}){const fromVersion=options.fromVersion??1;const toVersion=options.toVersion??this.version;const batchSize=options.batchSize??100;if(!Number.isInteger(fromVersion)||fromVersion<1)throw new TypeError("Relationship event stream fromVersion must be positive");if(!Number.isInteger(toVersion)||toVersion<0||toVersion>this.version)throw new TypeError(`Relationship event stream toVersion out of range: ${toVersion}`);if(!Number.isInteger(batchSize)||batchSize<1)throw new TypeError("Relationship event stream batchSize must be positive");if(fromVersion>toVersion+1)throw new TypeError("Relationship event stream fromVersion exceeds the selected prefix");for(let offset=fromVersion-1;offset<toVersion;offset+=batchSize){yield Object.freeze(this.#events.slice(offset,Math.min(offset+batchSize,toVersion)))}}project(initialState,reducer,options={}){if(typeof reducer!=="function")throw new TypeError("Relationship event projection requires a reducer");let state=initialState;let processed=0;let finalEvent;for(const batch of this.stream({...options,batchSize:256})){for(const event of batch){state=reducer(state,event);processed+=1;finalEvent=event}}return Object.freeze({state,version:finalEvent?.sequence??Math.max(0,(options.fromVersion??1)-1),processed,...finalEvent===void 0?{}:{asOf:finalEvent.timestamp}})}#indexActive(relationshipId,edge){const definition=this.#registry.require(edge.kind);this.#cardinalityIndexes.identities.set(edgeIdentity(edge,this.#registry),relationshipId);if(definition.outgoing==="one")this.#cardinalityIndexes.outgoingOne.set(`${definition.kind}\0${edge.source}`,relationshipId);if(definition.incoming==="one")this.#cardinalityIndexes.incomingOne.set(`${definition.kind}\0${edge.target}`,relationshipId)}#unindexActive(edge){const definition=this.#registry.require(edge.kind);this.#cardinalityIndexes.identities.delete(edgeIdentity(edge,this.#registry));if(definition.outgoing==="one")this.#cardinalityIndexes.outgoingOne.delete(`${definition.kind}\0${edge.source}`);if(definition.incoming==="one")this.#cardinalityIndexes.incomingOne.delete(`${definition.kind}\0${edge.target}`)}append(input){const header=normalizeEventHeader(input,this.version,this.#eventIds);const previous=this.#active.get(header.relationshipId);const edge=resolveMutationEdge(input,header.relationshipId,this.#active,this.#nodes,this.#registry,this.#cardinalityIndexes);const event=Object.freeze({eventId:header.eventId,relationshipId:header.relationshipId,action:input.action,...edge===void 0?{}:{edge},author:header.author,timestamp:header.timestamp,...input.reason?.trim()?{reason:input.reason.trim()}:{},sequence:this.version+1});this.#events.push(event);this.#eventIds.add(header.eventId);if(previous)this.#unindexActive(previous);if(input.action==="remove")this.#active.delete(header.relationshipId);else{this.#active.set(header.relationshipId,edge);this.#indexActive(header.relationshipId,edge)}return event}snapshot(options={}){if(options.atVersion!==void 0&&options.atTimestamp!==void 0)throw new TypeError("Relationship snapshot accepts one target");let included;if(options.atTimestamp!==void 0){const timestamp=Date.parse(options.atTimestamp);if(!Number.isFinite(timestamp))throw new TypeError("Relationship snapshot timestamp must be valid");included=this.#events.filter(event=>Date.parse(event.timestamp)<=timestamp)}else{const version=options.atVersion??this.version;if(!Number.isInteger(version)||version<0||version>this.version)throw new TypeError(`Relationship snapshot version out of range: ${version}`);included=this.#events.slice(0,version)}const active=replayEvents(included);const graph=new RelationshipGraph(this.#nodes,active.values(),this.#registry);return Object.freeze({version:included.at(-1)?.sequence??0,...included.at(-1)?{asOf:included.at(-1).timestamp}:{},edges:graph.edges(),graph})}page(options){if(!Number.isInteger(options.limit)||options.limit<1)throw new TypeError("Relationship event page limit must be positive");const fingerprint=createQueryFingerprint("relationship-events",{order:"append-sequence"});const snapshot=options.cursor===void 0?this.version:Number(decodeQueryCursorState(options.cursor,fingerprint).snapshot);if(!Number.isSafeInteger(snapshot)||snapshot<0||snapshot>this.version)throw new TypeError("Relationship event cursor snapshot version is invalid");const page=paginateQueryRows(this.#events.slice(0,snapshot),{cursor:options.cursor,fingerprint,limit:options.limit,readId:event=>event.eventId,snapshot:String(snapshot)});return{version:snapshot,events:page.rows,hasMore:page.has_more,...page.next_cursor?{nextCursor:page.next_cursor}:{}}}}const RELATIONSHIP_STORE_LOCK_ID="relationship-event-store";const RELATIONSHIP_NOFOLLOW_FLAG=constants.O_NOFOLLOW;function acquireRelationshipStoreLock(pmRoot){return acquireLock(pmRoot,RELATIONSHIP_STORE_LOCK_ID,30,`relationship-store:${process.pid}`,false,false,3e3)}async function resolveRelationshipEventStorePath(pmRoot,relativePath="relationships/events.jsonl"){const root=path.resolve(pmRoot);const target=path.resolve(root,relativePath);const relative=path.relative(root,target);if(relative.length===0)throw new TypeError("Relationship event path must name a file within the tracker root");if(relative===".."||relative.startsWith(`..${path.sep}`)||path.isAbsolute(relative))throw new TypeError("Relationship event path must stay within the tracker root");await mkdir(root,{recursive:true});const rootStats=await lstat(root);if(rootStats.isSymbolicLink())throw new TypeError("Relationship event tracker root must not be a symbolic link");let current=root;for(const segment of relative.split(path.sep)){current=path.join(current,segment);try{if((await lstat(current)).isSymbolicLink())throw new TypeError("Relationship event path must not contain symbolic links")}catch(error){if(isFileMissingError(error))break;throw error}}return target}async function loadRelationshipEventLog(target,nodes,registry){const log=new RelationshipEventLog(nodes,{registry});let raw;let handle;try{handle=await open(target,constants.O_RDONLY|RELATIONSHIP_NOFOLLOW_FLAG);raw=await handle.readFile("utf8")}catch(error){if(isFileMissingError(error))return{log,raw:""};throw error}finally{await handle?.close()}const lines=raw.split("\n");for(let index=0;index<lines.length;index+=1){const line=lines[index].trim();if(!line)continue;let stored;try{stored=JSON.parse(line)}catch{throw new TypeError(`Invalid relationship event JSONL at line ${index+1}`)}if(stored.sequence!==log.version+1)throw new TypeError(`Invalid relationship event sequence at line ${index+1}`);log.append({eventId:stored.eventId,relationshipId:stored.relationshipId,action:stored.action,...stored.edge===void 0?{}:{edge:stored.edge},author:stored.author,timestamp:stored.timestamp,...stored.reason===void 0?{}:{reason:stored.reason},expectedVersion:log.version})}return{log,raw}}function relationshipEventMatchesInput(event,input,nodes,registry){const timestamp=Date.parse(input.timestamp);let edge;if(input.action!=="remove"&&input.edge!==void 0)edge=new RelationshipGraph(nodes,[input.edge],registry).edges()[0];return event.eventId===input.eventId.trim()&&event.relationshipId===input.relationshipId.trim()&&event.action===input.action&&event.author===input.author.trim()&&Number.isFinite(timestamp)&&event.timestamp===new Date(timestamp).toISOString()&&event.reason===(input.reason?.trim()||void 0)&&stableStringify(event.edge)===stableStringify(edge)}class RelationshipEventStore{#pmRoot;#nodes;#registry;#path;#log;constructor(options,nodes,target,log){this.#pmRoot=options.pmRoot;this.#nodes=nodes;this.#registry=options.registry;this.#path=target;this.#log=log}static async open(options){const nodes=Object.freeze([...options.nodes]);const target=await resolveRelationshipEventStorePath(options.pmRoot,options.relativePath);const release=await acquireRelationshipStoreLock(options.pmRoot);try{await resolveRelationshipEventStorePath(options.pmRoot,target);const{log}=await loadRelationshipEventLog(target,nodes,options.registry);return new RelationshipEventStore(options,nodes,target,log)}finally{await release()}}get path(){return this.#path}async currentVersion(){this.#log=await this.#refreshFromDurableHistory();return this.#log.version}async append(input){const release=await acquireRelationshipStoreLock(this.#pmRoot);try{const target=await resolveRelationshipEventStorePath(this.#pmRoot,this.#path);const{log:refreshed}=await loadRelationshipEventLog(target,this.#nodes,this.#registry);const event=refreshed.append(input);await mkdir(path.dirname(target),{recursive:true});await resolveRelationshipEventStorePath(this.#pmRoot,target);const handle=await open(target,constants.O_APPEND|constants.O_CREAT|constants.O_WRONLY|RELATIONSHIP_NOFOLLOW_FLAG);try{await handle.appendFile(`${JSON.stringify(event)}
|
|
2
|
+
`,"utf8")}finally{await handle.close()}this.#log=refreshed;return event}finally{await release()}}async appendBatch(inputs,options={}){const release=await acquireRelationshipStoreLock(this.#pmRoot);try{const target=await resolveRelationshipEventStorePath(this.#pmRoot,this.#path);const{log:refreshed,raw}=await loadRelationshipEventLog(target,this.#nodes,this.#registry);const versionBefore=refreshed.version;const existing=new Map(refreshed.events().map(event=>[event.eventId,event]));const appended=[];const skippedEventIds=[];for(const input of inputs){const eventId=input.eventId.trim();const stored=existing.get(eventId);if(stored!==void 0){if(options.existingEventPolicy==="skip_identical"&&relationshipEventMatchesInput(stored,input,this.#nodes,this.#registry)){skippedEventIds.push(stored.eventId);continue}if(options.existingEventPolicy==="skip_identical")throw new TypeError(`Relationship event id collision with different content: ${eventId}`)}const event=refreshed.append(input);existing.set(event.eventId,event);appended.push(event)}if(appended.length>0){const prefix=raw.length===0||raw.endsWith("\n")?raw:`${raw}
|
|
3
|
+
`;await mkdir(path.dirname(target),{recursive:true});await resolveRelationshipEventStorePath(this.#pmRoot,target);await writeFileAtomic(target,`${prefix}${appended.map(event=>JSON.stringify(event)).join("\n")}
|
|
4
|
+
`)}this.#log=refreshed;return Object.freeze({version_before:versionBefore,version_after:refreshed.version,appended:Object.freeze(appended),skipped_event_ids:Object.freeze(skippedEventIds)})}finally{await release()}}async snapshot(options={}){this.#log=await this.#refreshFromDurableHistory();return this.#log.snapshot(options)}async page(options){this.#log=await this.#refreshFromDurableHistory();return this.#log.page(options)}async*stream(options={}){this.#log=await this.#refreshFromDurableHistory();yield*this.#log.stream(options)}async project(initialState,reducer,options={}){this.#log=await this.#refreshFromDurableHistory();return this.#log.project(initialState,reducer,options)}async#refreshFromDurableHistory(){const release=await acquireRelationshipStoreLock(this.#pmRoot);try{const target=await resolveRelationshipEventStorePath(this.#pmRoot,this.#path);return(await loadRelationshipEventLog(target,this.#nodes,this.#registry)).log}finally{await release()}}}export{RelationshipEventLog,RelationshipEventStore};
|
|
519
5
|
//# sourceMappingURL=relationship-history.js.map
|
|
520
|
-
//# debugId=bb5dfa6f-b60f-55f2-ae17-3dbcaaff1b47
|
|
@@ -1,23 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* @module sdk/relationship-kinds/contract
|
|
3
|
-
*
|
|
4
|
-
* Dependency-free relationship ontology shared by contracts and graph runtime.
|
|
5
|
-
*/
|
|
6
|
-
/** Stable built-in relationship ontology without graph or storage dependencies. */
|
|
7
|
-
|
|
8
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="aa7d04c7-b057-569c-816a-f53322c74261")}catch(e){}}();
|
|
9
|
-
export const BUILTIN_RELATIONSHIP_KINDS = [
|
|
10
|
-
{ kind: "blocked_by", direction: "directed", traversal: "ordering", inverse: "blocks", ordering: true, precedence: "target_before_source", hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "persistent", aliases: ["depends_on"], compatibilityVersion: 1, allowSelf: false },
|
|
11
|
-
{ kind: "blocks", direction: "directed", traversal: "ordering", inverse: "blocked_by", ordering: true, precedence: "source_before_target", hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "persistent", compatibilityVersion: 1, allowSelf: false },
|
|
12
|
-
{ kind: "parent", direction: "directed", traversal: "hierarchy", outcomeTraversal: "source_to_target", inverse: "child", ordering: false, hierarchy: true, hierarchyDirection: "target_parent", outgoing: "one", incoming: "many", lifecycle: "supersedable", aliases: ["child_of", "epic"], compatibilityVersion: 1, allowSelf: false },
|
|
13
|
-
{ kind: "child", direction: "directed", traversal: "hierarchy", outcomeTraversal: "target_to_source", inverse: "parent", ordering: false, hierarchy: true, hierarchyDirection: "source_parent", outgoing: "many", incoming: "one", lifecycle: "supersedable", aliases: ["parent_child", "task"], compatibilityVersion: 1, allowSelf: false },
|
|
14
|
-
{ kind: "related", direction: "undirected", traversal: "association", ordering: false, hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "persistent", aliases: ["related_to"], compatibilityVersion: 1, allowSelf: false },
|
|
15
|
-
{ kind: "discovered_from", direction: "directed", traversal: "semantic", outcomeTraversal: "source_to_target", ordering: false, hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "persistent", compatibilityVersion: 1, allowSelf: false },
|
|
16
|
-
{ kind: "incident_from", direction: "directed", traversal: "semantic", outcomeTraversal: "source_to_target", ordering: false, hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "persistent", compatibilityVersion: 1, allowSelf: false },
|
|
17
|
-
{ kind: "implements", direction: "directed", traversal: "semantic", outcomeTraversal: "source_to_target", ordering: false, hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "persistent", compatibilityVersion: 1, allowSelf: false },
|
|
18
|
-
{ kind: "recurs_from", direction: "directed", traversal: "semantic", outcomeTraversal: "source_to_target", ordering: false, temporalOrder: "source_after_target", hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "persistent", compatibilityVersion: 1, allowSelf: false },
|
|
19
|
-
{ kind: "verifies", direction: "directed", traversal: "semantic", outcomeTraversal: "source_to_target", ordering: false, hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "persistent", compatibilityVersion: 1, allowSelf: false },
|
|
20
|
-
{ kind: "supersedes", direction: "directed", traversal: "semantic", outcomeTraversal: "both", ordering: false, hierarchy: false, outgoing: "many", incoming: "many", lifecycle: "supersedable", compatibilityVersion: 1, allowSelf: false },
|
|
21
|
-
];
|
|
1
|
+
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4c00e38a-27df-5315-91e8-d35c03ed6bf3")}catch(e2){}})();const BUILTIN_RELATIONSHIP_KINDS=[{kind:"blocked_by",direction:"directed",traversal:"ordering",inverse:"blocks",ordering:true,precedence:"target_before_source",hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"persistent",aliases:["depends_on"],compatibilityVersion:1,allowSelf:false},{kind:"blocks",direction:"directed",traversal:"ordering",inverse:"blocked_by",ordering:true,precedence:"source_before_target",hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"persistent",compatibilityVersion:1,allowSelf:false},{kind:"parent",direction:"directed",traversal:"hierarchy",outcomeTraversal:"source_to_target",inverse:"child",ordering:false,hierarchy:true,hierarchyDirection:"target_parent",outgoing:"one",incoming:"many",lifecycle:"supersedable",aliases:["child_of","epic"],compatibilityVersion:1,allowSelf:false},{kind:"child",direction:"directed",traversal:"hierarchy",outcomeTraversal:"target_to_source",inverse:"parent",ordering:false,hierarchy:true,hierarchyDirection:"source_parent",outgoing:"many",incoming:"one",lifecycle:"supersedable",aliases:["parent_child","task"],compatibilityVersion:1,allowSelf:false},{kind:"related",direction:"undirected",traversal:"association",ordering:false,hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"persistent",aliases:["related_to"],compatibilityVersion:1,allowSelf:false},{kind:"discovered_from",direction:"directed",traversal:"semantic",outcomeTraversal:"source_to_target",ordering:false,hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"persistent",compatibilityVersion:1,allowSelf:false},{kind:"incident_from",direction:"directed",traversal:"semantic",outcomeTraversal:"source_to_target",ordering:false,hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"persistent",compatibilityVersion:1,allowSelf:false},{kind:"implements",direction:"directed",traversal:"semantic",outcomeTraversal:"source_to_target",ordering:false,hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"persistent",compatibilityVersion:1,allowSelf:false},{kind:"recurs_from",direction:"directed",traversal:"semantic",outcomeTraversal:"source_to_target",ordering:false,temporalOrder:"source_after_target",hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"persistent",compatibilityVersion:1,allowSelf:false},{kind:"verifies",direction:"directed",traversal:"semantic",outcomeTraversal:"source_to_target",ordering:false,hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"persistent",compatibilityVersion:1,allowSelf:false},{kind:"supersedes",direction:"directed",traversal:"semantic",outcomeTraversal:"both",ordering:false,hierarchy:false,outgoing:"many",incoming:"many",lifecycle:"supersedable",compatibilityVersion:1,allowSelf:false}];export{BUILTIN_RELATIONSHIP_KINDS};
|
|
22
2
|
//# sourceMappingURL=contract.js.map
|
|
23
|
-
//# debugId=aa7d04c7-b057-569c-816a-f53322c74261
|