soulbridge 0.0.100 → 0.0.101
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/dist/packages/core/src/config/status.d.ts +15 -15
- package/dist/packages/core/src/config/status.js +15 -15
- package/dist/packages/core/src/index.js +1 -1
- package/dist/packages/core/src/roles.d.ts +8 -9
- package/dist/packages/core/src/roles.js +4 -10
- package/dist/packages/core/src/sqlite.d.ts +2 -1
- package/dist/packages/core/src/sqlite.js +12 -6
- package/package.json +1 -1
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Fact lifecycle vocabulary — declared once, imported everywhere.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* These four replaced none/open/kept/broken/superseded. The older set mixed "what kind of
|
|
5
|
+
* fact" with "how far it has come", so every reader had to remember which values counted as
|
|
6
|
+
* live. The four below are the only ones written now: `raw` is the exchange itself,
|
|
7
|
+
* `candidate` is held but not injected, `active` is in use, `retracted` is kept for the
|
|
8
|
+
* record and read by nothing.
|
|
7
9
|
*
|
|
8
|
-
* Values match the column defaults in sqlite.ts; changing one is a schema migration,
|
|
9
|
-
*
|
|
10
|
+
* Values match the column defaults in sqlite.ts; changing one is a schema migration, not a
|
|
11
|
+
* rename.
|
|
10
12
|
*/
|
|
11
13
|
export declare const FACT_STATUS: {
|
|
12
|
-
/**
|
|
13
|
-
readonly
|
|
14
|
-
/**
|
|
15
|
-
readonly
|
|
16
|
-
/**
|
|
17
|
-
readonly
|
|
18
|
-
/**
|
|
19
|
-
readonly
|
|
20
|
-
/** Replaced by another fact; kept for the record, never injected. */
|
|
21
|
-
readonly superseded: 'superseded';
|
|
14
|
+
/** The exchange itself; not a distilled fact. */
|
|
15
|
+
readonly raw: 'raw';
|
|
16
|
+
/** Held, not injected: unverified inference or an unconfirmed rule. */
|
|
17
|
+
readonly candidate: 'candidate';
|
|
18
|
+
/** In use: retrieval, rules, profile, evidence. */
|
|
19
|
+
readonly active: 'active';
|
|
20
|
+
/** Replaced or withdrawn; kept for the audit trail, injected nowhere. */
|
|
21
|
+
readonly retracted: 'retracted';
|
|
22
22
|
};
|
|
23
23
|
export type FactStatus = (typeof FACT_STATUS)[keyof typeof FACT_STATUS];
|
|
24
24
|
/** Where a fact came from, in the trust sense (not a type). */
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Fact lifecycle vocabulary — declared once, imported everywhere.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* These four replaced none/open/kept/broken/superseded. The older set mixed "what kind of
|
|
5
|
+
* fact" with "how far it has come", so every reader had to remember which values counted as
|
|
6
|
+
* live. The four below are the only ones written now: `raw` is the exchange itself,
|
|
7
|
+
* `candidate` is held but not injected, `active` is in use, `retracted` is kept for the
|
|
8
|
+
* record and read by nothing.
|
|
7
9
|
*
|
|
8
|
-
* Values match the column defaults in sqlite.ts; changing one is a schema migration,
|
|
9
|
-
*
|
|
10
|
+
* Values match the column defaults in sqlite.ts; changing one is a schema migration, not a
|
|
11
|
+
* rename.
|
|
10
12
|
*/
|
|
11
13
|
export const FACT_STATUS = {
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
/** Replaced by another fact; kept for the record, never injected. */
|
|
21
|
-
superseded: 'superseded',
|
|
14
|
+
/** The exchange itself; not a distilled fact. */
|
|
15
|
+
raw: 'raw',
|
|
16
|
+
/** Held, not injected: unverified inference or an unconfirmed rule. */
|
|
17
|
+
candidate: 'candidate',
|
|
18
|
+
/** In use: retrieval, rules, profile, evidence. */
|
|
19
|
+
active: 'active',
|
|
20
|
+
/** Replaced or withdrawn; kept for the audit trail, injected nowhere. */
|
|
21
|
+
retracted: 'retracted',
|
|
22
22
|
};
|
|
23
23
|
/** Where a fact came from, in the trust sense (not a type). */
|
|
24
24
|
export const FACT_SOURCE = {
|
|
@@ -557,7 +557,7 @@ export class Soul {
|
|
|
557
557
|
// lost, and "the fact changed" is never claimed without a real predecessor.
|
|
558
558
|
const target = operation.targetId ? this.store.fact(operation.targetId) : null;
|
|
559
559
|
const sameScope = target && target.soulId === this.soulId && target.userId === this.userId;
|
|
560
|
-
if (target && sameScope && target
|
|
560
|
+
if (target && sameScope && isActive(target)) {
|
|
561
561
|
this.store.supersedeFact(target.id, written.id);
|
|
562
562
|
}
|
|
563
563
|
else {
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The two decisions every reader used to make for itself, in one place.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - `status` moves from none/superseded to raw/candidate/active/retracted, but old rows keep
|
|
8
|
-
* their old values until the migration runs.
|
|
4
|
+
* `role` says what a fact is for; `status` says how far it has come. Both used to be read by
|
|
5
|
+
* matching Chinese type labels and status strings at each call site, which is how one filter
|
|
6
|
+
* ended up admitting retired facts after a rename.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* This is the contract step: the dual-vocabulary fallback is gone. The migration normalises
|
|
9
|
+
* old rows (none/open/kept → active, broken/superseded → retracted) and the writer always
|
|
10
|
+
* stores a role, so a reader sees exactly one vocabulary.
|
|
13
11
|
*/
|
|
14
12
|
import type { Fact } from './types.ts';
|
|
15
13
|
import type { FactRole } from './types.ts';
|
|
16
|
-
|
|
14
|
+
/** Rows written before the role column existed cannot appear after the migration. */
|
|
15
|
+
export declare function roleOf(fact: Pick<Fact, 'role'>): FactRole;
|
|
17
16
|
export declare function isActive(fact: Pick<Fact, 'status'>): boolean;
|
|
18
17
|
export declare function isRetracted(fact: Pick<Fact, 'status'>): boolean;
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import { FACT_STATE_MIGRATION, LEGACY_ROLE_BY_TYPE } from './config/domains.js';
|
|
2
1
|
import { FACT_STATUS } from './config/status.js';
|
|
3
|
-
|
|
4
|
-
/** Old and new status values that mean "this is in use". */
|
|
5
|
-
const ACTIVE_STATES = new Set(['active', 'none', 'kept', 'open']);
|
|
2
|
+
/** Rows written before the role column existed cannot appear after the migration. */
|
|
6
3
|
export function roleOf(fact) {
|
|
7
|
-
|
|
8
|
-
return fact.role;
|
|
9
|
-
return LEGACY_ROLES[fact.typeName ?? ''] ?? 'observation';
|
|
4
|
+
return fact.role ?? 'observation';
|
|
10
5
|
}
|
|
11
6
|
export function isActive(fact) {
|
|
12
|
-
return
|
|
7
|
+
return String(fact.status) === FACT_STATUS.active;
|
|
13
8
|
}
|
|
14
9
|
export function isRetracted(fact) {
|
|
15
|
-
|
|
16
|
-
return mapped === 'retracted' || String(fact.status) === FACT_STATUS.superseded;
|
|
10
|
+
return String(fact.status) === FACT_STATUS.retracted;
|
|
17
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DatabaseSync } from 'node:sqlite';
|
|
2
2
|
import type { SoulStore } from './store.ts';
|
|
3
|
-
export declare const SCHEMA_VERSION =
|
|
3
|
+
export declare const SCHEMA_VERSION = 10;
|
|
4
4
|
export declare const AFFECT_RETENTION_MS: number;
|
|
5
5
|
export declare class DbNewerThanBinaryError extends Error {
|
|
6
6
|
readonly code = "DB_NEWER_THAN_BINARY";
|
|
@@ -13,6 +13,7 @@ export declare class DbNewerThanBinaryError extends Error {
|
|
|
13
13
|
* old table stays as a read-only legacy copy.
|
|
14
14
|
*/
|
|
15
15
|
/** v6 → v7: turn threads (a topic's turns need not be adjacent) plus turns.thread_id. */
|
|
16
|
+
export declare function upgradeToV10(db: DatabaseSync): void;
|
|
16
17
|
export declare function upgradeToV9(db: DatabaseSync): void;
|
|
17
18
|
export declare function upgradeToV8(db: DatabaseSync): void;
|
|
18
19
|
export declare function upgradeToV7(db: DatabaseSync): void;
|
|
@@ -12,7 +12,7 @@ import { DEFAULT_EMOTION } from './types.js';
|
|
|
12
12
|
import { FACT_STATUS, MEMORY_STATUS } from './config/status.js';
|
|
13
13
|
import { LEGACY_ROLE_BY_TYPE } from './config/domains.js';
|
|
14
14
|
import { bm25, buildCorpusStats, tokenize } from './scoring.js';
|
|
15
|
-
export const SCHEMA_VERSION =
|
|
15
|
+
export const SCHEMA_VERSION = 10;
|
|
16
16
|
/** How many recent pairs are considered before scoring. Bounded so recall stays O(candidates). */
|
|
17
17
|
const RECALL_CANDIDATES = 500;
|
|
18
18
|
export const AFFECT_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
@@ -175,7 +175,7 @@ CREATE TABLE IF NOT EXISTS facts (
|
|
|
175
175
|
at_end INTEGER,
|
|
176
176
|
at_precision TEXT NOT NULL DEFAULT 'unknown',
|
|
177
177
|
place_id TEXT,
|
|
178
|
-
status TEXT NOT NULL DEFAULT '
|
|
178
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
179
179
|
confidence REAL NOT NULL DEFAULT 1,
|
|
180
180
|
source TEXT NOT NULL DEFAULT 'experienced',
|
|
181
181
|
source_turn_id TEXT,
|
|
@@ -299,6 +299,12 @@ function upgradeToV3(db) {
|
|
|
299
299
|
* old table stays as a read-only legacy copy.
|
|
300
300
|
*/
|
|
301
301
|
/** v6 → v7: turn threads (a topic's turns need not be adjacent) plus turns.thread_id. */
|
|
302
|
+
export function upgradeToV10(db) {
|
|
303
|
+
// The four-state vocabulary (config/status.ts). Everything written under the old names
|
|
304
|
+
// becomes one of the two states the code now reads; after this the fallbacks are gone.
|
|
305
|
+
db.exec("UPDATE facts SET status = 'active' WHERE status IN ('none','open','kept')");
|
|
306
|
+
db.exec("UPDATE facts SET status = 'retracted' WHERE status IN ('broken','superseded')");
|
|
307
|
+
}
|
|
302
308
|
export function upgradeToV9(db) {
|
|
303
309
|
// Time became locatability (ADR 0032): a fact may be known to exist without a
|
|
304
310
|
// date, and that is a value — unknown — not a reason to discard it.
|
|
@@ -442,8 +448,8 @@ export function openSqlite(file) {
|
|
|
442
448
|
upgradeToV7(db);
|
|
443
449
|
if (version < 8)
|
|
444
450
|
upgradeToV8(db);
|
|
445
|
-
if (version <
|
|
446
|
-
|
|
451
|
+
if (version < 10)
|
|
452
|
+
upgradeToV10(db);
|
|
447
453
|
// v6 adds tables only; SCHEMA creates them on every open, nothing to copy.
|
|
448
454
|
setVersion(db, SCHEMA_VERSION);
|
|
449
455
|
db.exec('COMMIT');
|
|
@@ -827,7 +833,7 @@ export function openSqlite(file) {
|
|
|
827
833
|
},
|
|
828
834
|
supersedeFact(oldId, newId) {
|
|
829
835
|
withRetry(() => db
|
|
830
|
-
.prepare(`UPDATE facts SET status = '${FACT_STATUS.
|
|
836
|
+
.prepare(`UPDATE facts SET status = '${FACT_STATUS.retracted}', superseded_by = ? WHERE id = ?`)
|
|
831
837
|
.run(newId, oldId));
|
|
832
838
|
},
|
|
833
839
|
/* ---------------- gaps ---------------- */
|
|
@@ -1083,7 +1089,7 @@ export function openSqlite(file) {
|
|
|
1083
1089
|
.prepare(`SELECT DISTINCT f.* FROM facts f
|
|
1084
1090
|
JOIN fact_slots s ON s.fact_id = f.id AND s.value_type = 'entity'
|
|
1085
1091
|
JOIN entities e ON e.id = s.entity_id
|
|
1086
|
-
WHERE f.soul_id = ? AND f.user_id = ? AND f.status
|
|
1092
|
+
WHERE f.soul_id = ? AND f.user_id = ? AND f.status = '${FACT_STATUS.active}'
|
|
1087
1093
|
AND (e.name = ? OR e.aliases LIKE ?)
|
|
1088
1094
|
AND (? IS NULL OR f.statement LIKE ? OR COALESCE(f.type_name, '') LIKE ?)
|
|
1089
1095
|
ORDER BY COALESCE(f.at, f.created_at) DESC
|