@hypercarrier/rarebit 0.1.0-alpha.1

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 (50) hide show
  1. package/AGENTS.md +14 -0
  2. package/CHANGELOG.md +10 -0
  3. package/LICENSE +21 -0
  4. package/README.md +142 -0
  5. package/RUNBOOK.md +36 -0
  6. package/SECURITY.md +11 -0
  7. package/VISUAL-LANGUAGE.md +89 -0
  8. package/bin/rarebit.mjs +20 -0
  9. package/package.json +96 -0
  10. package/schemas/rarebit.schema.json +618 -0
  11. package/scripts/e2e-recall-pi083.mjs +199 -0
  12. package/scripts/e2e-summary-cache.mjs +257 -0
  13. package/scripts/verify-package.mjs +81 -0
  14. package/src/automatic-summary-policy.mjs +210 -0
  15. package/src/extension.mjs +516 -0
  16. package/src/herdr-activity.mjs +111 -0
  17. package/src/index.mjs +13 -0
  18. package/src/lifecycle.mjs +322 -0
  19. package/src/rarebit-activity.mjs +48 -0
  20. package/src/rarebit-artifact-state.mjs +839 -0
  21. package/src/rarebit-cli.mjs +305 -0
  22. package/src/rarebit-command.mjs +281 -0
  23. package/src/rarebit-core.mjs +525 -0
  24. package/src/rarebit-model.mjs +226 -0
  25. package/src/rarebit-recall.mjs +182 -0
  26. package/src/rarebit-service.mjs +579 -0
  27. package/src/rarebit-session.mjs +227 -0
  28. package/src/rarebit-settings.mjs +79 -0
  29. package/src/rarebit-store.mjs +771 -0
  30. package/src/rarebit-visual-language.mjs +110 -0
  31. package/src/types.d.ts +601 -0
  32. package/test/automatic-summary-policy.test.mjs +476 -0
  33. package/test/extension-activity.test.mjs +73 -0
  34. package/test/fixtures/branch-mixed.json +117 -0
  35. package/test/fixtures/conformance-corpus.v1.json +306 -0
  36. package/test/fixtures/truncated-mixed.jsonl +2 -0
  37. package/test/herdr-activity.test.mjs +93 -0
  38. package/test/lifecycle-contract-independent.test.mjs +627 -0
  39. package/test/rarebit-activity.test.mjs +82 -0
  40. package/test/rarebit-artifact-state.test.mjs +440 -0
  41. package/test/rarebit-cli.test.mjs +222 -0
  42. package/test/rarebit-command.test.mjs +127 -0
  43. package/test/rarebit-core.test.mjs +461 -0
  44. package/test/rarebit-cross-consumer-conformance.test.mjs +150 -0
  45. package/test/rarebit-independent-contract.test.mjs +317 -0
  46. package/test/rarebit-recall.test.mjs +434 -0
  47. package/test/rarebit-sidecar-protocol.test.mjs +538 -0
  48. package/test/rarebit-visual-language.test.mjs +75 -0
  49. package/test/summary-attention-independent.test.mjs +172 -0
  50. package/test/types-history.ts +13 -0
@@ -0,0 +1,210 @@
1
+ import { randomUUID } from "node:crypto";
2
+
3
+ export const RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT =
4
+ "rarebit-automatic-summary-policy/1";
5
+ export const RAREBIT_AUTOMATIC_SUMMARY_POLICY_EVENT =
6
+ "rarebit:automatic-summary-policy-query";
7
+ export const DEFAULT_AUTOMATIC_SUMMARY_POLICY_TIMEOUT_MS = 100;
8
+ const MAX_PROVIDER_VALIDITY_MS = 5_000;
9
+
10
+ function nonEmptyString(value) {
11
+ return typeof value === "string" && value.trim() ? value : null;
12
+ }
13
+
14
+ function finiteTime(value) {
15
+ const millis = typeof value === "string" ? Date.parse(value) : Number.NaN;
16
+ return Number.isFinite(millis) ? millis : null;
17
+ }
18
+
19
+ function sanitizeOpaqueProvenance(value) {
20
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
21
+ const identity = nonEmptyString(value.identity);
22
+ const generation = nonEmptyString(value.generation);
23
+ const association = nonEmptyString(value.association);
24
+ if (!identity || !generation || !association) return null;
25
+ return { identity, generation, association };
26
+ }
27
+
28
+ function validateResponse(response, query, receivedAt) {
29
+ if (!response || typeof response !== "object" || Array.isArray(response))
30
+ return { ok: false, reason: "malformed_response" };
31
+ if (response.contractVersion !== RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT)
32
+ return { ok: false, reason: "incompatible_response" };
33
+ if (response.queryId !== query.queryId)
34
+ return { ok: false, reason: "uncorrelated_response" };
35
+ if (response.decision !== "inhibit" && response.decision !== "abstain")
36
+ return { ok: false, reason: "invalid_decision" };
37
+ const provider = nonEmptyString(response.provider);
38
+ const reason = nonEmptyString(response.reason);
39
+ const observedAt = finiteTime(response.observedAt);
40
+ const validUntil = finiteTime(response.validUntil);
41
+ if (!provider || !reason || observedAt === null || validUntil === null)
42
+ return { ok: false, reason: "malformed_response" };
43
+ if (
44
+ observedAt < query.issuedAtMillis ||
45
+ observedAt > receivedAt ||
46
+ validUntil < receivedAt ||
47
+ validUntil <= observedAt ||
48
+ validUntil - observedAt > MAX_PROVIDER_VALIDITY_MS
49
+ )
50
+ return { ok: false, reason: "stale_response" };
51
+ const provenance =
52
+ response.decision === "inhibit"
53
+ ? sanitizeOpaqueProvenance(response.provenance)
54
+ : null;
55
+ if (response.decision === "inhibit" && !provenance)
56
+ return { ok: false, reason: "malformed_inhibition_provenance" };
57
+ return {
58
+ ok: true,
59
+ response: {
60
+ contractVersion: RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT,
61
+ queryId: query.queryId,
62
+ decision: response.decision,
63
+ provider,
64
+ reason,
65
+ observedAt: new Date(observedAt).toISOString(),
66
+ validUntil: new Date(validUntil).toISOString(),
67
+ ...(provenance ? { provenance } : {}),
68
+ },
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Query the shared Pi extension event bus for one operation-specific negative
74
+ * policy. Providers may inhibit or abstain; every other result fails open.
75
+ */
76
+ export async function queryAutomaticSummaryPolicy(
77
+ events,
78
+ session,
79
+ {
80
+ timeoutMs = DEFAULT_AUTOMATIC_SUMMARY_POLICY_TIMEOUT_MS,
81
+ now = () => Date.now(),
82
+ queryId = `rarebit_policy_${randomUUID()}`,
83
+ } = {},
84
+ ) {
85
+ if (!Number.isInteger(timeoutMs) || timeoutMs < 1)
86
+ throw new RangeError("automatic summary policy timeout must be positive");
87
+ const sessionId = nonEmptyString(session?.sessionId);
88
+ const durableAssociation = nonEmptyString(session?.durableAssociation);
89
+ if (!sessionId || !durableAssociation || typeof events?.emit !== "function")
90
+ return {
91
+ decision: "abstain",
92
+ queryStatus: "provider_absent",
93
+ contractVersion: RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT,
94
+ };
95
+
96
+ const issuedAtMillis = now();
97
+ const deadlineMillis = issuedAtMillis + timeoutMs;
98
+ const query = {
99
+ contractVersion: RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT,
100
+ queryId,
101
+ operation: "automatic_summary",
102
+ session: { id: sessionId, durableAssociation },
103
+ issuedAt: new Date(issuedAtMillis).toISOString(),
104
+ deadlineAt: new Date(deadlineMillis).toISOString(),
105
+ issuedAtMillis,
106
+ };
107
+ const received = [];
108
+ let accepting = true;
109
+ const respond = (response) => {
110
+ const receivedAt = now();
111
+ if (!accepting || receivedAt > deadlineMillis) return false;
112
+ received.push(validateResponse(response, query, receivedAt));
113
+ return true;
114
+ };
115
+
116
+ try {
117
+ events.emit(RAREBIT_AUTOMATIC_SUMMARY_POLICY_EVENT, {
118
+ contractVersion: query.contractVersion,
119
+ queryId: query.queryId,
120
+ operation: query.operation,
121
+ session: query.session,
122
+ issuedAt: query.issuedAt,
123
+ deadlineAt: query.deadlineAt,
124
+ respond,
125
+ });
126
+ } catch {
127
+ accepting = false;
128
+ return {
129
+ decision: "abstain",
130
+ queryStatus: "provider_failure",
131
+ contractVersion: RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT,
132
+ };
133
+ }
134
+
135
+ await new Promise((resolve) => setTimeout(resolve, timeoutMs));
136
+ accepting = false;
137
+ if (received.some((entry) => !entry.ok))
138
+ return {
139
+ decision: "abstain",
140
+ queryStatus: "invalid_response",
141
+ contractVersion: RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT,
142
+ };
143
+ const inhibitions = received
144
+ .map((entry) => entry.response)
145
+ .filter((response) => response.decision === "inhibit");
146
+ if (inhibitions.length > 1)
147
+ return {
148
+ decision: "abstain",
149
+ queryStatus: "conflict",
150
+ contractVersion: RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT,
151
+ };
152
+ if (inhibitions.length === 0)
153
+ return {
154
+ decision: "abstain",
155
+ queryStatus:
156
+ received.length === 0 ? "provider_absent" : "provider_abstained",
157
+ contractVersion: RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT,
158
+ };
159
+ const inhibition = inhibitions[0];
160
+ const completedAt = now();
161
+ if (finiteTime(inhibition.validUntil) <= completedAt)
162
+ return {
163
+ decision: "abstain",
164
+ queryStatus: "stale_response",
165
+ contractVersion: RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT,
166
+ };
167
+ return {
168
+ ...inhibition,
169
+ queryStatus: "inhibited",
170
+ queriedAt: new Date(completedAt).toISOString(),
171
+ };
172
+ }
173
+
174
+ export function automaticSummaryInhibitionIdentity(
175
+ inhibition,
176
+ { now = () => Date.now() } = {},
177
+ ) {
178
+ const provenance = sanitizeOpaqueProvenance(inhibition?.provenance);
179
+ const provider = nonEmptyString(inhibition?.provider);
180
+ const reason = nonEmptyString(inhibition?.reason);
181
+ const queryId = nonEmptyString(inhibition?.queryId);
182
+ const observedAt = finiteTime(inhibition?.observedAt);
183
+ const validUntil = finiteTime(inhibition?.validUntil);
184
+ const queriedAt = finiteTime(inhibition?.queriedAt);
185
+ const checkedAt = now();
186
+ if (
187
+ inhibition?.contractVersion !== RAREBIT_AUTOMATIC_SUMMARY_POLICY_CONTRACT ||
188
+ inhibition?.decision !== "inhibit" ||
189
+ inhibition?.queryStatus !== "inhibited" ||
190
+ !queryId ||
191
+ !provider ||
192
+ !reason ||
193
+ !provenance ||
194
+ observedAt === null ||
195
+ validUntil === null ||
196
+ queriedAt === null ||
197
+ observedAt > queriedAt ||
198
+ queriedAt > checkedAt ||
199
+ validUntil <= queriedAt ||
200
+ validUntil <= checkedAt ||
201
+ validUntil - observedAt > MAX_PROVIDER_VALIDITY_MS
202
+ )
203
+ return null;
204
+ return {
205
+ contractVersion: inhibition.contractVersion,
206
+ provider,
207
+ reason,
208
+ provenance,
209
+ };
210
+ }