Class: MemoryHarness
Defined in: memory-harness.ts:37
Stateful coordinator implementing MemoryHarnessContract (getConfig, init, loadScoped, propose, commit, drainNotes, and handleFileInteractionHook) per §9.1.
Delegates each domain tool and hook workflow to focused src/internal/* phase coordinators while managing configuration discovery (loadMemoryConfig), injectable clock (nowMs), and Distiller runner injection (distillerRunner).
Implements
Constructors
Constructor
new MemoryHarness(options): MemoryHarness;Defined in: memory-harness.ts:55
Creates a new MemoryHarness instance bound to options.workspaceRoot.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | MemoryHarnessOptions | Workspace root, optional config path, Distiller runner, and clock. |
Returns
MemoryHarness
Methods
commit()
commit(input): Promise<{
bucketStatusAfter: | {
bucketId: string;
bucketRecordIds: string[];
currentCount: number;
hardCap: number | null;
maxTotalRecords: number | null;
maxTotalRecordsReached: boolean;
softCap: number | null;
totalRecordsCount: number;
zone: "UNCAPPED" | "UNDER_SOFT_CAP" | "SOFT_CAP_PRESSURE" | "AT_HARD_CAP";
}
| null;
committedRecord: | {
context?: string[];
createdAt: string;
id: string;
repos?: string[];
role: string;
text: string;
type: "rule";
updatedAt?: string;
}
| {
context?: string[];
createdAt: string;
id: string;
repos?: string[];
role: string;
text: string;
type: "lesson";
updatedAt?: string;
}
| {
context?: string[];
createdAt: string;
id: string;
lifecycle: | {
mode: "persistent";
}
| {
mode: "read-count";
remainingReads: number;
}
| {
expiresAt: string;
mode: "hard-expiry";
}
| {
expiresAt: string;
mode: "soft-expiry";
};
repos?: string[];
role: string;
text: string;
type: "note";
updatedAt?: string;
}
| null;
gitCommitted: boolean;
gitPushed: boolean;
mergedKeepRecord: | {
context?: string[];
createdAt: string;
id: string;
repos?: string[];
role: string;
text: string;
type: "rule";
updatedAt?: string;
}
| {
context?: string[];
createdAt: string;
id: string;
repos?: string[];
role: string;
text: string;
type: "lesson";
updatedAt?: string;
}
| {
context?: string[];
createdAt: string;
id: string;
lifecycle: | {
mode: "persistent";
}
| {
mode: "read-count";
remainingReads: number;
}
| {
expiresAt: string;
mode: "hard-expiry";
}
| {
expiresAt: string;
mode: "soft-expiry";
};
repos?: string[];
role: string;
text: string;
type: "note";
updatedAt?: string;
}
| null;
op: "update" | "add" | "remove";
previousRecord: | {
context?: string[];
createdAt: string;
id: string;
repos?: string[];
role: string;
text: string;
type: "rule";
updatedAt?: string;
}
| {
context?: string[];
createdAt: string;
id: string;
repos?: string[];
role: string;
text: string;
type: "lesson";
updatedAt?: string;
}
| {
context?: string[];
createdAt: string;
id: string;
lifecycle: | {
mode: "persistent";
}
| {
mode: "read-count";
remainingReads: number;
}
| {
expiresAt: string;
mode: "hard-expiry";
}
| {
expiresAt: string;
mode: "soft-expiry";
};
repos?: string[];
role: string;
text: string;
type: "note";
updatedAt?: string;
}
| null;
removedIds: string[];
}>;Defined in: memory-harness.ts:142
Executes memory_commit to atomically add, update, or remove a record in memory.jsonl (§6.5).
Parameters
| Parameter | Type | Description |
|---|---|---|
input | | { callerRole: string; capMerge?: { keepId: string; mergedText: string; removeId: string; }; context?: string[]; lifecycle?: | { mode: "persistent"; } | { mode: "read-count"; remainingReads: number; } | { expiresAt: string; mode: "hard-expiry"; } | { expiresAt: string; mode: "soft-expiry"; }; op: "add"; repos?: string[]; role: string; text: string; type: "rule" | "lesson" | "note"; } | { alsoRemoveIds?: string[]; callerRole: string; context?: string[] | null; id: string; lifecycle?: | { mode: "persistent"; } | { mode: "read-count"; remainingReads: number; } | { expiresAt: string; mode: "hard-expiry"; } | { expiresAt: string; mode: "soft-expiry"; }; op: "update"; repos?: string[] | null; role?: string; text: string; } | { callerRole: string; id: string; op: "remove"; reason: | "owner_veto" | "promoted_to_tier1_or_tier2" | "merged_into_wider_record" | "note_settled_or_obsolete"; } | Discriminated 'add' | 'update' | 'remove' mutation payload. |
Returns
Promise<{ bucketStatusAfter: | { bucketId: string; bucketRecordIds: string[]; currentCount: number; hardCap: number | null; maxTotalRecords: number | null; maxTotalRecordsReached: boolean; softCap: number | null; totalRecordsCount: number; zone: "UNCAPPED" | "UNDER_SOFT_CAP" | "SOFT_CAP_PRESSURE" | "AT_HARD_CAP"; } | null; committedRecord: | { context?: string[]; createdAt: string; id: string; repos?: string[]; role: string; text: string; type: "rule"; updatedAt?: string; } | { context?: string[]; createdAt: string; id: string; repos?: string[]; role: string; text: string; type: "lesson"; updatedAt?: string; } | { context?: string[]; createdAt: string; id: string; lifecycle: | { mode: "persistent"; } | { mode: "read-count"; remainingReads: number; } | { expiresAt: string; mode: "hard-expiry"; } | { expiresAt: string; mode: "soft-expiry"; }; repos?: string[]; role: string; text: string; type: "note"; updatedAt?: string; } | null; gitCommitted: boolean; gitPushed: boolean; mergedKeepRecord: | { context?: string[]; createdAt: string; id: string; repos?: string[]; role: string; text: string; type: "rule"; updatedAt?: string; } | { context?: string[]; createdAt: string; id: string; repos?: string[]; role: string; text: string; type: "lesson"; updatedAt?: string; } | { context?: string[]; createdAt: string; id: string; lifecycle: | { mode: "persistent"; } | { mode: "read-count"; remainingReads: number; } | { expiresAt: string; mode: "hard-expiry"; } | { expiresAt: string; mode: "soft-expiry"; }; repos?: string[]; role: string; text: string; type: "note"; updatedAt?: string; } | null; op: "update" | "add" | "remove"; previousRecord: | { context?: string[]; createdAt: string; id: string; repos?: string[]; role: string; text: string; type: "rule"; updatedAt?: string; } | { context?: string[]; createdAt: string; id: string; repos?: string[]; role: string; text: string; type: "lesson"; updatedAt?: string; } | { context?: string[]; createdAt: string; id: string; lifecycle: | { mode: "persistent"; } | { mode: "read-count"; remainingReads: number; } | { expiresAt: string; mode: "hard-expiry"; } | { expiresAt: string; mode: "soft-expiry"; }; repos?: string[]; role: string; text: string; type: "note"; updatedAt?: string; } | null; removedIds: string[]; }>
Committed/previous record snapshots, post-commit bucket status, and Git sync flags.
Throws
With 'CONFIG_NOT_FOUND', 'CONFIG_VALIDATION_FAILED', 'INVALID_ROLE', 'VALIDATION_FAILED', 'LESSON_FORMAT_INVALID', 'CAP_EXCEEDED', 'RECORD_NOT_FOUND', 'RULE_PROTECTION_VIOLATION', or 'GIT_SYNC_FAILED'.
Implementation of
drainNotes()
drainNotes(input): Promise<{
drainedIds: string[];
dryRun: boolean;
gitCommitted: boolean;
gitPushed: boolean;
matchedNotes: object[];
}>;Defined in: memory-harness.ts:162
Executes memory_drain_notes in dry-run preview or destructive bulk-drain mode (§6.6).
Parameters
| Parameter | Type | Description |
|---|---|---|
input | { callerRole: string; dryRun: boolean; ids?: string[]; modes: ("persistent" | "read-count" | "hard-expiry" | "soft-expiry" | "*")[]; paths?: string[]; role?: string; } | Lifecycle mode selectors, optional role/path/ID filters, and dryRun flag. |
input.callerRole? | string | - |
input.dryRun? | boolean | - |
input.ids? | string[] | - |
input.modes? | ("persistent" | "read-count" | "hard-expiry" | "soft-expiry" | "*")[] | - |
input.paths? | string[] | - |
input.role? | string | - |
Returns
Promise<{ drainedIds: string[]; dryRun: boolean; gitCommitted: boolean; gitPushed: boolean; matchedNotes: object[]; }>
Matched note records, drained IDs, and Git sync flags.
Throws
With 'CONFIG_NOT_FOUND', 'CONFIG_VALIDATION_FAILED', 'INVALID_ROLE', 'VALIDATION_FAILED', or 'GIT_SYNC_FAILED'.
Implementation of
MemoryHarnessContract.drainNotes
getConfig()
getConfig(): object;Defined in: memory-harness.ts:69
Returns the loaded and validated MemoryConfig for this workspace (§2.1, §9.1).
Returns
object
Validated unified memory configuration object.
Throws
With 'CONFIG_NOT_FOUND' or 'CONFIG_VALIDATION_FAILED'.
Implementation of
MemoryHarnessContract.getConfig
handleFileInteractionHook()
handleFileInteractionHook(input): Promise<{
compactionEpochId: string;
formattedContext: string | null;
injected: boolean;
lessons: object[];
notes: object[];
rules: object[];
}>;Defined in: memory-harness.ts:181
Evaluates a file or directory tool interaction and returns unseen scoped memories for the active compaction epoch (§7.1–§7.2).
Parameters
| Parameter | Type | Description |
|---|---|---|
input | { role?: string; sessionId: string; touchedPaths: string[]; transcriptPath?: string; } | Session ID, touched paths/globs, and optional role and transcript path. |
input.role? | string | - |
input.sessionId? | string | - |
input.touchedPaths? | string[] | - |
input.transcriptPath? | string | - |
Returns
Promise<{ compactionEpochId: string; formattedContext: string | null; injected: boolean; lessons: object[]; notes: object[]; rules: object[]; }>
Injection status, compaction epoch ID, formatted context, and newly injected records.
Throws
With 'CONFIG_NOT_FOUND', 'CONFIG_VALIDATION_FAILED', 'INVALID_ROLE', 'VALIDATION_FAILED', or 'GIT_SYNC_FAILED'.
Implementation of
MemoryHarnessContract.handleFileInteractionHook
init()
init(input): Promise<{
lessons: object[];
notes: object[];
protocol: string;
repoId: string;
role: string;
rules: object[];
}>;Defined in: memory-harness.ts:83
Executes memory_init at session start and after context compaction, returning the config-adapted protocol and all unscoped 'general' and <role> rules, lessons, and active notes (§6.2).
Parameters
| Parameter | Type | Description |
|---|---|---|
input | { role: string; sessionId?: string; } | Session role and optional session identifier. |
input.role? | string | - |
input.sessionId? | string | - |
Returns
Promise<{ lessons: object[]; notes: object[]; protocol: string; repoId: string; role: string; rules: object[]; }>
Protocol markdown and ordered unscoped memories.
Throws
With 'CONFIG_NOT_FOUND', 'CONFIG_VALIDATION_FAILED', 'INVALID_ROLE', 'VALIDATION_FAILED', or 'GIT_SYNC_FAILED'.
Implementation of
loadScoped()
loadScoped(input): Promise<{
lessons: object[];
normalizedPaths: string[];
notes: object[];
role: string;
rules: object[];
}>;Defined in: memory-harness.ts:102
Executes memory_load_scoped for specific file paths, directories, or glob patterns (§6.3).
Parameters
| Parameter | Type | Description |
|---|---|---|
input | { paths: string[]; role: string; sessionId?: string; } | Target role, paths/globs to match, and optional session identifier. |
input.paths? | string[] | - |
input.role? | string | - |
input.sessionId? | string | - |
Returns
Promise<{ lessons: object[]; normalizedPaths: string[]; notes: object[]; role: string; rules: object[]; }>
Normalized query paths and matching scoped rules, lessons, and notes.
Throws
With 'CONFIG_NOT_FOUND', 'CONFIG_VALIDATION_FAILED', 'INVALID_ROLE', 'VALIDATION_FAILED', or 'GIT_SYNC_FAILED'.
Implementation of
MemoryHarnessContract.loadScoped
propose()
propose(input): Promise<
| {
bucketStatus: {
bucketId: string;
bucketRecordIds: string[];
currentCount: number;
hardCap: number | null;
maxTotalRecords: number | null;
maxTotalRecordsReached: boolean;
softCap: number | null;
totalRecordsCount: number;
zone: "UNCAPPED" | "UNDER_SOFT_CAP" | "SOFT_CAP_PRESSURE" | "AT_HARD_CAP";
};
choices: (
| {
alsoRemoveIds?: string[];
existingRecord: | {
context?: string[];
createdAt: string;
id: string;
repos?: string[];
role: string;
text: string;
type: "rule";
updatedAt?: string;
}
| {
context?: string[];
createdAt: string;
id: string;
repos?: string[];
role: string;
text: string;
type: "lesson";
updatedAt?: string;
};
op: "update";
proposedContext?: string[] | null;
proposedRepos?: string[] | null;
proposedRole: string;
proposedText: string;
targetId: string;
whyMatched: string;
}
| {
capMerge?: {
keepId: string;
mergedText: string;
removeId: string;
whyMerged: string;
};
op: "add";
proposedContext?: string[];
proposedRepos?: string[];
proposedRole: string;
proposedText: string;
})[];
executionMode: "resolved";
matchStatus: | "NO_MATCH"
| "LIKELY_MATCH"
| "EXACT_DUPLICATE"
| "REJECTED_TIER_1_OR_2";
recommendedChoiceIndex: number;
requiresOwnerGo: boolean;
tierRejectionReason?: string;
type: "rule" | "lesson";
}
| {
bucketStatus: {
bucketId: string;
bucketRecordIds: string[];
currentCount: number;
hardCap: number | null;
maxTotalRecords: number | null;
maxTotalRecordsReached: boolean;
softCap: number | null;
totalRecordsCount: number;
zone: "UNCAPPED" | "UNDER_SOFT_CAP" | "SOFT_CAP_PRESSURE" | "AT_HARD_CAP";
};
delegateToSubagent: {
effort: "low" | "medium" | "high";
model: string;
outputJsonSchema: Record<string, unknown>;
systemPrompt: string;
timeoutMs: number;
userPrompt: string;
};
executionMode: "delegate_to_subagent";
requiresOwnerGo: boolean;
type: "rule" | "lesson";
}>;Defined in: memory-harness.ts:121
Executes memory_propose to format, deduplicate, and evaluate capacity for a rule or lesson candidate (§6.4).
Parameters
| Parameter | Type | Description |
|---|---|---|
input | { callerRole: string; context?: string[]; incident?: string; rawText: string; repos?: string[]; targetRole: string; type: "rule" | "lesson"; } | Candidate rule or lesson payload and optional scope/incident context. |
input.callerRole? | string | - |
input.context? | string[] | - |
input.incident? | string | - |
input.rawText? | string | - |
input.repos? | string[] | - |
input.targetRole? | string | - |
input.type? | "rule" | "lesson" | - |
Returns
Promise< | { bucketStatus: { bucketId: string; bucketRecordIds: string[]; currentCount: number; hardCap: number | null; maxTotalRecords: number | null; maxTotalRecordsReached: boolean; softCap: number | null; totalRecordsCount: number; zone: "UNCAPPED" | "UNDER_SOFT_CAP" | "SOFT_CAP_PRESSURE" | "AT_HARD_CAP"; }; choices: ( | { alsoRemoveIds?: string[]; existingRecord: | { context?: string[]; createdAt: string; id: string; repos?: string[]; role: string; text: string; type: "rule"; updatedAt?: string; } | { context?: string[]; createdAt: string; id: string; repos?: string[]; role: string; text: string; type: "lesson"; updatedAt?: string; }; op: "update"; proposedContext?: string[] | null; proposedRepos?: string[] | null; proposedRole: string; proposedText: string; targetId: string; whyMatched: string; } | { capMerge?: { keepId: string; mergedText: string; removeId: string; whyMerged: string; }; op: "add"; proposedContext?: string[]; proposedRepos?: string[]; proposedRole: string; proposedText: string; })[]; executionMode: "resolved"; matchStatus: | "NO_MATCH" | "LIKELY_MATCH" | "EXACT_DUPLICATE" | "REJECTED_TIER_1_OR_2"; recommendedChoiceIndex: number; requiresOwnerGo: boolean; tierRejectionReason?: string; type: "rule" | "lesson"; } | { bucketStatus: { bucketId: string; bucketRecordIds: string[]; currentCount: number; hardCap: number | null; maxTotalRecords: number | null; maxTotalRecordsReached: boolean; softCap: number | null; totalRecordsCount: number; zone: "UNCAPPED" | "UNDER_SOFT_CAP" | "SOFT_CAP_PRESSURE" | "AT_HARD_CAP"; }; delegateToSubagent: { effort: "low" | "medium" | "high"; model: string; outputJsonSchema: Record<string, unknown>; systemPrompt: string; timeoutMs: number; userPrompt: string; }; executionMode: "delegate_to_subagent"; requiresOwnerGo: boolean; type: "rule" | "lesson"; }>
Resolved Distiller proposal choices or subagent delegation payload.
Throws
With 'CONFIG_NOT_FOUND', 'CONFIG_VALIDATION_FAILED', 'INVALID_ROLE', 'VALIDATION_FAILED', 'LESSON_FORMAT_INVALID', 'RULE_PROTECTION_VIOLATION', 'DISTILLER_EXECUTION_FAILED', or 'GIT_SYNC_FAILED'.