@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,172 @@
1
+ import assert from "node:assert/strict";
2
+ import Ajv from "ajv";
3
+ import { readFileSync } from "node:fs";
4
+ import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+ import test from "node:test";
8
+
9
+ import {
10
+ normalizeRarebitSummarySynthesis,
11
+ selectRarebits,
12
+ } from "../src/rarebit-core.mjs";
13
+ import { processRarebitSummary } from "../src/rarebit-service.mjs";
14
+
15
+ const summary =
16
+ "The agent inspected the evidence and needs the owner to decide.";
17
+ function branch() {
18
+ return [
19
+ {
20
+ type: "message",
21
+ id: "owner",
22
+ message: { role: "user", content: "Inspect the evidence." },
23
+ },
24
+ ];
25
+ }
26
+
27
+ test("v4 producer records free-form status/reason and owner-request provenance", async () => {
28
+ const schema = JSON.parse(
29
+ readFileSync(
30
+ new URL("../schemas/rarebit.schema.json", import.meta.url),
31
+ "utf8",
32
+ ),
33
+ );
34
+ assert.ok(schema.definitions.summary.properties.sessionStatus);
35
+ assert.ok(schema.definitions.summary.properties.statusReason);
36
+ const root = await mkdtemp(join(tmpdir(), "rarebit-summary-v4-"));
37
+ const sessionRoot = join(root, "sessions");
38
+ const rarebitRoot = join(root, "rarebit");
39
+ const sessionDir = join(sessionRoot, "owner-request");
40
+ const sessionFile = join(sessionDir, "session.jsonl");
41
+ await mkdir(sessionDir, { recursive: true });
42
+ await writeFile(sessionFile, "{}\n");
43
+ const result = await processRarebitSummary(
44
+ {
45
+ sessionManager: {
46
+ getHeader: () => ({ id: "owner-request" }),
47
+ getSessionFile: () => sessionFile,
48
+ getBranch: branch,
49
+ },
50
+ },
51
+ {
52
+ sessionRoot,
53
+ rarebitRoot,
54
+ summaryPolicy: { minTotalLength: 0, maxRarebitRatio: 1 },
55
+ model: { provider: "test", id: "v4" },
56
+ lifecycleBoundary: "owner_request",
57
+ modelClient: {
58
+ complete: async () => ({
59
+ text: JSON.stringify({
60
+ summary,
61
+ sessionStatus: "user_requested",
62
+ statusReason: "owner_request_recorded",
63
+ }),
64
+ }),
65
+ },
66
+ },
67
+ );
68
+ assert.equal(result.record.status, "ok");
69
+ assert.equal(result.record.schemaVersion, 4);
70
+ assert.equal(result.record.sessionStatus, "user_requested");
71
+ assert.equal(result.record.statusReason, "owner_request_recorded");
72
+ assert.equal(result.record.lifecycleBoundary, "owner_request");
73
+ const persisted = (await readFile(result.record.path, "utf8"))
74
+ .trim()
75
+ .split("\n")
76
+ .map(JSON.parse)
77
+ .find((record) => record.type === "rarebit_summary");
78
+ assert.equal(persisted.sessionStatus, "user_requested");
79
+ const validate = new Ajv({ allErrors: true }).compile(schema);
80
+ assert.equal(validate(persisted), true, JSON.stringify(validate.errors));
81
+ const unsupportedReceipt = { ...persisted, schemaVersion: 999 };
82
+ assert.equal(validate(unsupportedReceipt), false);
83
+ const missingV4Boundary = { ...persisted };
84
+ delete missingV4Boundary.lifecycleBoundary;
85
+ assert.equal(validate(missingV4Boundary), false);
86
+ const illegalNeedReason = {
87
+ ...persisted,
88
+ lifecycleBoundary: "agent_settled",
89
+ sessionStatus: "needs_attention",
90
+ statusReason: "all_requests_accomplished",
91
+ };
92
+ assert.equal(validate(illegalNeedReason), false);
93
+ const illegalOwnerBoundary = {
94
+ ...persisted,
95
+ sessionStatus: "finished",
96
+ statusReason: "all_requests_accomplished",
97
+ };
98
+ assert.equal(validate(illegalOwnerBoundary), false);
99
+ });
100
+
101
+ test("v4 synthesis validates legal status/reason combinations without rigid sections", () => {
102
+ assert.deepEqual(
103
+ normalizeRarebitSummarySynthesis(
104
+ JSON.stringify({
105
+ summary: "Any free-form prose\nwith controls\u0000 removed",
106
+ sessionStatus: "needs_attention",
107
+ statusReason: "unfinished",
108
+ }),
109
+ ),
110
+ {
111
+ summary: "Any free-form prose with controls removed",
112
+ sessionStatus: "needs_attention",
113
+ statusReason: "unfinished",
114
+ },
115
+ );
116
+ assert.throws(
117
+ () =>
118
+ normalizeRarebitSummarySynthesis(
119
+ JSON.stringify({
120
+ summary,
121
+ sessionStatus: "finished",
122
+ statusReason: "unfinished",
123
+ }),
124
+ ),
125
+ /illegal statusReason/,
126
+ );
127
+ assert.throws(
128
+ () => normalizeRarebitSummarySynthesis(JSON.stringify({ summary })),
129
+ /sessionStatus/,
130
+ );
131
+ });
132
+
133
+ test("settled prompt makes completion and unfinished judgments only from visible Rarebit prose", async () => {
134
+ const selection = selectRarebits(branch());
135
+ const { composeRarebitSummaryPrompt } =
136
+ await import("../src/rarebit-core.mjs");
137
+ const prompt = composeRarebitSummaryPrompt(selection, {
138
+ lifecycleBoundary: "agent_settled",
139
+ });
140
+ assert.match(prompt, /every active, non-superseded request/i);
141
+ assert.match(
142
+ prompt,
143
+ /cancellation, replacement, supersession, and later resolution/i,
144
+ );
145
+ assert.match(prompt, /Tool-call inputs, tool results.*deliberately absent/i);
146
+ assert.match(
147
+ prompt,
148
+ /Absence of a tool transcript.*never.*work was not performed/i,
149
+ );
150
+ assert.match(prompt, /concise 'done'.*appear accomplished/i);
151
+ assert.match(prompt, /I will run tests next/i);
152
+ assert.match(prompt, /unfinished.*explicit\/positive selected evidence/i);
153
+ assert.match(prompt, /finished\/all_requests_accomplished/i);
154
+ assert.match(
155
+ prompt,
156
+ /finished is only the scoped appearance-based Session-requests assessment/i,
157
+ );
158
+ assert.doesNotMatch(prompt, /"finished\|needs_attention"/);
159
+ const ownerRequestPrompt = composeRarebitSummaryPrompt(selection, {
160
+ lifecycleBoundary: "owner_request",
161
+ });
162
+ assert.match(
163
+ ownerRequestPrompt,
164
+ /newly persisted user message/i,
165
+ );
166
+ assert.match(ownerRequestPrompt, /change it makes to active requests/i);
167
+ assert.match(ownerRequestPrompt, /Tool-call inputs, tool results/i);
168
+ assert.match(
169
+ ownerRequestPrompt,
170
+ /Always use that status pair at this boundary/i,
171
+ );
172
+ });
@@ -0,0 +1,13 @@
1
+ import type {
2
+ RarebitSummaryReceiptV4,
3
+ RarebitTitleReceiptV4,
4
+ readRarebitHistory,
5
+ } from "../src/types.d.ts";
6
+
7
+ type History = Awaited<ReturnType<typeof readRarebitHistory>>;
8
+ type Receipt = History["records"][number]["record"];
9
+
10
+ const assertExactUnion = (
11
+ value: Receipt,
12
+ ): RarebitSummaryReceiptV4 | RarebitTitleReceiptV4 => value;
13
+ void assertExactUnion;