@victframework/runtime 0.1.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.
Files changed (115) hide show
  1. package/dist/agent-governance.d.ts +285 -0
  2. package/dist/agent-governance.js +438 -0
  3. package/dist/agent-governance.js.map +1 -0
  4. package/dist/agent-registry.d.ts +103 -0
  5. package/dist/agent-registry.js +758 -0
  6. package/dist/agent-registry.js.map +1 -0
  7. package/dist/agent-types.d.ts +433 -0
  8. package/dist/agent-types.js +480 -0
  9. package/dist/agent-types.js.map +1 -0
  10. package/dist/authority.d.ts +83 -0
  11. package/dist/authority.js +170 -0
  12. package/dist/authority.js.map +1 -0
  13. package/dist/boundary-conformance.d.ts +51 -0
  14. package/dist/boundary-conformance.js +364 -0
  15. package/dist/boundary-conformance.js.map +1 -0
  16. package/dist/control-conformance.d.ts +68 -0
  17. package/dist/control-conformance.js +1131 -0
  18. package/dist/control-conformance.js.map +1 -0
  19. package/dist/control-in-memory.d.ts +257 -0
  20. package/dist/control-in-memory.js +886 -0
  21. package/dist/control-in-memory.js.map +1 -0
  22. package/dist/control-types.d.ts +1017 -0
  23. package/dist/control-types.js +779 -0
  24. package/dist/control-types.js.map +1 -0
  25. package/dist/durable-run.d.ts +73 -0
  26. package/dist/durable-run.js +262 -0
  27. package/dist/durable-run.js.map +1 -0
  28. package/dist/effect-policy.d.ts +22 -0
  29. package/dist/effect-policy.js +45 -0
  30. package/dist/effect-policy.js.map +1 -0
  31. package/dist/errors.d.ts +36 -0
  32. package/dist/errors.js +71 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/in-memory-stores.d.ts +16 -0
  35. package/dist/in-memory-stores.js +522 -0
  36. package/dist/in-memory-stores.js.map +1 -0
  37. package/dist/index.d.ts +41 -0
  38. package/dist/index.js +26 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/operator-config.d.ts +141 -0
  41. package/dist/operator-config.js +289 -0
  42. package/dist/operator-config.js.map +1 -0
  43. package/dist/orchestration-activation.d.ts +116 -0
  44. package/dist/orchestration-activation.js +223 -0
  45. package/dist/orchestration-activation.js.map +1 -0
  46. package/dist/orchestration-canary-conformance.d.ts +10 -0
  47. package/dist/orchestration-canary-conformance.js +726 -0
  48. package/dist/orchestration-canary-conformance.js.map +1 -0
  49. package/dist/orchestration-commands.d.ts +47 -0
  50. package/dist/orchestration-commands.js +538 -0
  51. package/dist/orchestration-commands.js.map +1 -0
  52. package/dist/orchestration-conformance.d.ts +59 -0
  53. package/dist/orchestration-conformance.js +594 -0
  54. package/dist/orchestration-conformance.js.map +1 -0
  55. package/dist/orchestration-driver-types.d.ts +163 -0
  56. package/dist/orchestration-driver-types.js +21 -0
  57. package/dist/orchestration-driver-types.js.map +1 -0
  58. package/dist/orchestration-driver.d.ts +48 -0
  59. package/dist/orchestration-driver.js +1030 -0
  60. package/dist/orchestration-driver.js.map +1 -0
  61. package/dist/orchestration-in-memory.d.ts +18 -0
  62. package/dist/orchestration-in-memory.js +1313 -0
  63. package/dist/orchestration-in-memory.js.map +1 -0
  64. package/dist/orchestration-join-conformance.d.ts +20 -0
  65. package/dist/orchestration-join-conformance.js +542 -0
  66. package/dist/orchestration-join-conformance.js.map +1 -0
  67. package/dist/orchestration-plan.d.ts +52 -0
  68. package/dist/orchestration-plan.js +265 -0
  69. package/dist/orchestration-plan.js.map +1 -0
  70. package/dist/orchestration-race-conformance.d.ts +35 -0
  71. package/dist/orchestration-race-conformance.js +1265 -0
  72. package/dist/orchestration-race-conformance.js.map +1 -0
  73. package/dist/orchestration-remediation-conformance.d.ts +54 -0
  74. package/dist/orchestration-remediation-conformance.js +632 -0
  75. package/dist/orchestration-remediation-conformance.js.map +1 -0
  76. package/dist/orchestration-store-types.d.ts +568 -0
  77. package/dist/orchestration-store-types.js +2 -0
  78. package/dist/orchestration-store-types.js.map +1 -0
  79. package/dist/pack-conformance.d.ts +59 -0
  80. package/dist/pack-conformance.js +222 -0
  81. package/dist/pack-conformance.js.map +1 -0
  82. package/dist/pack-install.d.ts +44 -0
  83. package/dist/pack-install.js +126 -0
  84. package/dist/pack-install.js.map +1 -0
  85. package/dist/registry.d.ts +107 -0
  86. package/dist/registry.js +481 -0
  87. package/dist/registry.js.map +1 -0
  88. package/dist/runtime.d.ts +158 -0
  89. package/dist/runtime.js +1341 -0
  90. package/dist/runtime.js.map +1 -0
  91. package/dist/serialization.d.ts +26 -0
  92. package/dist/serialization.js +162 -0
  93. package/dist/serialization.js.map +1 -0
  94. package/dist/store-conformance.d.ts +45 -0
  95. package/dist/store-conformance.js +876 -0
  96. package/dist/store-conformance.js.map +1 -0
  97. package/dist/store-errors.d.ts +49 -0
  98. package/dist/store-errors.js +48 -0
  99. package/dist/store-errors.js.map +1 -0
  100. package/dist/store-types.d.ts +331 -0
  101. package/dist/store-types.js +14 -0
  102. package/dist/store-types.js.map +1 -0
  103. package/dist/store-validation.d.ts +63 -0
  104. package/dist/store-validation.js +164 -0
  105. package/dist/store-validation.js.map +1 -0
  106. package/dist/stream-hub.d.ts +151 -0
  107. package/dist/stream-hub.js +402 -0
  108. package/dist/stream-hub.js.map +1 -0
  109. package/dist/testing.d.ts +25 -0
  110. package/dist/testing.js +19 -0
  111. package/dist/testing.js.map +1 -0
  112. package/dist/types.d.ts +221 -0
  113. package/dist/types.js +2 -0
  114. package/dist/types.js.map +1 -0
  115. package/package.json +45 -0
@@ -0,0 +1,164 @@
1
+ import { canonicalJson, canonicalSemanticForm, canonicalSemanticFormV2, computeActivationVersion, computeCapabilitySetVersion, computeGraphVersion, } from '@victframework/kernel';
2
+ import { VictStoreError } from './store-errors.js';
3
+ /**
4
+ * Shared store-level identity validation, executed identically by every
5
+ * conforming adapter (in-memory and SQLite).
6
+ *
7
+ * Identity is CONTENT-derived (Stage 02): the three activation identities
8
+ * are SHA-256 fingerprints computed by the kernel's canonical identity
9
+ * functions. Stores therefore do not trust top-level strings — they
10
+ * recompute every identity from the canonical content and reject any
11
+ * disagreement with a structured, safe error and no partial mutation.
12
+ */
13
+ function mismatch(operation, message, details) {
14
+ return new VictStoreError('VICT_STORE_ACTIVATION_MISMATCH', message, {
15
+ operation,
16
+ ...details,
17
+ });
18
+ }
19
+ /**
20
+ * Publish-time validation: the supplied canonical JSON must be exactly the
21
+ * canonical representation of the supplied manifest, and every
22
+ * content-derived identity must be reproducible from that content:
23
+ *
24
+ * - `manifest.graph` must already be the canonical semantic form of the
25
+ * graph declaration;
26
+ * - `graphVersion` must equal the canonical fingerprint of that form;
27
+ * - `capabilitySetVersion` must equal the canonical fingerprint of the
28
+ * effective bindings;
29
+ * - `activationVersion` must equal the canonical combination of the two.
30
+ *
31
+ * This catches manifests whose top-level identifiers look valid while the
32
+ * binding or graph content differs (the identity would not recompute).
33
+ */
34
+ export function assertPublishableManifest(command) {
35
+ const manifest = command.manifest;
36
+ if (typeof command.canonicalManifest !== 'string' || command.canonicalManifest.length === 0) {
37
+ throw new VictStoreError('VICT_STORE_INVALID_COMMAND', 'A canonical manifest string is required.', { operation: 'catalog.publish' });
38
+ }
39
+ let recomputed;
40
+ try {
41
+ recomputed = canonicalJson(manifest);
42
+ }
43
+ catch {
44
+ throw new VictStoreError('VICT_STORE_INVALID_COMMAND', 'The manifest is not a persistable canonical value.', { operation: 'catalog.publish' });
45
+ }
46
+ if (recomputed !== command.canonicalManifest) {
47
+ throw mismatch('catalog.publish', 'The supplied canonical manifest is not the canonical representation of the supplied manifest.', { activationVersion: manifest.activationVersion });
48
+ }
49
+ const isV2 = manifest.graph?.schema === 'vict.graph@2';
50
+ let canonicalGraph;
51
+ try {
52
+ // canonicalSemanticForm is idempotent on an already-canonical graph;
53
+ // comparing its JSON against the stored form detects tampering.
54
+ canonicalGraph = isV2
55
+ ? canonicalSemanticFormV2(manifest.graph)
56
+ : canonicalSemanticForm(manifest.graph);
57
+ }
58
+ catch {
59
+ throw mismatch('catalog.publish', 'The manifest graph declaration is not in canonical semantic form.', { activationVersion: manifest.activationVersion });
60
+ }
61
+ if (canonicalJson(canonicalGraph) !== canonicalJson(manifest.graph)) {
62
+ throw mismatch('catalog.publish', 'The manifest graph declaration is not in canonical semantic form.', { activationVersion: manifest.activationVersion });
63
+ }
64
+ let graphVersion;
65
+ try {
66
+ graphVersion = computeGraphVersion(manifest.graph);
67
+ }
68
+ catch {
69
+ throw mismatch('catalog.publish', 'The graph version could not be recomputed from the manifest content.', { activationVersion: manifest.activationVersion });
70
+ }
71
+ if (graphVersion !== manifest.graphVersion) {
72
+ throw mismatch('catalog.publish', 'The manifest graphVersion does not match its graph content.', { activationVersion: manifest.activationVersion });
73
+ }
74
+ let capabilitySetVersion;
75
+ try {
76
+ capabilitySetVersion = computeCapabilitySetVersion(manifest.bindings);
77
+ }
78
+ catch {
79
+ throw mismatch('catalog.publish', 'The capability-set version could not be recomputed from the manifest bindings.', { activationVersion: manifest.activationVersion });
80
+ }
81
+ if (capabilitySetVersion !== manifest.capabilitySetVersion) {
82
+ throw mismatch('catalog.publish', 'The manifest capabilitySetVersion does not match its bindings.', { activationVersion: manifest.activationVersion });
83
+ }
84
+ const activationVersion = computeActivationVersion(graphVersion, capabilitySetVersion, graphVersion.startsWith('v2_') ? 'vict.activation@2' : 'vict.activation@1');
85
+ if (activationVersion !== manifest.activationVersion) {
86
+ throw mismatch('catalog.publish', 'The manifest activationVersion does not match its graph and capability-set versions.', { activationVersion: manifest.activationVersion });
87
+ }
88
+ }
89
+ /**
90
+ * Run-creation validation: the run's graph, graph version, capability-set
91
+ * version, and activation version must describe ONE coherent published
92
+ * activation — the exact stored one.
93
+ */
94
+ export function assertRunMatchesActivation(stored, identity, operation) {
95
+ if (stored.graphId !== identity.graphId ||
96
+ stored.graphVersion !== identity.graphVersion ||
97
+ stored.capabilitySetVersion !== identity.capabilitySetVersion ||
98
+ stored.activationVersion !== identity.activationVersion) {
99
+ throw mismatch(operation, 'The run identity does not describe the referenced published activation.', {
100
+ activationVersion: identity.activationVersion,
101
+ graphId: identity.graphId,
102
+ });
103
+ }
104
+ }
105
+ /**
106
+ * Selection validation: an activation may only be selected for the graph it
107
+ * belongs to.
108
+ */
109
+ export function assertActivationBelongsToGraph(stored, graphId, operation) {
110
+ if (stored.graphId !== graphId) {
111
+ throw mismatch(operation, 'The activation does not belong to the graph being selected for.', {
112
+ activationVersion: stored.activationVersion,
113
+ graphId,
114
+ });
115
+ }
116
+ }
117
+ /**
118
+ * Event-append validation: every appended event must carry exactly its
119
+ * stored run's identity columns.
120
+ */
121
+ export function assertEventMatchesRun(event, run) {
122
+ if (event.runId !== run.runId ||
123
+ event.graphId !== run.graphId ||
124
+ event.graphVersion !== run.graphVersion ||
125
+ event.capabilitySetVersion !== run.capabilitySetVersion ||
126
+ event.activationVersion !== run.activationVersion) {
127
+ throw new VictStoreError('VICT_STORE_INVALID_COMMAND', 'An event references a different run or activation identity than the transition targets.', { operation: 'execution.appendEvents', runId: run.runId, eventRunId: event.runId });
128
+ }
129
+ }
130
+ /**
131
+ * Read-time validation for a stored activation: recompute every identity
132
+ * from the persisted canonical manifest and reject corrupt content instead
133
+ * of silently normalizing it. Used defensively on read paths.
134
+ */
135
+ export function assertStoredActivationReadable(row) {
136
+ const fail = () => new VictStoreError('VICT_STORE_INVALID_RECORD', 'A stored activation manifest disagrees with its identity columns.', { operation: 'catalog.readActivation', activationVersion: row.activationVersion });
137
+ const manifest = row.manifest;
138
+ if (manifest.activationVersion !== row.activationVersion ||
139
+ manifest.graphId !== row.graphId ||
140
+ manifest.graphVersion !== row.graphVersion ||
141
+ manifest.capabilitySetVersion !== row.capabilitySetVersion) {
142
+ throw fail();
143
+ }
144
+ try {
145
+ const isV2 = manifest.graph?.schema === 'vict.graph@2';
146
+ const canonicalGraph = isV2
147
+ ? canonicalSemanticFormV2(manifest.graph)
148
+ : canonicalSemanticForm(manifest.graph);
149
+ if (canonicalJson(canonicalGraph) !== canonicalJson(manifest.graph) ||
150
+ computeGraphVersion(manifest.graph) !==
151
+ manifest.graphVersion ||
152
+ computeCapabilitySetVersion(manifest.bindings) !== manifest.capabilitySetVersion ||
153
+ computeActivationVersion(manifest.graphVersion, manifest.capabilitySetVersion, manifest.graphVersion.startsWith('v2_') ? 'vict.activation@2' : 'vict.activation@1') !== manifest.activationVersion) {
154
+ throw fail();
155
+ }
156
+ }
157
+ catch (cause) {
158
+ if (cause instanceof VictStoreError) {
159
+ throw cause;
160
+ }
161
+ throw fail();
162
+ }
163
+ }
164
+ //# sourceMappingURL=store-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-validation.js","sourceRoot":"","sources":["../src/store-validation.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;;;;;;GASG;AAEH,SAAS,QAAQ,CACf,SAAiB,EACjB,OAAe,EACf,OAAgC;IAEhC,OAAO,IAAI,cAAc,CAAC,gCAAgC,EAAE,OAAO,EAAE;QACnE,SAAS;QACT,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAiC;IACzE,MAAM,QAAQ,GAAuB,OAAO,CAAC,QAAQ,CAAC;IACtD,IAAI,OAAO,OAAO,CAAC,iBAAiB,KAAK,QAAQ,IAAI,OAAO,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5F,MAAM,IAAI,cAAc,CACtB,4BAA4B,EAC5B,0CAA0C,EAC1C,EAAE,SAAS,EAAE,iBAAiB,EAAE,CACjC,CAAC;IACJ,CAAC;IACD,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CACtB,4BAA4B,EAC5B,oDAAoD,EACpD,EAAE,SAAS,EAAE,iBAAiB,EAAE,CACjC,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC7C,MAAM,QAAQ,CACZ,iBAAiB,EACjB,+FAA+F,EAC/F,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAClD,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAI,QAAQ,CAAC,KAAoC,EAAE,MAAM,KAAK,cAAc,CAAC;IACvF,IAAI,cAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,qEAAqE;QACrE,gEAAgE;QAChE,cAAc,GAAG,IAAI;YACnB,CAAC,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAsD,CAAC;YAC1F,CAAC,CAAC,qBAAqB,CAAC,QAAQ,CAAC,KAAoD,CAAC,CAAC;IAC3F,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,QAAQ,CACZ,iBAAiB,EACjB,mEAAmE,EACnE,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAClD,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,CAAC,cAAc,CAAC,KAAK,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpE,MAAM,QAAQ,CACZ,iBAAiB,EACjB,mEAAmE,EACnE,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAClD,CAAC;IACJ,CAAC;IACD,IAAI,YAAoB,CAAC;IACzB,IAAI,CAAC;QACH,YAAY,GAAG,mBAAmB,CAAC,QAAQ,CAAC,KAAkD,CAAC,CAAC;IAClG,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,QAAQ,CACZ,iBAAiB,EACjB,sEAAsE,EACtE,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAClD,CAAC;IACJ,CAAC;IACD,IAAI,YAAY,KAAK,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC3C,MAAM,QAAQ,CACZ,iBAAiB,EACjB,6DAA6D,EAC7D,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAClD,CAAC;IACJ,CAAC;IACD,IAAI,oBAA4B,CAAC;IACjC,IAAI,CAAC;QACH,oBAAoB,GAAG,2BAA2B,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,QAAQ,CACZ,iBAAiB,EACjB,gFAAgF,EAChF,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAClD,CAAC;IACJ,CAAC;IACD,IAAI,oBAAoB,KAAK,QAAQ,CAAC,oBAAoB,EAAE,CAAC;QAC3D,MAAM,QAAQ,CACZ,iBAAiB,EACjB,gEAAgE,EAChE,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAClD,CAAC;IACJ,CAAC;IACD,MAAM,iBAAiB,GAAG,wBAAwB,CAChD,YAAY,EACZ,oBAAoB,EACpB,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,CAC3E,CAAC;IACF,IAAI,iBAAiB,KAAK,QAAQ,CAAC,iBAAiB,EAAE,CAAC;QACrD,MAAM,QAAQ,CACZ,iBAAiB,EACjB,sFAAsF,EACtF,EAAE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,CAClD,CAAC;IACJ,CAAC;AACH,CAAC;AASD;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAA0B,EAC1B,QAA4B,EAC5B,SAAiB;IAEjB,IACE,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,OAAO;QACnC,MAAM,CAAC,YAAY,KAAK,QAAQ,CAAC,YAAY;QAC7C,MAAM,CAAC,oBAAoB,KAAK,QAAQ,CAAC,oBAAoB;QAC7D,MAAM,CAAC,iBAAiB,KAAK,QAAQ,CAAC,iBAAiB,EACvD,CAAC;QACD,MAAM,QAAQ,CACZ,SAAS,EACT,yEAAyE,EACzE;YACE,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;YAC7C,OAAO,EAAE,QAAQ,CAAC,OAAO;SAC1B,CACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC5C,MAAwE,EACxE,OAAe,EACf,SAAiB;IAEjB,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC/B,MAAM,QAAQ,CAAC,SAAS,EAAE,iEAAiE,EAAE;YAC3F,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;YAC3C,OAAO;SACR,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAUD;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAkB,EAAE,GAAuB;IAC/E,IACE,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK;QACzB,KAAK,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO;QAC7B,KAAK,CAAC,YAAY,KAAK,GAAG,CAAC,YAAY;QACvC,KAAK,CAAC,oBAAoB,KAAK,GAAG,CAAC,oBAAoB;QACvD,KAAK,CAAC,iBAAiB,KAAK,GAAG,CAAC,iBAAiB,EACjD,CAAC;QACD,MAAM,IAAI,cAAc,CACtB,4BAA4B,EAC5B,yFAAyF,EACzF,EAAE,SAAS,EAAE,wBAAwB,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,KAAK,EAAE,CACnF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,GAO9C;IACC,MAAM,IAAI,GAAG,GAAmB,EAAE,CAChC,IAAI,cAAc,CAChB,2BAA2B,EAC3B,mEAAmE,EACnE,EAAE,SAAS,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,EAAE,CAClF,CAAC;IACJ,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;IAC9B,IACE,QAAQ,CAAC,iBAAiB,KAAK,GAAG,CAAC,iBAAiB;QACpD,QAAQ,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO;QAChC,QAAQ,CAAC,YAAY,KAAK,GAAG,CAAC,YAAY;QAC1C,QAAQ,CAAC,oBAAoB,KAAK,GAAG,CAAC,oBAAoB,EAC1D,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAI,QAAQ,CAAC,KAAoC,EAAE,MAAM,KAAK,cAAc,CAAC;QACvF,MAAM,cAAc,GAAG,IAAI;YACzB,CAAC,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAsD,CAAC;YAC1F,CAAC,CAAC,qBAAqB,CAAC,QAAQ,CAAC,KAAoD,CAAC,CAAC;QACzF,IACE,aAAa,CAAC,cAAc,CAAC,KAAK,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC/D,mBAAmB,CAAC,QAAQ,CAAC,KAAkD,CAAC;gBAC9E,QAAQ,CAAC,YAAY;YACvB,2BAA2B,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,oBAAoB;YAChF,wBAAwB,CACtB,QAAQ,CAAC,YAAY,EACrB,QAAQ,CAAC,oBAAoB,EAC7B,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,CACpF,KAAK,QAAQ,CAAC,iBAAiB,EAChC,CAAC;YACD,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;YACpC,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,151 @@
1
+ import { type AgentStreamEvent } from '@victframework/contracts';
2
+ import type { AgentStreamLedgerStore } from './control-types.js';
3
+ /**
4
+ * Stage 06B — the neutral agent-stream hub (AI-009).
5
+ *
6
+ * One hub owns the per-stream event flow above a durable ledger:
7
+ *
8
+ * - every event is validated against the FINAL `vict.agent-stream@1`
9
+ * field-level schema (fail closed on unknown kinds/fields);
10
+ * - sequence numbers are assigned by the durable ledger (strictly
11
+ * monotonic per stream, survive restart);
12
+ * - durable kinds are persisted ledger rows; `text.delta` is transient and
13
+ * lives only in the bounded replay buffer;
14
+ * - delivery is at-least-once in sequence order (clients deduplicate by
15
+ * streamId + seq);
16
+ * - replay and live delivery use ISOLATED copies: no stored/frozen event
17
+ * object is ever handed to a subscriber queue or mutated after publish;
18
+ * - backpressure coalesces CONSECUTIVE pending `text.delta` events for a
19
+ * slow subscriber only, and never drops, reorders, or coalesces
20
+ * non-delta events; a coalesced delta carries the cursor semantics of
21
+ * the COMPLETE coalesced range (its sequence is the LAST combined
22
+ * sequence, so a reconnect cannot re-deliver part of its text);
23
+ * - reconnect replays from a cursor: durable ledger rows plus buffered
24
+ * transient deltas, detected against the AUTHORITATIVE ledger
25
+ * high-watermark; a cursor older than the replayable transient content
26
+ * reports `olderThanBuffer` so completed content is recovered from
27
+ * durable state — including after a restart when the memory buffer is
28
+ * empty;
29
+ * - a bounded subscriber queue that overflows follows an EXPLICIT
30
+ * recoverable policy: the subscriber is detached through
31
+ * `onOverflow()` and MUST reconnect/replay from its last acknowledged
32
+ * cursor. Durable, control, and terminal events are never silently
33
+ * discarded.
34
+ *
35
+ * The hub is transport-free: SSE belongs to `@victframework/server`.
36
+ */
37
+ /** One hub subscriber (transport-owned delivery mechanism). */
38
+ export interface AgentStreamSubscriber {
39
+ readonly subscriberId: string;
40
+ /**
41
+ * Deliver one event. Returning `false` signals backpressure: the hub
42
+ * switches this subscriber to buffered mode with delta coalescing until
43
+ * it drains via `pull()`.
44
+ */
45
+ deliver(event: AgentStreamEvent): boolean;
46
+ /**
47
+ * Called when the subscriber's bounded pending queue OVERFLOWS, immediately
48
+ * before the hub detaches the subscriber. The transport MUST recover by
49
+ * reconnecting/replaying from its last acknowledged cursor — the hub never
50
+ * silently discards events to fit the bound.
51
+ */
52
+ onOverflow?(): void;
53
+ /** Called when the subscriber is detached (clean completion or overflow). */
54
+ detach?(): void;
55
+ }
56
+ /** The reconnect cursor: stream identity + last processed sequence. */
57
+ export interface AgentStreamCursor {
58
+ readonly streamId: string;
59
+ readonly lastSeq: number;
60
+ }
61
+ /** Replay/status disclosure for a reconnect (bounded-memory computation). */
62
+ export interface AgentStreamReplayStatus {
63
+ /** The newest sequence the stream has assigned (ledger high-watermark). */
64
+ readonly newestSeq: number;
65
+ /**
66
+ * True when transient content after the cursor is no longer replayable:
67
+ * at least one sequence in `(lastSeq, newestSeq]` is neither a durable
68
+ * row nor a buffered transient delta (lost transient interval), so
69
+ * completed content must be restored from authoritative durable state.
70
+ * Detected against the ledger high-watermark — a fresh hub over the same
71
+ * ledger with an EMPTY memory buffer still reports the lost interval.
72
+ */
73
+ readonly olderThanBuffer: boolean;
74
+ }
75
+ /** Result of a materialized replay. */
76
+ export interface AgentStreamReplay extends AgentStreamReplayStatus {
77
+ readonly events: readonly AgentStreamEvent[];
78
+ }
79
+ export interface AgentStreamHubOptions {
80
+ readonly ledger: AgentStreamLedgerStore;
81
+ /** Injected clock (epoch ms). */
82
+ readonly clock?: () => number;
83
+ /** Bounded transient replay buffer per stream (default 512). */
84
+ readonly transientBufferSize?: number;
85
+ /** Hard pending-queue bound per slow subscriber (default 4096 events). */
86
+ readonly pendingLimit?: number;
87
+ /** Ledger read page size for bounded-memory replay (default 256). */
88
+ readonly replayPageSize?: number;
89
+ }
90
+ export declare class AgentStreamHub {
91
+ #private;
92
+ constructor(options: AgentStreamHubOptions);
93
+ /**
94
+ * Validate and publish one event. Assigns the monotonic sequence via the
95
+ * durable ledger, persists durable kinds, buffers transient deltas, and
96
+ * delivers to subscribers. Throws (fail closed) on any schema-invalid
97
+ * event.
98
+ */
99
+ publish(event: Omit<AgentStreamEvent, 'seq'> & {
100
+ readonly seq?: number;
101
+ }): Promise<AgentStreamEvent>;
102
+ /**
103
+ * Subscribe to a stream and replay everything after the cursor: durable
104
+ * ledger rows plus buffered transient deltas, in strict sequence order.
105
+ *
106
+ * The subscriber is REGISTERED before the ledger is read, so a concurrent
107
+ * publish can never fall into the gap between the replay read and the
108
+ * live attachment: events published during the replay read are captured
109
+ * in the subscriber's private pending queue and delivered in sequence
110
+ * order as part of the backlog.
111
+ *
112
+ * Delivery is at-least-once and CURSOR-DEDUPLICATED. Backpressure NEVER
113
+ * discards events: the remaining backlog is buffered (bounded) for this
114
+ * subscriber and delivered through `pull()`. If the bounded pending
115
+ * queue overflows, the explicit recoverable policy applies: `onOverflow()`
116
+ * is called and the subscriber is detached (reconnect from the last
117
+ * acknowledged cursor).
118
+ */
119
+ subscribe(streamId: string, subscriber: AgentStreamSubscriber, cursor?: {
120
+ lastSeq?: number;
121
+ }): Promise<void>;
122
+ /** Detach a subscriber (clean completion/cancellation/overflow). */
123
+ unsubscribe(streamId: string, subscriberId: string): void;
124
+ /** Latest assigned sequence for a stream (ledger high-watermark). */
125
+ latestSeq(streamId: string): Promise<number>;
126
+ /**
127
+ * Drain the pending queue of a slow subscriber. Consecutive pending
128
+ * `text.delta` events are coalesced into one delta whose sequence is the
129
+ * LAST combined sequence (complete-range cursor semantics: a client that
130
+ * acknowledges the coalesced event acknowledges every delta inside it).
131
+ * Non-delta events are never dropped, reordered, or coalesced. Returned
132
+ * events are private copies of this subscriber's queue — coalescing never
133
+ * mutates any event that another consumer can observe.
134
+ */
135
+ pull(streamId: string, subscriberId: string): readonly AgentStreamEvent[];
136
+ /**
137
+ * Reconnect status WITHOUT materializing the replay: ledger high-watermark
138
+ * plus exact transient-gap detection against the durable rows. Bounded
139
+ * memory: the durable coverage is counted page by page.
140
+ */
141
+ replayStatus(cursor: AgentStreamCursor): Promise<AgentStreamReplayStatus>;
142
+ /**
143
+ * Materialized replay for reconnect: durable ledger rows plus buffered
144
+ * transient deltas after the cursor, in strict sequence order. The
145
+ * returned events are private copies; `olderThanBuffer` is detected
146
+ * against the authoritative ledger high-watermark (exact, restart-safe).
147
+ * For arbitrarily large histories prefer `replayIterate`/`replayStatus`,
148
+ * which never materialize the whole range.
149
+ */
150
+ replay(cursor: AgentStreamCursor): Promise<AgentStreamReplay>;
151
+ }