@hypercarrier/rarebit 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -7,7 +7,7 @@ must not replace it or claim Task, Project, runtime, or delivery truth.
7
7
  Keep the public surface small. Test CLI behavior, package boundaries, and Pi
8
8
  installation paths. Do not add private-helper mocks, export-count tests,
9
9
  coverage targets, or tautological snapshots. Run `npm ci`, `npm test`, and
10
- `npm run verify:package` before a release candidate.
10
+ `npm run verify:package` before a release.
11
11
 
12
12
  Do not record Session prose, provider credentials, Recall bundles, or private
13
13
  paths in issues, fixtures, logs, or release records. `README.md` owns user
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.2 — 2026-10-15
4
+
5
+ - Add a development-only simulator lane (`npm run test:sim`) that runs real
6
+ Rarebit selection, materialization, Recall, compaction and tree navigation on
7
+ the shared HyperCarrier Pi simulator. It needs the HyperCarrier workspace.
8
+ `sim/` is not in the npm package. The lane found no Rarebit product bug.
9
+ - Move the selection monitor tests into `test/`.
10
+
11
+ ## 0.5.1 — 2026-10-12
12
+
13
+ - Document the release privacy gate as the baseline range scan in `RUNBOOK.md`
14
+ and `AGENTS.md`. A change outside the npm `files` list ships on `main`
15
+ without a version.
16
+
3
17
  ## 0.5.0 — 2026-10-07
4
18
 
5
19
  - Add `/rarebit btw [--rarebits] [--readonly] [question]`. It opens a
package/README.md CHANGED
@@ -400,6 +400,16 @@ Use [GitHub Issues](https://github.com/deephbz/rarebit/issues) for normal
400
400
  support. Include no Session prose, credentials, or Recall files in public
401
401
  reports.
402
402
 
403
+ ## Development verification
404
+
405
+ `npm ci && npm test` runs standalone unit and selection checks. The private
406
+ R&D simulator lane uses HC's shared `@hypercarrier/pi-sim`; it does not enter
407
+ Rarebit's root install or published artifact. Run `npm run test:sim` in the HC
408
+ workspace or set `HC_PI_SIM_PATH` to an installed simulator package root.
409
+ Run `npm run test:sim:campaign` for the longer seeded campaign.
410
+ [Simulator scope, setup, properties, replay, and results](sim/README.md) remain
411
+ repository-only development artifacts. No real provider credentials are needed.
412
+
403
413
  ## Release and source history
404
414
 
405
415
  Rarebit is released from an immutable version tag by
package/RUNBOOK.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # Rarebit runbook
2
2
 
3
3
  To release, merge the version bump and its [CHANGELOG.md](CHANGELOG.md) entry
4
- to `main`, run `git-privacy-scan --ref HEAD history`, then push tag
5
- `v<version>`. The tag push runs
4
+ to `main`, run
5
+ `git-privacy-scan --ref HEAD --base "$(git config privacy.baseline)" range`,
6
+ then push tag `v<version>`. Any finding blocks the release; the pre-push hook
7
+ runs the same scan. The tag push runs
6
8
  [`.github/workflows/publish.yml`](.github/workflows/publish.yml). It runs the
7
9
  package gates, publishes one verified packed artifact with npm provenance, and
8
10
  creates the GitHub Release. A prerelease version goes to npm `next`; any other
9
- version goes to `latest`. Publication adds no commit.
11
+ version goes to `latest`. Publication adds no commit. A change outside the npm
12
+ `files` list, such as `claude-code/`, changes no package bytes: push it to
13
+ `main` without a version.
10
14
 
11
15
  Set `rarebit.model` in global Pi settings or in a trusted Project's
12
16
  `.pi/settings.json`. It must be `provider/model` or an object with `provider`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypercarrier/rarebit",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Sparse, provenance-bearing conversational evidence recovery for Pi sessions.",
5
5
  "license": "MIT",
6
6
  "author": "HyperCarrier contributors",
@@ -29,6 +29,9 @@
29
29
  },
30
30
  "scripts": {
31
31
  "test": "node --test test/*.test.mjs",
32
+ "test:sim": "node --test sim/*.test.mjs",
33
+ "test:sim:campaign": "RAREBIT_SIM_RUNS=100 node --test sim/*.test.mjs",
34
+ "test:sim:replay": "node sim/replay.mjs",
32
35
  "test:e2e:tui": "node scripts/e2e-v020-pi.mjs",
33
36
  "test:e2e:summary-cache": "node scripts/e2e-summary-cache.mjs",
34
37
  "test:e2e:recall": "node scripts/e2e-recall-pi0842.mjs",
@@ -55,6 +58,7 @@
55
58
  "@earendil-works/pi-coding-agent": "0.84.2",
56
59
  "@earendil-works/pi-tui": "0.84.2",
57
60
  "ajv": "^6.15.0",
61
+ "fast-check": "^4.10.2",
58
62
  "typescript": "^5.9.3"
59
63
  },
60
64
  "pi": {
@@ -0,0 +1,10 @@
1
+ // Independent observation of the prose-selection contract; no simulator needed.
2
+ import assert from 'node:assert/strict';
3
+ export function expectedProse(branch) {
4
+ return branch.filter(e => e.type === 'message' && (e.message.role === 'user' || (e.message.role === 'assistant' && ['stop', 'toolUse'].includes(e.message.stopReason))))
5
+ .map(e => ({ id: e.id ?? e.message.id ?? null, text: typeof e.message.content === 'string' ? e.message.content : (e.message.content ?? []).filter(b => b.type === 'text' && typeof b.text === 'string').map(b => b.text).join('\n'), readable: typeof e.message.content === 'string' || (e.message.content ?? []).some(b => b.type === 'text' && typeof b.text === 'string') }))
6
+ .filter(e => e.readable).map(({ id, text }) => ({ id, text }));
7
+ }
8
+ export function checkSelection(selection, branch) {
9
+ assert.deepEqual(selection.occurrences.map(o => ({ id: o.sourceEntryId, text: o.text })), expectedProse(branch), 'R1 selection contract');
10
+ }
@@ -0,0 +1,31 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import fc from 'fast-check';
4
+ import { selectRarebits } from '../src/rarebit-core.mjs';
5
+ import { parseNativeSession, resolveActiveBranch } from '../src/rarebit-session.mjs';
6
+ import { checkSelection } from './helpers/selection-monitor.mjs';
7
+
8
+ test('R1 exhaustive role/outcome/content pairs; R8 old and current native formats', () => {
9
+ const entries = [];
10
+ for (const role of ['user', 'assistant', 'toolResult']) for (const stopReason of ['stop', 'toolUse', 'error', 'aborted', 'length', undefined]) for (const content of ['prose', [{ type: 'text', text: 'prose' }, { type: 'thinking', thinking: 'private reasoning' }], [{ type: 'toolCall', id: 'synthetic', name: 'read', arguments: {} }], []]) entries.push({ type: 'message', message: { role, stopReason, content } });
11
+ let count = 0;
12
+ for (const a of entries) for (const b of entries) {
13
+ const branch = [a, b].map((e, i) => ({ ...e, id: `e${i}`, parentId: i ? 'e0' : null }));
14
+ checkSelection(selectRarebits(branch), branch); count++;
15
+ }
16
+ assert.equal(count, 5184);
17
+ for (const version of [1, 2, 3]) {
18
+ const branch = entries.map((e, i) => ({ ...e, id: `e${i}`, parentId: i ? `e${i-1}` : null, legacyExtra: 'retained' }));
19
+ const original = JSON.stringify([{ type: 'session', id: 'synthetic-old', version }, ...branch]);
20
+ const parsed = parseNativeSession(JSON.parse(original).map(e => JSON.stringify(e)).join('\n'));
21
+ checkSelection(selectRarebits(resolveActiveBranch(parsed)), branch);
22
+ assert.equal(JSON.stringify([parsed.header, ...parsed.entries]), original, 'R8 no read-time migration');
23
+ }
24
+ });
25
+
26
+ test('R1/R8 fast-check mixed native evidence with shrinking', () => {
27
+ fc.assert(fc.property(fc.array(fc.record({ role: fc.constantFrom('user', 'assistant', 'toolResult'), stopReason: fc.constantFrom('stop', 'toolUse', 'error', 'aborted'), text: fc.string({ maxLength: 100 }) }), { maxLength: 30 }), records => {
28
+ const branch = records.map((r, i) => ({ type: 'message', id: `e${i}`, parentId: i ? `e${i-1}` : null, message: { role: r.role, stopReason: r.stopReason, content: [{ type: 'text', text: r.text }] } }));
29
+ checkSelection(selectRarebits(branch), branch);
30
+ }), { seed: 20261015, numRuns: 100 });
31
+ });