Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
2dd3a74
feat(core): add judgment contract types, parsers and intention transi…
thisisjun786 Sep 11, 2026
4335e94
feat(core): export parseObjectiveProfileRef for judgment store re-par…
thisisjun786 Sep 11, 2026
17db2c1
feat(core): add PersonaSchema v1 contract and LifeDefinition derivati…
thisisjun786 Sep 11, 2026
53a0be1
feat(core): add ContextReadProjection separating working and instruct…
thisisjun786 Sep 11, 2026
4c17e1d
feat(core): add personal.v1 option catalog and arbitration policy rev…
thisisjun786 Sep 11, 2026
71dcf58
fix(core): preserve catalog rejection precedence and clear literal-ke…
thisisjun786 Sep 11, 2026
33d888b
style(core): reformat judgment-validation.ts after parseObjectiveProf…
thisisjun786 Sep 11, 2026
fdcb794
feat(core): add JudgmentStore standalone SQLite persistence for round…
thisisjun786 Sep 11, 2026
d6ddd33
refactor(core): share JSON canonicalizer between judgment digest and …
thisisjun786 Sep 11, 2026
8c4eb98
test(core): prove shared judgment canonicalizer through public barrel…
thisisjun786 Sep 11, 2026
02cb0ef
test(core): add end-to-end personal.v1 judgment round fixture (F1 int…
thisisjun786 Sep 12, 2026
7e9bffc
test(core): assert judgment round reload against original in-memory r…
thisisjun786 Sep 12, 2026
b028518
test(core): import behaviorFingerprint through the agents barrel in p…
thisisjun786 Sep 12, 2026
e597594
fix(core): harden judgment transitions, policy and store consistency
thisisjun786 Sep 12, 2026
8cf0198
test(core): prove judgment canonical JSON bounds through the agents b…
thisisjun786 Sep 12, 2026
c37851c
fix(core): preserve persona projection allowlists
thisisjun786 Sep 12, 2026
8cc88f6
fix(core): validate restored context projections
thisisjun786 Sep 12, 2026
4512d67
fix(core): bind judgment actions and frozen provenance
thisisjun786 Sep 12, 2026
67bf83b
test(runtime): finalize SQLite state at cold restart
thisisjun786 Sep 12, 2026
2dabeda
test(runtime): isolate the LIFE archive capacity boundary
thisisjun786 Sep 12, 2026
f8b48fa
fix(core): enforce the immutable personal policy declaration
thisisjun786 Sep 12, 2026
6ea9cec
fix(core): apply context ID bounds to instruction references
thisisjun786 Sep 12, 2026
6175e8a
fix(core): verify persisted judgment digests on retrieval
thisisjun786 Sep 12, 2026
f443122
fix(core): preserve LIFE persona ownership restrictions
thisisjun786 Sep 12, 2026
e5dcaaa
fix(core): bound canonical option keys for valid targets
thisisjun786 Sep 12, 2026
a8c9340
fix(core): honor judgment source ownership contracts
thisisjun786 Sep 12, 2026
d9cadf7
fix(core): bind candidates and concessions to the round
thisisjun786 Sep 12, 2026
1370e90
test(core): isolate stable orphan quota adoption setup
thisisjun786 Sep 12, 2026
7bff0ae
fix(core): validate identity policy before persona derivation
thisisjun786 Sep 12, 2026
3b769eb
fix(core): preserve abstention and neural failure semantics
thisisjun786 Sep 12, 2026
49b2dbb
fix(core): audit judgment ledger before scoped operations
thisisjun786 Sep 12, 2026
d17c33e
fix(core): validate previous context projections before reuse
thisisjun786 Sep 13, 2026
21cd1aa
fix(core): identify protected commitments in judgment evidence
thisisjun786 Sep 13, 2026
9c565b3
fix(core): ground commitment exemptions and judgment inputs
thisisjun786 Sep 13, 2026
66f9c84
fix(core): replay judgment policy from frozen candidate inputs
thisisjun786 Sep 13, 2026
dfadcea
test(runtime): finalize SQLite state before binding restart
thisisjun786 Sep 13, 2026
46b4b77
fix(core): require canonical intention timestamps
thisisjun786 Sep 13, 2026
7eac3fe
fix(core): verify arbitration evidence and currentness
thisisjun786 Sep 13, 2026
ebd7af9
fix(core): persist candidate-free dialogue judgments
thisisjun786 Sep 13, 2026
5484813
fix(core): validate source intentions before transitions
thisisjun786 Sep 13, 2026
fb15519
fix(core): close dialogue and snapshot boundary gaps
thisisjun786 Sep 13, 2026
ee47070
fix(core): enforce intention chronology and raw argument bounds
thisisjun786 Sep 13, 2026
be29476
test(runtime): isolate persona restart resources
thisisjun786 Sep 13, 2026
cf3a46e
fix(core): reject cross-module objective aliases
thisisjun786 Sep 13, 2026
fdce947
fix(core): fence unverified user commitment cancellation
thisisjun786 Sep 13, 2026
0785eda
fix(core): prevent objective reactivation from reviving stale rounds
thisisjun786 Sep 13, 2026
ff241e6
fix(core): bind dialogue digests to frozen source provenance
thisisjun786 Sep 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions packages/lina-core/src/agents/behavior-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,20 @@ export interface BehaviorPersistence {
): CurrentBehaviorProjection;
status(agentId: string): BehaviorJob[];
}

export const DIMENSION_SOURCES = ["reflection", "neural"] as const;
export type DimensionSource = (typeof DIMENSION_SOURCES)[number];
export type PersonaDimensionRef = {
schemaRevision: number;
dimensionId: string;
source: DimensionSource;
};
/** F2 fills this; F1 declares the shape only. */
export type NeuralProjectionRef = {
schemaVersion: 1;
agentId: string;
scopeId: string;
schemaRevision: number;
observationRef: string;
projectionDigest: string;
};
59 changes: 59 additions & 0 deletions packages/lina-core/src/agents/index.ts
Comment thread
thisisjun786 marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,62 @@ export {
parseVisualReference,
visualIdentityDigest,
} from "./visual-validation.ts";

// Judgment contracts.

export * from "./judgment.ts";
export {
assessmentInputDigest,
INTENTION_TRANSITIONS,
intentionDigest,
judgmentDigest,
parseAssessment,
parseAssessmentSet,
parseIntentionRecord,
parseIntentionTransition,
parseJudgmentSnapshotRef,
parseObjectiveProfile,
parseObjectiveProfileRef,
parseOptionAssessment,
parseResolutionRecord,
parseSelectionSpec,
snapshotDigest,
transitionIntention,
} from "./judgment-validation.ts";

// Persona schema contracts.

export type {
DimensionSource,
NeuralProjectionRef,
PersonaDimensionRef,
} from "./behavior-types.ts";
export { DIMENSION_SOURCES } from "./behavior-types.ts";
export type {
PersonaDimension,
PersonaDimensionKind,
PersonaSchema,
} from "./persona-schema.ts";
export {
parsePersonaSchema,
personaSchemaDigest,
personaSchemaFromLifeDefinition,
} from "./persona-schema.ts";

// Personal catalog and arbitration policy.

export * from "./judgment-catalog.ts";
export * from "./judgment-policy.ts";

// Judgment persistence.

export { JUDGMENT_SCHEMA_VERSION } from "./judgment-schema.ts";
export { JudgmentStore } from "./judgment-store.ts";

// Behavior identity (pre-existing pure function; exposed so persona contract
// tests can pin the BehaviorJobInput fingerprint through the public barrel).

export { behaviorFingerprint } from "./behavior-validation.ts";

export * from "./judgment-candidates.ts";
export * from "./judgment-dialogue.ts";
192 changes: 192 additions & 0 deletions packages/lina-core/src/agents/judgment-candidates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import { INTENTION_STATUSES, type IntentionStatus } from "./judgment.ts";
import {
type CanonicalOption,
parseCanonicalOption,
} from "./judgment-catalog.ts";
import type { HostEligibility } from "./judgment-policy.ts";
import { judgmentDigest } from "./judgment-validation.ts";
import { boundedId, boundedText } from "./validation.ts";

/** Closed Host inputs, independent of assessment arrival order and session lifetime. */
export type CandidateSet = {
schemaVersion: 1;
roundId: string;
snapshotDigest: string;
options: CanonicalOption[];
eligibility: HostEligibility;
intentionRefs: Array<{
intentionId: string;
revision: number;
status: IntentionStatus;
digest: string;
}>;
candidateDigest: string;
};

function fields(
value: unknown,
keys: string[],
label: string,
): Record<string, unknown> {
if (
value === null ||
typeof value !== "object" ||
Array.isArray(value) ||
Object.getPrototypeOf(value) !== Object.prototype
)
throw Error(`invalid ${label}`);
const row = value as Record<string, unknown>;
for (const key of Object.keys(row))
if (!keys.includes(key)) throw Error(`unknown ${label} field ${key}`);
for (const key of keys)
if (!Object.hasOwn(row, key)) throw Error(`missing ${label} field ${key}`);
return row;
}
function list<T>(value: unknown, parse: (value: unknown) => T): T[] {
if (!Array.isArray(value) || value.length > 256)
throw Error("invalid candidate list");
return Array.from(value, parse);
}
function unique<T>(items: T[], key: (item: T) => string): T[] {
if (new Set(items.map(key)).size !== items.length)
throw Error("duplicate candidate key");
return items;
}
function sorted<T>(items: T[], key: (item: T) => string): T[] {
return unique(items, key).sort((a, b) =>
key(a) < key(b) ? -1 : key(a) > key(b) ? 1 : 0,
);
}

function candidateBody(value: unknown): Omit<CandidateSet, "candidateDigest"> {
const {
schemaVersion,
roundId,
snapshotDigest,
options: rawOptions,
eligibility: rawEligibility,
intentionRefs: rawRefs,
} = fields(
value,
[
"schemaVersion",
"roundId",
"snapshotDigest",
"options",
"eligibility",
"intentionRefs",
],
"candidate set",
);
if (schemaVersion !== 1)
throw Error("Unsupported candidate set schema version");
const options = sorted(
list(rawOptions, parseCanonicalOption),
(o) => o.optionKey,
);
const actor = options[0]?.actor;
if (
options.some(
(o) =>
o.actor.agentId !== actor?.agentId ||
o.actor.scopeId !== actor?.scopeId,
)
)
throw Error("candidate actor mismatch");
const keys = new Set(options.map((o) => o.optionKey));
// Eligibility is an ordered Host list, not a derived/defaulted set. Missing
// rows remain missing and the policy treats them as ineligible.
const eligibility = unique(
list(rawEligibility, (value) => {
const {
optionKey: rawKey,
eligible,
reason,
} = fields(
value,
["optionKey", "eligible", "reason"],
"candidate eligibility",
);
const optionKey = boundedId(rawKey, "option key");
if (!keys.has(optionKey)) throw Error("unknown eligibility option key");
if (typeof eligible !== "boolean")
throw Error("invalid candidate eligibility");
return {
optionKey,
eligible,
reason:
reason === null ? null : boundedText(reason, "eligibility reason"),
};
}),
(r) => r.optionKey,
);
const intentionRefs = sorted(
list(rawRefs, (value) => {
const {
intentionId,
revision,
status: rawStatus,
digest,
} = fields(
value,
["intentionId", "revision", "status", "digest"],
"candidate intention ref",
);
const status = INTENTION_STATUSES.find((s) => s === rawStatus);
if (
typeof revision !== "number" ||
!Number.isSafeInteger(revision) ||
revision < 0 ||
status === undefined
)
throw Error("invalid candidate intention ref");
return {
intentionId: boundedId(intentionId, "intention id"),
revision,
status,
digest: boundedId(digest, "intention digest"),
};
}),
(r) => r.intentionId,
);
return {
schemaVersion: 1,
roundId: boundedId(roundId, "round id"),
snapshotDigest: boundedId(snapshotDigest, "snapshot digest"),
options,
eligibility,
intentionRefs,
};
}

export function parseCandidateSet(value: unknown): CandidateSet {
const row = fields(
value,
[
"schemaVersion",
"roundId",
"snapshotDigest",
"options",
"eligibility",
"intentionRefs",
"candidateDigest",
],
"candidate set",
);
const { candidateDigest, ...rest } = row;
const result = candidateBody(rest);
if (candidateDigest !== judgmentDigest(result))
throw Error("candidate set digest mismatch");
return { ...result, candidateDigest };
}

export function buildCandidateSet(input: {
roundId: string;
snapshotDigest: string;
options: CanonicalOption[];
eligibility: HostEligibility;
intentionRefs: CandidateSet["intentionRefs"];
}): CandidateSet {
const result = candidateBody({ schemaVersion: 1, ...input });
return { ...result, candidateDigest: judgmentDigest(result) };
}
Loading
Loading