@namzu/sdk 0.1.8 → 0.3.0
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 +69 -2
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +5 -2
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/RouterAgent.d.ts.map +1 -1
- package/dist/agents/RouterAgent.js +3 -0
- package/dist/agents/RouterAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +21 -5
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/bridge/a2a/index.d.ts +1 -1
- package/dist/bridge/a2a/index.d.ts.map +1 -1
- package/dist/bridge/a2a/index.js +1 -1
- package/dist/bridge/a2a/index.js.map +1 -1
- package/dist/bridge/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +6 -0
- package/dist/bridge/a2a/mapper.js.map +1 -1
- package/dist/bridge/a2a/message.d.ts +0 -2
- package/dist/bridge/a2a/message.d.ts.map +1 -1
- package/dist/bridge/a2a/message.js +0 -26
- package/dist/bridge/a2a/message.js.map +1 -1
- package/dist/bridge/a2a/task.d.ts +5 -4
- package/dist/bridge/a2a/task.d.ts.map +1 -1
- package/dist/bridge/a2a/task.js +4 -4
- package/dist/bridge/a2a/task.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +6 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/constants/a2a/index.d.ts +2 -2
- package/dist/constants/a2a/index.d.ts.map +1 -1
- package/dist/constants/a2a/index.js.map +1 -1
- package/dist/contracts/api.d.ts +14 -27
- package/dist/contracts/api.d.ts.map +1 -1
- package/dist/contracts/ids.d.ts +1 -1
- package/dist/contracts/ids.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +3 -3
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +1 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/schemas.d.ts +1 -31
- package/dist/contracts/schemas.d.ts.map +1 -1
- package/dist/contracts/schemas.js +1 -7
- package/dist/contracts/schemas.js.map +1 -1
- package/dist/gateway/local.d.ts.map +1 -1
- package/dist/gateway/local.js +6 -0
- package/dist/gateway/local.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/manager/agent/__tests__/lifecycle.test.d.ts +2 -0
- package/dist/manager/agent/__tests__/lifecycle.test.d.ts.map +1 -0
- package/dist/manager/agent/__tests__/lifecycle.test.js +316 -0
- package/dist/manager/agent/__tests__/lifecycle.test.js.map +1 -0
- package/dist/manager/agent/lifecycle.d.ts +67 -3
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +375 -14
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/index.d.ts +2 -0
- package/dist/manager/index.d.ts.map +1 -1
- package/dist/manager/index.js +1 -0
- package/dist/manager/index.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +10 -1
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +20 -0
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/manager/thread/__tests__/lifecycle.test.d.ts +2 -0
- package/dist/manager/thread/__tests__/lifecycle.test.d.ts.map +1 -0
- package/dist/manager/thread/__tests__/lifecycle.test.js +216 -0
- package/dist/manager/thread/__tests__/lifecycle.test.js.map +1 -0
- package/dist/manager/thread/lifecycle.d.ts +105 -0
- package/dist/manager/thread/lifecycle.d.ts.map +1 -0
- package/dist/manager/thread/lifecycle.js +186 -0
- package/dist/manager/thread/lifecycle.js.map +1 -0
- package/dist/rag/retriever.js +2 -2
- package/dist/run/reporter.d.ts.map +1 -1
- package/dist/run/reporter.js +25 -0
- package/dist/run/reporter.js.map +1 -1
- package/dist/runtime/query/__tests__/context.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/context.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/context.test.js +85 -0
- package/dist/runtime/query/__tests__/context.test.js.map +1 -0
- package/dist/runtime/query/context-cache.d.ts +3 -3
- package/dist/runtime/query/context-cache.d.ts.map +1 -1
- package/dist/runtime/query/context-cache.js +2 -2
- package/dist/runtime/query/context-cache.js.map +1 -1
- package/dist/runtime/query/context.d.ts +45 -1
- package/dist/runtime/query/context.d.ts.map +1 -1
- package/dist/runtime/query/context.js +50 -8
- package/dist/runtime/query/context.js.map +1 -1
- package/dist/runtime/query/events.d.ts.map +1 -1
- package/dist/runtime/query/events.js +8 -0
- package/dist/runtime/query/events.js.map +1 -1
- package/dist/runtime/query/index.d.ts +22 -1
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +11 -0
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/session/__tests__/integration/_fixtures.d.ts +122 -0
- package/dist/session/__tests__/integration/_fixtures.d.ts.map +1 -0
- package/dist/session/__tests__/integration/_fixtures.js +215 -0
- package/dist/session/__tests__/integration/_fixtures.js.map +1 -0
- package/dist/session/__tests__/integration/archive-gate.test.d.ts +15 -0
- package/dist/session/__tests__/integration/archive-gate.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/archive-gate.test.js +214 -0
- package/dist/session/__tests__/integration/archive-gate.test.js.map +1 -0
- package/dist/session/__tests__/integration/capacity-caps.test.d.ts +13 -0
- package/dist/session/__tests__/integration/capacity-caps.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/capacity-caps.test.js +123 -0
- package/dist/session/__tests__/integration/capacity-caps.test.js.map +1 -0
- package/dist/session/__tests__/integration/e2e-spawn.test.d.ts +18 -0
- package/dist/session/__tests__/integration/e2e-spawn.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/e2e-spawn.test.js +238 -0
- package/dist/session/__tests__/integration/e2e-spawn.test.js.map +1 -0
- package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts +15 -0
- package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/event-stream-ordering.test.js +330 -0
- package/dist/session/__tests__/integration/event-stream-ordering.test.js.map +1 -0
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts +12 -0
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js +182 -0
- package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js.map +1 -0
- package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts +18 -0
- package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/handoff-illegal-transition.test.js +156 -0
- package/dist/session/__tests__/integration/handoff-illegal-transition.test.js.map +1 -0
- package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts +15 -0
- package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/handoff-single-e2e.test.js +179 -0
- package/dist/session/__tests__/integration/handoff-single-e2e.test.js.map +1 -0
- package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts +12 -0
- package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js +158 -0
- package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js.map +1 -0
- package/dist/session/__tests__/integration/migration-filesystem.test.d.ts +11 -0
- package/dist/session/__tests__/integration/migration-filesystem.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/migration-filesystem.test.js +140 -0
- package/dist/session/__tests__/integration/migration-filesystem.test.js.map +1 -0
- package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts +13 -0
- package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/migration-id-prefix.test.js +84 -0
- package/dist/session/__tests__/integration/migration-id-prefix.test.js.map +1 -0
- package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts +14 -0
- package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/prev-artifact-dag.test.js +242 -0
- package/dist/session/__tests__/integration/prev-artifact-dag.test.js.map +1 -0
- package/dist/session/__tests__/integration/retention-archive.test.d.ts +12 -0
- package/dist/session/__tests__/integration/retention-archive.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/retention-archive.test.js +187 -0
- package/dist/session/__tests__/integration/retention-archive.test.js.map +1 -0
- package/dist/session/__tests__/integration/spawn-rollback.test.d.ts +26 -0
- package/dist/session/__tests__/integration/spawn-rollback.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/spawn-rollback.test.js +236 -0
- package/dist/session/__tests__/integration/spawn-rollback.test.js.map +1 -0
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts +18 -0
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.js +201 -0
- package/dist/session/__tests__/integration/summary-materialization-e2e.test.js.map +1 -0
- package/dist/session/__tests__/integration/tenant-isolation.test.d.ts +14 -0
- package/dist/session/__tests__/integration/tenant-isolation.test.d.ts.map +1 -0
- package/dist/session/__tests__/integration/tenant-isolation.test.js +189 -0
- package/dist/session/__tests__/integration/tenant-isolation.test.js.map +1 -0
- package/dist/session/errors.d.ts +139 -0
- package/dist/session/errors.d.ts.map +1 -0
- package/dist/session/errors.js +107 -0
- package/dist/session/errors.js.map +1 -0
- package/dist/session/events/index.d.ts +4 -0
- package/dist/session/events/index.d.ts.map +1 -0
- package/dist/session/events/index.js +8 -0
- package/dist/session/events/index.js.map +1 -0
- package/dist/session/events/schema-version.d.ts +13 -0
- package/dist/session/events/schema-version.d.ts.map +1 -0
- package/dist/session/events/schema-version.js +12 -0
- package/dist/session/events/schema-version.js.map +1 -0
- package/dist/session/events/types.d.ts +64 -0
- package/dist/session/events/types.d.ts.map +1 -0
- package/dist/session/events/types.js +2 -0
- package/dist/session/events/types.js.map +1 -0
- package/dist/session/handoff/__tests__/broadcast.test.d.ts +2 -0
- package/dist/session/handoff/__tests__/broadcast.test.d.ts.map +1 -0
- package/dist/session/handoff/__tests__/broadcast.test.js +261 -0
- package/dist/session/handoff/__tests__/broadcast.test.js.map +1 -0
- package/dist/session/handoff/__tests__/capacity.test.d.ts +2 -0
- package/dist/session/handoff/__tests__/capacity.test.d.ts.map +1 -0
- package/dist/session/handoff/__tests__/capacity.test.js +103 -0
- package/dist/session/handoff/__tests__/capacity.test.js.map +1 -0
- package/dist/session/handoff/__tests__/single.test.d.ts +2 -0
- package/dist/session/handoff/__tests__/single.test.d.ts.map +1 -0
- package/dist/session/handoff/__tests__/single.test.js +239 -0
- package/dist/session/handoff/__tests__/single.test.js.map +1 -0
- package/dist/session/handoff/assignment.d.ts +71 -0
- package/dist/session/handoff/assignment.d.ts.map +1 -0
- package/dist/session/handoff/assignment.js +11 -0
- package/dist/session/handoff/assignment.js.map +1 -0
- package/dist/session/handoff/broadcast.d.ts +54 -0
- package/dist/session/handoff/broadcast.d.ts.map +1 -0
- package/dist/session/handoff/broadcast.js +311 -0
- package/dist/session/handoff/broadcast.js.map +1 -0
- package/dist/session/handoff/capacity.d.ts +66 -0
- package/dist/session/handoff/capacity.d.ts.map +1 -0
- package/dist/session/handoff/capacity.js +60 -0
- package/dist/session/handoff/capacity.js.map +1 -0
- package/dist/session/handoff/events.d.ts +66 -0
- package/dist/session/handoff/events.d.ts.map +1 -0
- package/dist/session/handoff/events.js +13 -0
- package/dist/session/handoff/events.js.map +1 -0
- package/dist/session/handoff/index.d.ts +12 -0
- package/dist/session/handoff/index.d.ts.map +1 -0
- package/dist/session/handoff/index.js +9 -0
- package/dist/session/handoff/index.js.map +1 -0
- package/dist/session/handoff/single.d.ts +69 -0
- package/dist/session/handoff/single.d.ts.map +1 -0
- package/dist/session/handoff/single.js +229 -0
- package/dist/session/handoff/single.js.map +1 -0
- package/dist/session/handoff/version.d.ts +52 -0
- package/dist/session/handoff/version.d.ts.map +1 -0
- package/dist/session/handoff/version.js +36 -0
- package/dist/session/handoff/version.js.map +1 -0
- package/dist/session/hierarchy/__tests__/session.test.d.ts +2 -0
- package/dist/session/hierarchy/__tests__/session.test.d.ts.map +1 -0
- package/dist/session/hierarchy/__tests__/session.test.js +69 -0
- package/dist/session/hierarchy/__tests__/session.test.js.map +1 -0
- package/dist/session/hierarchy/actor.d.ts +26 -0
- package/dist/session/hierarchy/actor.d.ts.map +1 -0
- package/dist/session/hierarchy/actor.js +2 -0
- package/dist/session/hierarchy/actor.js.map +1 -0
- package/dist/session/hierarchy/index.d.ts +9 -0
- package/dist/session/hierarchy/index.d.ts.map +1 -0
- package/dist/session/hierarchy/index.js +4 -0
- package/dist/session/hierarchy/index.js.map +1 -0
- package/dist/session/hierarchy/lineage.d.ts +15 -0
- package/dist/session/hierarchy/lineage.d.ts.map +1 -0
- package/dist/session/hierarchy/lineage.js +2 -0
- package/dist/session/hierarchy/lineage.js.map +1 -0
- package/dist/session/hierarchy/project.d.ts +40 -0
- package/dist/session/hierarchy/project.d.ts.map +1 -0
- package/dist/session/hierarchy/project.js +2 -0
- package/dist/session/hierarchy/project.js.map +1 -0
- package/dist/session/hierarchy/session.d.ts +71 -0
- package/dist/session/hierarchy/session.d.ts.map +1 -0
- package/dist/session/hierarchy/session.js +51 -0
- package/dist/session/hierarchy/session.js.map +1 -0
- package/dist/session/hierarchy/sub-session.d.ts +76 -0
- package/dist/session/hierarchy/sub-session.d.ts.map +1 -0
- package/dist/session/hierarchy/sub-session.js +2 -0
- package/dist/session/hierarchy/sub-session.js.map +1 -0
- package/dist/session/hierarchy/tenant.d.ts +13 -0
- package/dist/session/hierarchy/tenant.d.ts.map +1 -0
- package/dist/session/hierarchy/tenant.js +2 -0
- package/dist/session/hierarchy/tenant.js.map +1 -0
- package/dist/session/hierarchy/thread.d.ts +54 -0
- package/dist/session/hierarchy/thread.d.ts.map +1 -0
- package/dist/session/hierarchy/thread.js +2 -0
- package/dist/session/hierarchy/thread.js.map +1 -0
- package/dist/session/index.d.ts +10 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +15 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/intervention/__tests__/prev-artifact.test.d.ts +2 -0
- package/dist/session/intervention/__tests__/prev-artifact.test.d.ts.map +1 -0
- package/dist/session/intervention/__tests__/prev-artifact.test.js +179 -0
- package/dist/session/intervention/__tests__/prev-artifact.test.js.map +1 -0
- package/dist/session/intervention/index.d.ts +3 -0
- package/dist/session/intervention/index.d.ts.map +1 -0
- package/dist/session/intervention/index.js +8 -0
- package/dist/session/intervention/index.js.map +1 -0
- package/dist/session/intervention/prev-artifact.d.ts +103 -0
- package/dist/session/intervention/prev-artifact.d.ts.map +1 -0
- package/dist/session/intervention/prev-artifact.js +112 -0
- package/dist/session/intervention/prev-artifact.js.map +1 -0
- package/dist/session/migration/__tests__/filesystem.test.d.ts +2 -0
- package/dist/session/migration/__tests__/filesystem.test.d.ts.map +1 -0
- package/dist/session/migration/__tests__/filesystem.test.js +188 -0
- package/dist/session/migration/__tests__/filesystem.test.js.map +1 -0
- package/dist/session/migration/__tests__/id-prefix.test.d.ts +2 -0
- package/dist/session/migration/__tests__/id-prefix.test.d.ts.map +1 -0
- package/dist/session/migration/__tests__/id-prefix.test.js +83 -0
- package/dist/session/migration/__tests__/id-prefix.test.js.map +1 -0
- package/dist/session/migration/__tests__/marker.test.d.ts +2 -0
- package/dist/session/migration/__tests__/marker.test.d.ts.map +1 -0
- package/dist/session/migration/__tests__/marker.test.js +75 -0
- package/dist/session/migration/__tests__/marker.test.js.map +1 -0
- package/dist/session/migration/errors.d.ts +26 -0
- package/dist/session/migration/errors.d.ts.map +1 -0
- package/dist/session/migration/errors.js +22 -0
- package/dist/session/migration/errors.js.map +1 -0
- package/dist/session/migration/filesystem.d.ts +94 -0
- package/dist/session/migration/filesystem.d.ts.map +1 -0
- package/dist/session/migration/filesystem.js +319 -0
- package/dist/session/migration/filesystem.js.map +1 -0
- package/dist/session/migration/id-prefix.d.ts +93 -0
- package/dist/session/migration/id-prefix.d.ts.map +1 -0
- package/dist/session/migration/id-prefix.js +111 -0
- package/dist/session/migration/id-prefix.js.map +1 -0
- package/dist/session/migration/index.d.ts +8 -0
- package/dist/session/migration/index.d.ts.map +1 -0
- package/dist/session/migration/index.js +8 -0
- package/dist/session/migration/index.js.map +1 -0
- package/dist/session/migration/marker.d.ts +57 -0
- package/dist/session/migration/marker.d.ts.map +1 -0
- package/dist/session/migration/marker.js +111 -0
- package/dist/session/migration/marker.js.map +1 -0
- package/dist/session/retention/__tests__/archive.test.d.ts +2 -0
- package/dist/session/retention/__tests__/archive.test.d.ts.map +1 -0
- package/dist/session/retention/__tests__/archive.test.js +253 -0
- package/dist/session/retention/__tests__/archive.test.js.map +1 -0
- package/dist/session/retention/__tests__/disk-backend.test.d.ts +2 -0
- package/dist/session/retention/__tests__/disk-backend.test.d.ts.map +1 -0
- package/dist/session/retention/__tests__/disk-backend.test.js +154 -0
- package/dist/session/retention/__tests__/disk-backend.test.js.map +1 -0
- package/dist/session/retention/archive-backend-ref.d.ts +18 -0
- package/dist/session/retention/archive-backend-ref.d.ts.map +1 -0
- package/dist/session/retention/archive-backend-ref.js +2 -0
- package/dist/session/retention/archive-backend-ref.js.map +1 -0
- package/dist/session/retention/archive.d.ts +130 -0
- package/dist/session/retention/archive.d.ts.map +1 -0
- package/dist/session/retention/archive.js +203 -0
- package/dist/session/retention/archive.js.map +1 -0
- package/dist/session/retention/backend.d.ts +101 -0
- package/dist/session/retention/backend.d.ts.map +1 -0
- package/dist/session/retention/backend.js +15 -0
- package/dist/session/retention/backend.js.map +1 -0
- package/dist/session/retention/disk-backend.d.ts +59 -0
- package/dist/session/retention/disk-backend.d.ts.map +1 -0
- package/dist/session/retention/disk-backend.js +236 -0
- package/dist/session/retention/disk-backend.js.map +1 -0
- package/dist/session/retention/index.d.ts +9 -0
- package/dist/session/retention/index.d.ts.map +1 -0
- package/dist/session/retention/index.js +6 -0
- package/dist/session/retention/index.js.map +1 -0
- package/dist/session/retention/policy.d.ts +49 -0
- package/dist/session/retention/policy.d.ts.map +1 -0
- package/dist/session/retention/policy.js +21 -0
- package/dist/session/retention/policy.js.map +1 -0
- package/dist/session/summary/__tests__/materialize.test.d.ts +2 -0
- package/dist/session/summary/__tests__/materialize.test.d.ts.map +1 -0
- package/dist/session/summary/__tests__/materialize.test.js +270 -0
- package/dist/session/summary/__tests__/materialize.test.js.map +1 -0
- package/dist/session/summary/deliverable.d.ts +74 -0
- package/dist/session/summary/deliverable.d.ts.map +1 -0
- package/dist/session/summary/deliverable.js +20 -0
- package/dist/session/summary/deliverable.js.map +1 -0
- package/dist/session/summary/index.d.ts +6 -0
- package/dist/session/summary/index.d.ts.map +1 -0
- package/dist/session/summary/index.js +9 -0
- package/dist/session/summary/index.js.map +1 -0
- package/dist/session/summary/materialize.d.ts +82 -0
- package/dist/session/summary/materialize.d.ts.map +1 -0
- package/dist/session/summary/materialize.js +117 -0
- package/dist/session/summary/materialize.js.map +1 -0
- package/dist/session/summary/ref.d.ts +91 -0
- package/dist/session/summary/ref.d.ts.map +1 -0
- package/dist/session/summary/ref.js +51 -0
- package/dist/session/summary/ref.js.map +1 -0
- package/dist/session/workspace/__tests__/git-worktree.test.d.ts +2 -0
- package/dist/session/workspace/__tests__/git-worktree.test.d.ts.map +1 -0
- package/dist/session/workspace/__tests__/git-worktree.test.js +244 -0
- package/dist/session/workspace/__tests__/git-worktree.test.js.map +1 -0
- package/dist/session/workspace/__tests__/path-builder.test.d.ts +2 -0
- package/dist/session/workspace/__tests__/path-builder.test.d.ts.map +1 -0
- package/dist/session/workspace/__tests__/path-builder.test.js +37 -0
- package/dist/session/workspace/__tests__/path-builder.test.js.map +1 -0
- package/dist/session/workspace/driver.d.ts +55 -0
- package/dist/session/workspace/driver.d.ts.map +1 -0
- package/dist/session/workspace/driver.js +12 -0
- package/dist/session/workspace/driver.js.map +1 -0
- package/dist/session/workspace/git-worktree.d.ts +65 -0
- package/dist/session/workspace/git-worktree.d.ts.map +1 -0
- package/dist/session/workspace/git-worktree.js +156 -0
- package/dist/session/workspace/git-worktree.js.map +1 -0
- package/dist/session/workspace/index.d.ts +8 -0
- package/dist/session/workspace/index.d.ts.map +1 -0
- package/dist/session/workspace/index.js +7 -0
- package/dist/session/workspace/index.js.map +1 -0
- package/dist/session/workspace/path-builder.d.ts +50 -0
- package/dist/session/workspace/path-builder.d.ts.map +1 -0
- package/dist/session/workspace/path-builder.js +50 -0
- package/dist/session/workspace/path-builder.js.map +1 -0
- package/dist/session/workspace/ref.d.ts +46 -0
- package/dist/session/workspace/ref.d.ts.map +1 -0
- package/dist/session/workspace/ref.js +11 -0
- package/dist/session/workspace/ref.js.map +1 -0
- package/dist/session/workspace/registry.d.ts +26 -0
- package/dist/session/workspace/registry.d.ts.map +1 -0
- package/dist/session/workspace/registry.js +35 -0
- package/dist/session/workspace/registry.js.map +1 -0
- package/dist/store/index.d.ts +0 -2
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +0 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/session/__tests__/disk.test.d.ts +2 -0
- package/dist/store/session/__tests__/disk.test.d.ts.map +1 -0
- package/dist/store/session/__tests__/disk.test.js +267 -0
- package/dist/store/session/__tests__/disk.test.js.map +1 -0
- package/dist/store/session/__tests__/memory.test.d.ts +2 -0
- package/dist/store/session/__tests__/memory.test.d.ts.map +1 -0
- package/dist/store/session/__tests__/memory.test.js +258 -0
- package/dist/store/session/__tests__/memory.test.js.map +1 -0
- package/dist/store/session/disk.d.ts +86 -0
- package/dist/store/session/disk.d.ts.map +1 -0
- package/dist/store/session/disk.js +818 -0
- package/dist/store/session/disk.js.map +1 -0
- package/dist/store/session/index.d.ts +7 -0
- package/dist/store/session/index.d.ts.map +1 -0
- package/dist/store/session/index.js +10 -0
- package/dist/store/session/index.js.map +1 -0
- package/dist/store/session/linkage.d.ts +38 -0
- package/dist/store/session/linkage.d.ts.map +1 -0
- package/dist/store/session/linkage.js +64 -0
- package/dist/store/session/linkage.js.map +1 -0
- package/dist/store/session/memory.d.ts +49 -0
- package/dist/store/session/memory.d.ts.map +1 -0
- package/dist/store/session/memory.js +335 -0
- package/dist/store/session/memory.js.map +1 -0
- package/dist/store/session/messages.d.ts +20 -0
- package/dist/store/session/messages.d.ts.map +1 -0
- package/dist/store/session/messages.js +12 -0
- package/dist/store/session/messages.js.map +1 -0
- package/dist/store/thread/disk.d.ts +41 -0
- package/dist/store/thread/disk.d.ts.map +1 -0
- package/dist/store/thread/disk.js +229 -0
- package/dist/store/thread/disk.js.map +1 -0
- package/dist/store/thread/index.d.ts +4 -0
- package/dist/store/thread/index.d.ts.map +1 -0
- package/dist/store/thread/index.js +6 -0
- package/dist/store/thread/index.js.map +1 -0
- package/dist/store/thread/memory.d.ts +23 -0
- package/dist/store/thread/memory.d.ts.map +1 -0
- package/dist/store/thread/memory.js +90 -0
- package/dist/store/thread/memory.js.map +1 -0
- package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +1 -1
- package/dist/types/agent/base.d.ts +24 -1
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/factory.d.ts +8 -2
- package/dist/types/agent/factory.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +57 -2
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/agent/task.js.map +1 -1
- package/dist/types/ids/index.d.ts +22 -3
- package/dist/types/ids/index.d.ts.map +1 -1
- package/dist/types/ids/index.js +8 -1
- package/dist/types/ids/index.js.map +1 -1
- package/dist/types/invocation/__tests__/state.test.js +36 -29
- package/dist/types/invocation/__tests__/state.test.js.map +1 -1
- package/dist/types/invocation/index.d.ts +20 -4
- package/dist/types/invocation/index.d.ts.map +1 -1
- package/dist/types/invocation/index.js +10 -7
- package/dist/types/invocation/index.js.map +1 -1
- package/dist/types/rag/retrieval.d.ts +4 -3
- package/dist/types/rag/retrieval.d.ts.map +1 -1
- package/dist/types/run/config.d.ts +12 -1
- package/dist/types/run/config.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +26 -1
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/index.d.ts.map +1 -1
- package/dist/types/run/index.js +8 -0
- package/dist/types/run/index.js.map +1 -1
- package/dist/types/run/metadata.d.ts +12 -2
- package/dist/types/run/metadata.d.ts.map +1 -1
- package/dist/types/run/status.d.ts +26 -0
- package/dist/types/run/status.d.ts.map +1 -0
- package/dist/types/run/status.js +2 -0
- package/dist/types/run/status.js.map +1 -0
- package/dist/types/session/ids.d.ts +9 -0
- package/dist/types/session/ids.d.ts.map +1 -0
- package/dist/types/session/ids.js +9 -0
- package/dist/types/session/ids.js.map +1 -0
- package/dist/types/session/index.d.ts +3 -0
- package/dist/types/session/index.d.ts.map +1 -0
- package/dist/types/session/index.js +5 -0
- package/dist/types/session/index.js.map +1 -0
- package/dist/types/session/store.d.ts +210 -0
- package/dist/types/session/store.d.ts.map +1 -0
- package/dist/types/session/store.js +9 -0
- package/dist/types/session/store.js.map +1 -0
- package/dist/types/thread/index.d.ts +2 -0
- package/dist/types/thread/index.d.ts.map +1 -0
- package/dist/types/thread/index.js +5 -0
- package/dist/types/thread/index.js.map +1 -0
- package/dist/types/thread/store.d.ts +86 -0
- package/dist/types/thread/store.d.ts.map +1 -0
- package/dist/types/thread/store.js +22 -0
- package/dist/types/thread/store.js.map +1 -0
- package/dist/utils/id.d.ts +8 -2
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +22 -4
- package/dist/utils/id.js.map +1 -1
- package/package.json +6 -11
- package/src/agents/ReactiveAgent.ts +7 -2
- package/src/agents/RouterAgent.ts +5 -0
- package/src/agents/SupervisorAgent.ts +29 -6
- package/src/bridge/a2a/index.ts +0 -1
- package/src/bridge/a2a/mapper.ts +7 -0
- package/src/bridge/a2a/message.ts +0 -32
- package/src/bridge/a2a/task.ts +9 -8
- package/src/bridge/sse/mapper.ts +8 -1
- package/src/constants/a2a/index.ts +2 -2
- package/src/contracts/api.ts +14 -30
- package/src/contracts/ids.ts +1 -1
- package/src/contracts/index.ts +3 -7
- package/src/contracts/schemas.ts +1 -8
- package/src/gateway/local.ts +6 -0
- package/src/index.ts +14 -4
- package/src/manager/agent/__tests__/lifecycle.test.ts +473 -0
- package/src/manager/agent/lifecycle.ts +515 -21
- package/src/manager/index.ts +3 -0
- package/src/manager/run/persistence.ts +26 -1
- package/src/manager/thread/__tests__/lifecycle.test.ts +286 -0
- package/src/manager/thread/lifecycle.ts +217 -0
- package/src/rag/retriever.ts +2 -2
- package/src/run/reporter.ts +28 -0
- package/src/runtime/query/__tests__/context.test.ts +102 -0
- package/src/runtime/query/context-cache.ts +4 -4
- package/src/runtime/query/context.ts +98 -9
- package/src/runtime/query/events.ts +8 -0
- package/src/runtime/query/index.ts +38 -1
- package/src/session/__tests__/integration/_fixtures.ts +310 -0
- package/src/session/__tests__/integration/archive-gate.test.ts +288 -0
- package/src/session/__tests__/integration/capacity-caps.test.ts +171 -0
- package/src/session/__tests__/integration/e2e-spawn.test.ts +296 -0
- package/src/session/__tests__/integration/event-stream-ordering.test.ts +410 -0
- package/src/session/__tests__/integration/handoff-broadcast-e2e.test.ts +271 -0
- package/src/session/__tests__/integration/handoff-illegal-transition.test.ts +214 -0
- package/src/session/__tests__/integration/handoff-single-e2e.test.ts +251 -0
- package/src/session/__tests__/integration/hierarchy-lifecycle.test.ts +240 -0
- package/src/session/__tests__/integration/migration-filesystem.test.ts +209 -0
- package/src/session/__tests__/integration/migration-id-prefix.test.ts +101 -0
- package/src/session/__tests__/integration/prev-artifact-dag.test.ts +325 -0
- package/src/session/__tests__/integration/retention-archive.test.ts +233 -0
- package/src/session/__tests__/integration/spawn-rollback.test.ts +313 -0
- package/src/session/__tests__/integration/summary-materialization-e2e.test.ts +239 -0
- package/src/session/__tests__/integration/tenant-isolation.test.ts +292 -0
- package/src/session/errors.ts +159 -0
- package/src/session/events/index.ts +16 -0
- package/src/session/events/schema-version.ts +13 -0
- package/src/session/events/types.ts +71 -0
- package/src/session/handoff/__tests__/broadcast.test.ts +378 -0
- package/src/session/handoff/__tests__/capacity.test.ts +129 -0
- package/src/session/handoff/__tests__/single.test.ts +333 -0
- package/src/session/handoff/assignment.ts +74 -0
- package/src/session/handoff/broadcast.ts +406 -0
- package/src/session/handoff/capacity.ts +121 -0
- package/src/session/handoff/events.ts +72 -0
- package/src/session/handoff/index.ts +29 -0
- package/src/session/handoff/single.ts +310 -0
- package/src/session/handoff/version.ts +59 -0
- package/src/session/hierarchy/__tests__/session.test.ts +100 -0
- package/src/session/hierarchy/actor.ts +17 -0
- package/src/session/hierarchy/index.ts +18 -0
- package/src/session/hierarchy/lineage.ts +15 -0
- package/src/session/hierarchy/project.ts +41 -0
- package/src/session/hierarchy/session.ts +109 -0
- package/src/session/hierarchy/sub-session.ts +92 -0
- package/src/session/hierarchy/tenant.ts +13 -0
- package/src/session/hierarchy/thread.ts +55 -0
- package/src/session/index.ts +15 -0
- package/src/session/intervention/__tests__/prev-artifact.test.ts +234 -0
- package/src/session/intervention/index.ts +16 -0
- package/src/session/intervention/prev-artifact.ts +180 -0
- package/src/session/migration/__tests__/filesystem.test.ts +263 -0
- package/src/session/migration/__tests__/id-prefix.test.ts +101 -0
- package/src/session/migration/__tests__/marker.test.ts +84 -0
- package/src/session/migration/errors.ts +23 -0
- package/src/session/migration/filesystem.ts +401 -0
- package/src/session/migration/id-prefix.ts +141 -0
- package/src/session/migration/index.ts +38 -0
- package/src/session/migration/marker.ts +131 -0
- package/src/session/retention/__tests__/archive.test.ts +318 -0
- package/src/session/retention/__tests__/disk-backend.test.ts +180 -0
- package/src/session/retention/archive-backend-ref.ts +17 -0
- package/src/session/retention/archive.ts +281 -0
- package/src/session/retention/backend.ts +107 -0
- package/src/session/retention/disk-backend.ts +304 -0
- package/src/session/retention/index.ts +16 -0
- package/src/session/retention/policy.ts +53 -0
- package/src/session/summary/__tests__/materialize.test.ts +343 -0
- package/src/session/summary/deliverable.ts +84 -0
- package/src/session/summary/index.ts +31 -0
- package/src/session/summary/materialize.ts +169 -0
- package/src/session/summary/ref.ts +104 -0
- package/src/session/workspace/__tests__/git-worktree.test.ts +258 -0
- package/src/session/workspace/__tests__/path-builder.test.ts +51 -0
- package/src/session/workspace/driver.ts +60 -0
- package/src/session/workspace/git-worktree.ts +209 -0
- package/src/session/workspace/index.ts +25 -0
- package/src/session/workspace/path-builder.ts +71 -0
- package/src/session/workspace/ref.ts +50 -0
- package/src/session/workspace/registry.ts +42 -0
- package/src/store/index.ts +0 -3
- package/src/store/session/__tests__/disk.test.ts +397 -0
- package/src/store/session/__tests__/memory.test.ts +402 -0
- package/src/store/session/disk.ts +976 -0
- package/src/store/session/index.ts +13 -0
- package/src/store/session/linkage.ts +80 -0
- package/src/store/session/memory.ts +412 -0
- package/src/store/session/messages.ts +21 -0
- package/src/store/thread/disk.ts +261 -0
- package/src/store/thread/index.ts +7 -0
- package/src/store/thread/memory.ts +104 -0
- package/src/types/agent/base.ts +27 -1
- package/src/types/agent/factory.ts +8 -3
- package/src/types/agent/task.ts +66 -2
- package/src/types/ids/index.ts +34 -3
- package/src/types/invocation/__tests__/state.test.ts +37 -29
- package/src/types/invocation/index.ts +26 -10
- package/src/types/rag/retrieval.ts +4 -3
- package/src/types/run/config.ts +13 -1
- package/src/types/run/events.ts +36 -1
- package/src/types/run/index.ts +8 -0
- package/src/types/run/metadata.ts +12 -2
- package/src/types/run/status.ts +33 -0
- package/src/types/session/ids.ts +23 -0
- package/src/types/session/index.ts +27 -0
- package/src/types/session/store.ts +252 -0
- package/src/types/thread/index.ts +5 -0
- package/src/types/thread/store.ts +92 -0
- package/src/utils/id.ts +34 -4
- package/dist/store/conversation/memory.d.ts +0 -21
- package/dist/store/conversation/memory.d.ts.map +0 -1
- package/dist/store/conversation/memory.js +0 -86
- package/dist/store/conversation/memory.js.map +0 -1
- package/dist/types/conversation/index.d.ts +0 -7
- package/dist/types/conversation/index.d.ts.map +0 -1
- package/dist/types/conversation/index.js +0 -2
- package/dist/types/conversation/index.js.map +0 -1
- package/src/store/conversation/memory.ts +0 -121
- package/src/types/conversation/index.ts +0 -8
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Sub-barrel for session-hierarchy run-event surface.
|
|
2
|
+
// Convention #4: concrete types live in sibling files; re-export them here.
|
|
3
|
+
//
|
|
4
|
+
// Phase 2 scope is limited to the sub-session lifecycle variants that are
|
|
5
|
+
// spliced into `RunEvent`. A dedicated `SessionHierarchyEvent` top-level
|
|
6
|
+
// union lands in a later phase (see session-hierarchy.md §10.2).
|
|
7
|
+
|
|
8
|
+
export { RUN_EVENT_SCHEMA_VERSION } from './schema-version.js'
|
|
9
|
+
export type { RunEventSchemaVersion } from './schema-version.js'
|
|
10
|
+
|
|
11
|
+
export type {
|
|
12
|
+
SubsessionSpawnedEvent,
|
|
13
|
+
SubsessionMessagedEvent,
|
|
14
|
+
SubsessionIdledEvent,
|
|
15
|
+
SubsessionLifecycleEvent,
|
|
16
|
+
} from './types.js'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RunEvent envelope schema version. Bumped on breaking envelope change.
|
|
3
|
+
*
|
|
4
|
+
* - v1: pre-0.2.0 (implicit; untagged events are treated as v1 by consumers).
|
|
5
|
+
* - v2: 0.2.0+ — adds `schemaVersion`, `lineage`, and sub-session lifecycle
|
|
6
|
+
* events.
|
|
7
|
+
*
|
|
8
|
+
* See session-hierarchy.md §10.1 (Event-schema evolution contract) and
|
|
9
|
+
* §13.3.2 (`schemaVersion` back-compat).
|
|
10
|
+
*/
|
|
11
|
+
export const RUN_EVENT_SCHEMA_VERSION = 2 as const
|
|
12
|
+
|
|
13
|
+
export type RunEventSchemaVersion = typeof RUN_EVENT_SCHEMA_VERSION
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { MessageId, RunId, SessionId } from '../../types/ids/index.js'
|
|
2
|
+
import type { SubSessionId } from '../../types/session/ids.js'
|
|
3
|
+
import type { ActorRef } from '../hierarchy/actor.js'
|
|
4
|
+
import type { Lineage } from '../hierarchy/lineage.js'
|
|
5
|
+
import type { RunEventSchemaVersion } from './schema-version.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Sub-session lifecycle events that splice into {@link RunEvent}.
|
|
9
|
+
*
|
|
10
|
+
* See session-hierarchy.md §10.4 (Parent-Child Linkage). These cover the
|
|
11
|
+
* in-flight visibility gap that the terminal-only `SessionSummaryRef` does
|
|
12
|
+
* not address. Every sub-session emission carries the full {@link Lineage}
|
|
13
|
+
* chain — consumers can reconstruct the delegation tree without walking the
|
|
14
|
+
* store (§10.4 invariant).
|
|
15
|
+
*
|
|
16
|
+
* Note: these events are spliced into the `RunEvent` union in
|
|
17
|
+
* `types/run/events.ts` rather than kept as a separate top-level union.
|
|
18
|
+
* A dedicated `SessionHierarchyEvent` top-level type lands in Phase 3+.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Emitted when the kernel creates a new sub-session. Precedes the child
|
|
23
|
+
* session's `run_started`. See §10.4 / §10.5 example stream.
|
|
24
|
+
*/
|
|
25
|
+
export interface SubsessionSpawnedEvent {
|
|
26
|
+
type: 'subsession_spawned'
|
|
27
|
+
runId: RunId
|
|
28
|
+
subSessionId: SubSessionId
|
|
29
|
+
parentSessionId: SessionId
|
|
30
|
+
spawnedBy: ActorRef
|
|
31
|
+
lineage: Lineage
|
|
32
|
+
schemaVersion: RunEventSchemaVersion
|
|
33
|
+
at: Date
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Emitted each time the child session's Run appends a message. Gives parents
|
|
38
|
+
* and platform consumers in-flight visibility without requiring a drill into
|
|
39
|
+
* the child transcript. See §10.4.
|
|
40
|
+
*/
|
|
41
|
+
export interface SubsessionMessagedEvent {
|
|
42
|
+
type: 'subsession_messaged'
|
|
43
|
+
runId: RunId
|
|
44
|
+
subSessionId: SubSessionId
|
|
45
|
+
parentSessionId: SessionId
|
|
46
|
+
messageId: MessageId
|
|
47
|
+
lineage: Lineage
|
|
48
|
+
schemaVersion: RunEventSchemaVersion
|
|
49
|
+
at: Date
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Emitted when the child session transitions to `idle` (terminal persistent
|
|
54
|
+
* state per §5.3 — sub-sessions never close). A separate
|
|
55
|
+
* `sub_session.summarized` event carries the `SessionSummaryRef` (§8); this
|
|
56
|
+
* event only reports the lifecycle transition.
|
|
57
|
+
*/
|
|
58
|
+
export interface SubsessionIdledEvent {
|
|
59
|
+
type: 'subsession_idled'
|
|
60
|
+
runId: RunId
|
|
61
|
+
subSessionId: SubSessionId
|
|
62
|
+
parentSessionId: SessionId
|
|
63
|
+
lineage: Lineage
|
|
64
|
+
schemaVersion: RunEventSchemaVersion
|
|
65
|
+
at: Date
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type SubsessionLifecycleEvent =
|
|
69
|
+
| SubsessionSpawnedEvent
|
|
70
|
+
| SubsessionMessagedEvent
|
|
71
|
+
| SubsessionIdledEvent
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { ThreadManager } from '../../../manager/thread/lifecycle.js'
|
|
3
|
+
import type { ActorRef } from '../../../session/hierarchy/actor.js'
|
|
4
|
+
import {
|
|
5
|
+
type ExecFile,
|
|
6
|
+
type ExecFileResult,
|
|
7
|
+
GitWorktreeDriver,
|
|
8
|
+
} from '../../../session/workspace/git-worktree.js'
|
|
9
|
+
import { WorkspaceBackendRegistry } from '../../../session/workspace/registry.js'
|
|
10
|
+
import { InMemorySessionStore } from '../../../store/session/memory.js'
|
|
11
|
+
import { InMemoryThreadStore } from '../../../store/thread/memory.js'
|
|
12
|
+
import type { SessionId, TenantId, UserId } from '../../../types/ids/index.js'
|
|
13
|
+
import type { ProjectId } from '../../../types/session/ids.js'
|
|
14
|
+
import { generateHandoffId } from '../../../utils/id.js'
|
|
15
|
+
import type { HandoffAssignment } from '../assignment.js'
|
|
16
|
+
import { type BroadcastHandoffDeps, executeBroadcastHandoff } from '../broadcast.js'
|
|
17
|
+
import { DefaultCapacityValidator } from '../capacity.js'
|
|
18
|
+
import type {
|
|
19
|
+
HandoffBroadcastRollbackEvent,
|
|
20
|
+
HandoffCommittedEvent,
|
|
21
|
+
HandoffEventSink,
|
|
22
|
+
HandoffLockedEvent,
|
|
23
|
+
HandoffUnlockedEvent,
|
|
24
|
+
} from '../events.js'
|
|
25
|
+
import { HandoffVersionConflict } from '../version.js'
|
|
26
|
+
|
|
27
|
+
const tenant = 'tnt_alpha' as TenantId
|
|
28
|
+
|
|
29
|
+
function stubLogger() {
|
|
30
|
+
return {
|
|
31
|
+
debug: vi.fn(),
|
|
32
|
+
info: vi.fn(),
|
|
33
|
+
warn: vi.fn(),
|
|
34
|
+
error: vi.fn(),
|
|
35
|
+
child() {
|
|
36
|
+
return stubLogger()
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function okExec(stdout = '', stderr = ''): ExecFileResult {
|
|
42
|
+
return { stdout, stderr }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function user(userId: string): ActorRef {
|
|
46
|
+
return { kind: 'user', userId: userId as UserId, tenantId: tenant }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface MockedHandoffEventSink extends HandoffEventSink {
|
|
50
|
+
onLocked: ReturnType<typeof vi.fn<(ev: HandoffLockedEvent) => void>>
|
|
51
|
+
onUnlocked: ReturnType<typeof vi.fn<(ev: HandoffUnlockedEvent) => void>>
|
|
52
|
+
onCommitted: ReturnType<typeof vi.fn<(ev: HandoffCommittedEvent) => void>>
|
|
53
|
+
onBroadcastRollback: ReturnType<typeof vi.fn<(ev: HandoffBroadcastRollbackEvent) => void>>
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface DepsBundle {
|
|
57
|
+
deps: BroadcastHandoffDeps
|
|
58
|
+
events: MockedHandoffEventSink
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function buildDeps(
|
|
62
|
+
store: InMemorySessionStore,
|
|
63
|
+
threadStore: InMemoryThreadStore,
|
|
64
|
+
execOverride?: ExecFile,
|
|
65
|
+
): DepsBundle {
|
|
66
|
+
const exec: ExecFile = execOverride ? execOverride : async (_file, _args) => okExec()
|
|
67
|
+
const driver = new GitWorktreeDriver({
|
|
68
|
+
repoRoot: '/repo',
|
|
69
|
+
logger: stubLogger(),
|
|
70
|
+
execFile: exec,
|
|
71
|
+
})
|
|
72
|
+
const registry = new WorkspaceBackendRegistry()
|
|
73
|
+
registry.register(driver)
|
|
74
|
+
|
|
75
|
+
const events: MockedHandoffEventSink = {
|
|
76
|
+
onLocked: vi.fn<(ev: HandoffLockedEvent) => void>(),
|
|
77
|
+
onUnlocked: vi.fn<(ev: HandoffUnlockedEvent) => void>(),
|
|
78
|
+
onCommitted: vi.fn<(ev: HandoffCommittedEvent) => void>(),
|
|
79
|
+
onBroadcastRollback: vi.fn<(ev: HandoffBroadcastRollbackEvent) => void>(),
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const threadManager = new ThreadManager({ threadStore, sessionStore: store })
|
|
83
|
+
return {
|
|
84
|
+
deps: {
|
|
85
|
+
store,
|
|
86
|
+
workspaceRegistry: registry,
|
|
87
|
+
capacity: new DefaultCapacityValidator(store),
|
|
88
|
+
events,
|
|
89
|
+
threadManager,
|
|
90
|
+
},
|
|
91
|
+
events,
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function seedIdle(store: InMemorySessionStore, threadStore: InMemoryThreadStore) {
|
|
96
|
+
const project = await store.createProject({ tenantId: tenant, name: 'p' }, tenant)
|
|
97
|
+
const thread = await threadStore.createThread(
|
|
98
|
+
{ projectId: project.id, title: 'handoff-broadcast-test' },
|
|
99
|
+
tenant,
|
|
100
|
+
)
|
|
101
|
+
const session = await store.createSession(
|
|
102
|
+
{ threadId: thread.id, projectId: project.id, currentActor: user('usr_source') },
|
|
103
|
+
tenant,
|
|
104
|
+
)
|
|
105
|
+
return { project, thread, session }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function buildAssignments(
|
|
109
|
+
sourceSessionId: SessionId,
|
|
110
|
+
projectId: ProjectId,
|
|
111
|
+
threadId: Awaited<ReturnType<InMemoryThreadStore['createThread']>>['id'],
|
|
112
|
+
expectedOwnerVersion: number,
|
|
113
|
+
recipients: ActorRef[],
|
|
114
|
+
broadcastId = 'bc_1',
|
|
115
|
+
): HandoffAssignment[] {
|
|
116
|
+
return recipients.map((recipientActor) => ({
|
|
117
|
+
id: generateHandoffId(),
|
|
118
|
+
mode: 'broadcast' as const,
|
|
119
|
+
sourceSessionId,
|
|
120
|
+
tenantId: tenant,
|
|
121
|
+
threadId,
|
|
122
|
+
projectId,
|
|
123
|
+
sourceActor: user('usr_source'),
|
|
124
|
+
recipientActor,
|
|
125
|
+
expectedOwnerVersion,
|
|
126
|
+
broadcastId,
|
|
127
|
+
createdAt: new Date('2026-02-01'),
|
|
128
|
+
}))
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
describe('executeBroadcastHandoff', () => {
|
|
132
|
+
let store: InMemorySessionStore
|
|
133
|
+
let threadStore: InMemoryThreadStore
|
|
134
|
+
|
|
135
|
+
beforeEach(() => {
|
|
136
|
+
store = new InMemorySessionStore()
|
|
137
|
+
threadStore = new InMemoryThreadStore()
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('happy path: 3 recipients → source ends in awaiting_merge with 3 new children', async () => {
|
|
141
|
+
const { project, thread, session } = await seedIdle(store, threadStore)
|
|
142
|
+
const { deps, events } = buildDeps(store, threadStore)
|
|
143
|
+
|
|
144
|
+
const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
|
|
145
|
+
user('usr_bob'),
|
|
146
|
+
user('usr_carol'),
|
|
147
|
+
user('usr_dan'),
|
|
148
|
+
])
|
|
149
|
+
|
|
150
|
+
const outcomes = await executeBroadcastHandoff(deps, assignments, tenant)
|
|
151
|
+
expect(outcomes).toHaveLength(3)
|
|
152
|
+
expect(new Set(outcomes.map((o) => o.newSessionId)).size).toBe(3)
|
|
153
|
+
expect(outcomes.every((o) => o.committedOwnerVersion === 1)).toBe(true)
|
|
154
|
+
|
|
155
|
+
const reloaded = await store.getSession(session.id, tenant)
|
|
156
|
+
expect(reloaded?.status).toBe('awaiting_merge')
|
|
157
|
+
expect(reloaded?.ownerVersion).toBe(1)
|
|
158
|
+
|
|
159
|
+
const children = await store.getChildren(session.id, tenant)
|
|
160
|
+
expect(children).toHaveLength(3)
|
|
161
|
+
|
|
162
|
+
expect(events.onLocked).toHaveBeenCalledTimes(1)
|
|
163
|
+
expect(events.onCommitted).toHaveBeenCalledTimes(1)
|
|
164
|
+
expect(events.onBroadcastRollback).not.toHaveBeenCalled()
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('rollback on mid-fan-out failure (2nd recipient worktree add fails): source reverts, rollback emits accurate partialState', async () => {
|
|
168
|
+
const { project, thread, session } = await seedIdle(store, threadStore)
|
|
169
|
+
|
|
170
|
+
let addCount = 0
|
|
171
|
+
const exec: ExecFile = async (_file, args) => {
|
|
172
|
+
if (args.includes('add')) {
|
|
173
|
+
addCount += 1
|
|
174
|
+
if (addCount === 2) throw new Error('simulated mid-fanout failure')
|
|
175
|
+
}
|
|
176
|
+
return okExec()
|
|
177
|
+
}
|
|
178
|
+
const { deps, events } = buildDeps(store, threadStore, exec)
|
|
179
|
+
|
|
180
|
+
const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
|
|
181
|
+
user('usr_b'),
|
|
182
|
+
user('usr_c'),
|
|
183
|
+
user('usr_d'),
|
|
184
|
+
])
|
|
185
|
+
|
|
186
|
+
await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
|
|
187
|
+
/Workspace backend git-worktree failed on create/,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
const reloaded = await store.getSession(session.id, tenant)
|
|
191
|
+
expect(reloaded?.status).toBe('idle')
|
|
192
|
+
expect(reloaded?.ownerVersion).toBe(0)
|
|
193
|
+
|
|
194
|
+
// The first recipient got through all three sub-ops; the second failed
|
|
195
|
+
// during worktree provisioning. partialState reports:
|
|
196
|
+
// worktreesProvisioned: 1 (the first recipient's)
|
|
197
|
+
// subsessionsCreated: 1 (the first recipient's)
|
|
198
|
+
// assignmentsWritten: 1 (the first recipient's)
|
|
199
|
+
expect(events.onBroadcastRollback).toHaveBeenCalledTimes(1)
|
|
200
|
+
const rollbackCall = events.onBroadcastRollback.mock.calls[0]?.[0]
|
|
201
|
+
expect(rollbackCall).toBeDefined()
|
|
202
|
+
expect(rollbackCall?.partialState.worktreesProvisioned).toBe(1)
|
|
203
|
+
expect(rollbackCall?.partialState.subsessionsCreated).toBe(1)
|
|
204
|
+
expect(rollbackCall?.partialState.assignmentsWritten).toBe(1)
|
|
205
|
+
expect(rollbackCall?.broadcastId).toBe('bc_1')
|
|
206
|
+
|
|
207
|
+
// Phase 8: rollback now fully deletes partial records rather than
|
|
208
|
+
// flipping them to 'archived'. The source session has no children and
|
|
209
|
+
// no orphan child sessions remain under the project.
|
|
210
|
+
const children = await store.getChildren(session.id, tenant)
|
|
211
|
+
expect(children).toHaveLength(0)
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
it('rollback performs full cleanup via deleteSubSession/deleteSession (no status-flip stopgap)', async () => {
|
|
215
|
+
const { project, thread, session } = await seedIdle(store, threadStore)
|
|
216
|
+
|
|
217
|
+
let addCount = 0
|
|
218
|
+
const exec: ExecFile = async (_file, args) => {
|
|
219
|
+
if (args.includes('add')) {
|
|
220
|
+
addCount += 1
|
|
221
|
+
if (addCount === 2) throw new Error('simulated failure')
|
|
222
|
+
}
|
|
223
|
+
return okExec()
|
|
224
|
+
}
|
|
225
|
+
const { deps } = buildDeps(store, threadStore, exec)
|
|
226
|
+
|
|
227
|
+
const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
|
|
228
|
+
user('usr_b'),
|
|
229
|
+
user('usr_c'),
|
|
230
|
+
])
|
|
231
|
+
|
|
232
|
+
await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow()
|
|
233
|
+
|
|
234
|
+
// No sub-session record remains.
|
|
235
|
+
const children = await store.getChildren(session.id, tenant)
|
|
236
|
+
expect(children).toHaveLength(0)
|
|
237
|
+
|
|
238
|
+
// Source is back to idle with its original ownerVersion (unchanged because
|
|
239
|
+
// the CAS commit never landed).
|
|
240
|
+
const reloaded = await store.getSession(session.id, tenant)
|
|
241
|
+
expect(reloaded?.status).toBe('idle')
|
|
242
|
+
expect(reloaded?.ownerVersion).toBe(0)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
it('rollback idempotency: worktree dispose throwing during rollback does not bubble a secondary failure', async () => {
|
|
246
|
+
const { project, thread, session } = await seedIdle(store, threadStore)
|
|
247
|
+
|
|
248
|
+
let addCount = 0
|
|
249
|
+
let removeCount = 0
|
|
250
|
+
const exec: ExecFile = async (_file, args) => {
|
|
251
|
+
if (args.includes('add')) {
|
|
252
|
+
addCount += 1
|
|
253
|
+
if (addCount === 2) throw new Error('primary: mid-fanout add failure')
|
|
254
|
+
}
|
|
255
|
+
if (args.includes('remove')) {
|
|
256
|
+
removeCount += 1
|
|
257
|
+
// Throw an unclassified error so the regex in dispose does NOT treat
|
|
258
|
+
// it as idempotent success — exercises the outer try/catch in the
|
|
259
|
+
// rollback loop.
|
|
260
|
+
throw new Error('secondary rollback dispose failure (unexpected)')
|
|
261
|
+
}
|
|
262
|
+
return okExec()
|
|
263
|
+
}
|
|
264
|
+
const { deps, events } = buildDeps(store, threadStore, exec)
|
|
265
|
+
|
|
266
|
+
const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
|
|
267
|
+
user('usr_b'),
|
|
268
|
+
user('usr_c'),
|
|
269
|
+
])
|
|
270
|
+
|
|
271
|
+
// Outer failure is the PRIMARY one — the secondary dispose failure is
|
|
272
|
+
// swallowed. Primary wraps in WorkspaceBackendError (create op).
|
|
273
|
+
await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
|
|
274
|
+
/Workspace backend git-worktree failed on create/,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
expect(removeCount).toBeGreaterThanOrEqual(1)
|
|
278
|
+
expect(events.onBroadcastRollback).toHaveBeenCalledTimes(1)
|
|
279
|
+
|
|
280
|
+
// Source is idle (rollback succeeded at the store layer even if dispose
|
|
281
|
+
// partially failed).
|
|
282
|
+
const reloaded = await store.getSession(session.id, tenant)
|
|
283
|
+
expect(reloaded?.status).toBe('idle')
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it('dedupe: two assignments targeting same recipient → rejected pre-lock (no side effects)', async () => {
|
|
287
|
+
const { project, thread, session } = await seedIdle(store, threadStore)
|
|
288
|
+
const { deps, events } = buildDeps(store, threadStore)
|
|
289
|
+
|
|
290
|
+
const bob = user('usr_bob')
|
|
291
|
+
const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
|
|
292
|
+
bob,
|
|
293
|
+
bob,
|
|
294
|
+
user('usr_dan'),
|
|
295
|
+
])
|
|
296
|
+
|
|
297
|
+
await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
|
|
298
|
+
/duplicate recipient/,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
// Source never locked — no events fired.
|
|
302
|
+
expect(events.onLocked).not.toHaveBeenCalled()
|
|
303
|
+
expect(events.onCommitted).not.toHaveBeenCalled()
|
|
304
|
+
expect(events.onBroadcastRollback).not.toHaveBeenCalled()
|
|
305
|
+
const reloaded = await store.getSession(session.id, tenant)
|
|
306
|
+
expect(reloaded?.status).toBe('idle')
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
it('width cap: 9 recipients exceeds default maxWidth=8 → rejected before source lock', async () => {
|
|
310
|
+
const { project, thread, session } = await seedIdle(store, threadStore)
|
|
311
|
+
const { deps, events } = buildDeps(store, threadStore)
|
|
312
|
+
|
|
313
|
+
const recipients = Array.from({ length: 9 }, (_, i) => user(`usr_${i}`))
|
|
314
|
+
const assignments = buildAssignments(session.id, project.id, thread.id, 0, recipients)
|
|
315
|
+
|
|
316
|
+
await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
|
|
317
|
+
/Delegation capacity exceeded/,
|
|
318
|
+
)
|
|
319
|
+
expect(events.onLocked).not.toHaveBeenCalled()
|
|
320
|
+
expect(events.onBroadcastRollback).not.toHaveBeenCalled()
|
|
321
|
+
|
|
322
|
+
const reloaded = await store.getSession(session.id, tenant)
|
|
323
|
+
expect(reloaded?.status).toBe('idle')
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
it('concurrent broadcast on same source: second attempt rejected with HandoffVersionConflict', async () => {
|
|
327
|
+
const { project, thread, session } = await seedIdle(store, threadStore)
|
|
328
|
+
const { deps } = buildDeps(store, threadStore)
|
|
329
|
+
|
|
330
|
+
const firstAssignments = buildAssignments(
|
|
331
|
+
session.id,
|
|
332
|
+
project.id,
|
|
333
|
+
thread.id,
|
|
334
|
+
0,
|
|
335
|
+
[user('usr_b'), user('usr_c')],
|
|
336
|
+
'bc_1',
|
|
337
|
+
)
|
|
338
|
+
await executeBroadcastHandoff(deps, firstAssignments, tenant)
|
|
339
|
+
|
|
340
|
+
// Second broadcast still has expectedOwnerVersion = 0 but source is now 1.
|
|
341
|
+
// It should also observe source.status === 'awaiting_merge' (non-idle) —
|
|
342
|
+
// that rejects with HandoffLockRejected BEFORE the CAS check fires. To
|
|
343
|
+
// exercise the CAS path, reset source to `idle` (simulating all recipients
|
|
344
|
+
// completing) and THEN attempt the second handoff with stale expected=0.
|
|
345
|
+
const reloaded = await store.getSession(session.id, tenant)
|
|
346
|
+
if (!reloaded) throw new Error('source missing')
|
|
347
|
+
await store.updateSession({ ...reloaded, status: 'idle' }, tenant)
|
|
348
|
+
|
|
349
|
+
const second = buildAssignments(
|
|
350
|
+
session.id,
|
|
351
|
+
project.id,
|
|
352
|
+
thread.id,
|
|
353
|
+
0, // stale — actual is 1
|
|
354
|
+
[user('usr_d'), user('usr_e')],
|
|
355
|
+
'bc_2',
|
|
356
|
+
)
|
|
357
|
+
await expect(executeBroadcastHandoff(deps, second, tenant)).rejects.toBeInstanceOf(
|
|
358
|
+
HandoffVersionConflict,
|
|
359
|
+
)
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
it('empty assignments → throws a descriptive error', async () => {
|
|
363
|
+
const { deps } = buildDeps(store, threadStore)
|
|
364
|
+
await expect(executeBroadcastHandoff(deps, [], tenant)).rejects.toThrow(
|
|
365
|
+
/assignments must not be empty/,
|
|
366
|
+
)
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
it('single-row broadcast → rejected (caller must use executeSingleHandoff)', async () => {
|
|
370
|
+
const { project, thread, session } = await seedIdle(store, threadStore)
|
|
371
|
+
const { deps } = buildDeps(store, threadStore)
|
|
372
|
+
const assignments = buildAssignments(session.id, project.id, thread.id, 0, [user('usr_b')])
|
|
373
|
+
|
|
374
|
+
await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
|
|
375
|
+
/single-recipient handoffs must use executeSingleHandoff/,
|
|
376
|
+
)
|
|
377
|
+
})
|
|
378
|
+
})
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import type { ActorRef } from '../../../session/hierarchy/actor.js'
|
|
3
|
+
import { InMemorySessionStore } from '../../../store/session/memory.js'
|
|
4
|
+
import { InMemoryThreadStore } from '../../../store/thread/memory.js'
|
|
5
|
+
import type { AgentId, SessionId, TenantId, UserId } from '../../../types/ids/index.js'
|
|
6
|
+
import type { ProjectId, ThreadId } from '../../../types/session/ids.js'
|
|
7
|
+
import { DefaultCapacityValidator, DelegationCapacityExceeded } from '../capacity.js'
|
|
8
|
+
|
|
9
|
+
const tenant = 'tnt_alpha' as TenantId
|
|
10
|
+
|
|
11
|
+
function user(): ActorRef {
|
|
12
|
+
return { kind: 'user', userId: 'usr_a' as UserId, tenantId: tenant }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function agent(): ActorRef {
|
|
16
|
+
return { kind: 'agent', agentId: 'agt_a' as AgentId, tenantId: tenant }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function seedProject(store: InMemorySessionStore) {
|
|
20
|
+
const project = await store.createProject({ tenantId: tenant, name: 'p' }, tenant)
|
|
21
|
+
const threadStore = new InMemoryThreadStore()
|
|
22
|
+
const thread = await threadStore.createThread({ projectId: project.id, title: 'default' }, tenant)
|
|
23
|
+
const root = await store.createSession(
|
|
24
|
+
{ threadId: thread.id, projectId: project.id, currentActor: user() },
|
|
25
|
+
tenant,
|
|
26
|
+
)
|
|
27
|
+
return { project, thread, root }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function spawnChild(
|
|
31
|
+
store: InMemorySessionStore,
|
|
32
|
+
parentId: SessionId,
|
|
33
|
+
projectId: ProjectId,
|
|
34
|
+
threadId: ThreadId,
|
|
35
|
+
): Promise<{ childId: SessionId }> {
|
|
36
|
+
const child = await store.createSession({ threadId, projectId, currentActor: user() }, tenant)
|
|
37
|
+
await store.createSubSession(
|
|
38
|
+
{
|
|
39
|
+
parentSessionId: parentId,
|
|
40
|
+
childSessionId: child.id,
|
|
41
|
+
kind: 'agent_spawn',
|
|
42
|
+
spawnedBy: agent(),
|
|
43
|
+
},
|
|
44
|
+
tenant,
|
|
45
|
+
)
|
|
46
|
+
return { childId: child.id }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe('DefaultCapacityValidator', () => {
|
|
50
|
+
it('depth: root session validates against limit 4 (new child would be depth 1) — passes', async () => {
|
|
51
|
+
const store = new InMemorySessionStore()
|
|
52
|
+
const { root } = await seedProject(store)
|
|
53
|
+
const validator = new DefaultCapacityValidator(store)
|
|
54
|
+
|
|
55
|
+
await expect(validator.validateDepth(root.id, 4, tenant)).resolves.toBeUndefined()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('depth: chain of 4 (root→c1→c2→c3→c4) allows a 5th (depth 5) to pass when limit = 5', async () => {
|
|
59
|
+
const store = new InMemorySessionStore()
|
|
60
|
+
const { project, thread, root } = await seedProject(store)
|
|
61
|
+
const c1 = await spawnChild(store, root.id, project.id, thread.id)
|
|
62
|
+
const c2 = await spawnChild(store, c1.childId, project.id, thread.id)
|
|
63
|
+
const c3 = await spawnChild(store, c2.childId, project.id, thread.id)
|
|
64
|
+
const c4 = await spawnChild(store, c3.childId, project.id, thread.id)
|
|
65
|
+
|
|
66
|
+
const validator = new DefaultCapacityValidator(store)
|
|
67
|
+
// Ancestry of c4: root→c1→c2→c3→c4 = length 5. Spawning under c4 = depth 5.
|
|
68
|
+
await expect(validator.validateDepth(c4.childId, 5, tenant)).resolves.toBeUndefined()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('depth: over-limit throws DelegationCapacityExceeded with dimension=depth', async () => {
|
|
72
|
+
const store = new InMemorySessionStore()
|
|
73
|
+
const { project, thread, root } = await seedProject(store)
|
|
74
|
+
const c1 = await spawnChild(store, root.id, project.id, thread.id)
|
|
75
|
+
const c2 = await spawnChild(store, c1.childId, project.id, thread.id)
|
|
76
|
+
const c3 = await spawnChild(store, c2.childId, project.id, thread.id)
|
|
77
|
+
const c4 = await spawnChild(store, c3.childId, project.id, thread.id)
|
|
78
|
+
|
|
79
|
+
const validator = new DefaultCapacityValidator(store)
|
|
80
|
+
try {
|
|
81
|
+
// Ancestry of c4 has length 5; limit=4 means depth 5 > 4 → reject.
|
|
82
|
+
await validator.validateDepth(c4.childId, 4, tenant)
|
|
83
|
+
expect.fail('expected DelegationCapacityExceeded')
|
|
84
|
+
} catch (err) {
|
|
85
|
+
expect(err).toBeInstanceOf(DelegationCapacityExceeded)
|
|
86
|
+
const e = err as DelegationCapacityExceeded
|
|
87
|
+
expect(e.details.dimension).toBe('depth')
|
|
88
|
+
expect(e.details.limit).toBe(4)
|
|
89
|
+
expect(e.details.current).toBe(5)
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('width: empty parent with 4 pending children passes limit=8', async () => {
|
|
94
|
+
const store = new InMemorySessionStore()
|
|
95
|
+
const { root } = await seedProject(store)
|
|
96
|
+
const validator = new DefaultCapacityValidator(store)
|
|
97
|
+
|
|
98
|
+
await expect(validator.validateWidth(root.id, 4, 8, tenant)).resolves.toBeUndefined()
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('width: existing 5 + pending 3 = 8 passes exactly at the limit', async () => {
|
|
102
|
+
const store = new InMemorySessionStore()
|
|
103
|
+
const { project, thread, root } = await seedProject(store)
|
|
104
|
+
for (let i = 0; i < 5; i++) {
|
|
105
|
+
await spawnChild(store, root.id, project.id, thread.id)
|
|
106
|
+
}
|
|
107
|
+
const validator = new DefaultCapacityValidator(store)
|
|
108
|
+
await expect(validator.validateWidth(root.id, 3, 8, tenant)).resolves.toBeUndefined()
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('width: existing 6 + pending 3 = 9 exceeds 8, throws dimension=width', async () => {
|
|
112
|
+
const store = new InMemorySessionStore()
|
|
113
|
+
const { project, thread, root } = await seedProject(store)
|
|
114
|
+
for (let i = 0; i < 6; i++) {
|
|
115
|
+
await spawnChild(store, root.id, project.id, thread.id)
|
|
116
|
+
}
|
|
117
|
+
const validator = new DefaultCapacityValidator(store)
|
|
118
|
+
try {
|
|
119
|
+
await validator.validateWidth(root.id, 3, 8, tenant)
|
|
120
|
+
expect.fail('expected DelegationCapacityExceeded')
|
|
121
|
+
} catch (err) {
|
|
122
|
+
expect(err).toBeInstanceOf(DelegationCapacityExceeded)
|
|
123
|
+
const e = err as DelegationCapacityExceeded
|
|
124
|
+
expect(e.details.dimension).toBe('width')
|
|
125
|
+
expect(e.details.current).toBe(9)
|
|
126
|
+
expect(e.details.limit).toBe(8)
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
})
|