ctxpool 0.1.0

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.
@@ -0,0 +1,33 @@
1
+ import { type Database } from "sql.js";
2
+ import type { ContextPack, HandoffPacket, HandoffSummary } from "./types.js";
3
+ export declare function openStore(dbPath?: string): Promise<CtxStore>;
4
+ export declare class CtxStore {
5
+ private db;
6
+ private dbPath;
7
+ constructor(db: Database, dbPath: string);
8
+ close(): void;
9
+ saveHandoff(packet: HandoffPacket): void;
10
+ listTasks(): {
11
+ task: string;
12
+ handoffCount: number;
13
+ latestAt: string;
14
+ }[];
15
+ listHandoffs(task?: string): HandoffSummary[];
16
+ listHandoffPackets(task?: string): HandoffPacket[];
17
+ getLatestHandoff(task?: string): HandoffPacket | undefined;
18
+ getHandoffById(id: string): HandoffPacket | undefined;
19
+ saveContextPack(pack: ContextPack): ContextPack;
20
+ listContextPacks(): ContextPack[];
21
+ getContextPackById(id: string): ContextPack | undefined;
22
+ deleteContextPack(id: string): boolean;
23
+ getStatus(): {
24
+ home: string;
25
+ dbPath: string;
26
+ teamExportsDir: string;
27
+ handoffCount: number;
28
+ taskCount: number;
29
+ };
30
+ private migrate;
31
+ private queryRows;
32
+ private persist;
33
+ }
package/dist/store.js ADDED
@@ -0,0 +1,215 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import initSqlJs from "sql.js";
4
+ import { ensureCtxDirs, getCtxPaths } from "./paths.js";
5
+ import { normalizeContextPack, normalizeHandoffPacket } from "./handoff.js";
6
+ let sqlModule;
7
+ export async function openStore(dbPath = getCtxPaths().dbPath) {
8
+ ensureCtxDirs();
9
+ sqlModule ||= initSqlJs({
10
+ locateFile: (file) => {
11
+ const require = createRequire(import.meta.url);
12
+ return require.resolve(`sql.js/dist/${file}`);
13
+ }
14
+ });
15
+ const SQL = await sqlModule;
16
+ const db = existsSync(dbPath) ? new SQL.Database(readFileSync(dbPath)) : new SQL.Database();
17
+ return new CtxStore(db, dbPath);
18
+ }
19
+ export class CtxStore {
20
+ db;
21
+ dbPath;
22
+ constructor(db, dbPath) {
23
+ this.db = db;
24
+ this.dbPath = dbPath;
25
+ this.migrate();
26
+ }
27
+ close() {
28
+ this.persist();
29
+ this.db.close();
30
+ }
31
+ saveHandoff(packet) {
32
+ this.db.run(`
33
+ INSERT OR REPLACE INTO handoffs (
34
+ id, task, created_at, repo_path, branch, commit_hash, markdown_path,
35
+ next_best_action, blockers_json, files_json, status_json, packet_json
36
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
37
+ `, [
38
+ packet.id,
39
+ packet.task,
40
+ packet.createdAt,
41
+ packet.repo.repoPath,
42
+ packet.repo.branch,
43
+ packet.repo.commit,
44
+ packet.markdownPath,
45
+ packet.sections.nextBestAction,
46
+ JSON.stringify(packet.sections.blockers),
47
+ JSON.stringify(packet.sections.filesTouched),
48
+ JSON.stringify(packet.sections.currentStatus),
49
+ JSON.stringify(packet)
50
+ ]);
51
+ this.persist();
52
+ }
53
+ listTasks() {
54
+ return this.queryRows(`
55
+ SELECT task, COUNT(*) as handoffCount, MAX(created_at) as latestAt
56
+ FROM handoffs
57
+ GROUP BY task
58
+ ORDER BY latestAt DESC
59
+ `);
60
+ }
61
+ listHandoffs(task) {
62
+ const rows = task
63
+ ? this.queryRows("SELECT * FROM handoffs WHERE task = ? ORDER BY created_at DESC", [task])
64
+ : this.queryRows("SELECT * FROM handoffs ORDER BY created_at DESC");
65
+ return rows.map(rowToSummary);
66
+ }
67
+ listHandoffPackets(task) {
68
+ const rows = task
69
+ ? this.queryRows("SELECT * FROM handoffs WHERE task = ? ORDER BY created_at DESC", [task])
70
+ : this.queryRows("SELECT * FROM handoffs ORDER BY created_at DESC");
71
+ return rows.map(rowToPacket);
72
+ }
73
+ getLatestHandoff(task) {
74
+ const rows = task
75
+ ? this.queryRows("SELECT * FROM handoffs WHERE task = ? ORDER BY created_at DESC LIMIT 1", [task])
76
+ : this.queryRows("SELECT * FROM handoffs ORDER BY created_at DESC LIMIT 1");
77
+ return rows[0] ? rowToPacket(rows[0]) : undefined;
78
+ }
79
+ getHandoffById(id) {
80
+ const rows = this.queryRows("SELECT * FROM handoffs WHERE id = ? LIMIT 1", [id]);
81
+ return rows[0] ? rowToPacket(rows[0]) : undefined;
82
+ }
83
+ saveContextPack(pack) {
84
+ const normalized = normalizeContextPack({
85
+ ...pack,
86
+ updatedAt: pack.updatedAt || new Date().toISOString()
87
+ });
88
+ this.db.run(`
89
+ INSERT OR REPLACE INTO context_packs (
90
+ id, name, created_at, updated_at, pack_json
91
+ ) VALUES (?, ?, ?, ?, ?)
92
+ `, [normalized.id, normalized.name, normalized.createdAt, normalized.updatedAt, JSON.stringify(normalized)]);
93
+ this.persist();
94
+ return normalized;
95
+ }
96
+ listContextPacks() {
97
+ const rows = this.queryRows("SELECT * FROM context_packs ORDER BY updated_at DESC");
98
+ return rows.map(rowToContextPack);
99
+ }
100
+ getContextPackById(id) {
101
+ const rows = this.queryRows("SELECT * FROM context_packs WHERE id = ? LIMIT 1", [id]);
102
+ return rows[0] ? rowToContextPack(rows[0]) : undefined;
103
+ }
104
+ deleteContextPack(id) {
105
+ const before = Number(this.queryRows("SELECT COUNT(*) as count FROM context_packs WHERE id = ?", [id])[0].count);
106
+ this.db.run("DELETE FROM context_packs WHERE id = ?", [id]);
107
+ this.persist();
108
+ return before > 0;
109
+ }
110
+ getStatus() {
111
+ const paths = getCtxPaths();
112
+ const handoffCount = this.queryRows("SELECT COUNT(*) as count FROM handoffs")[0];
113
+ const taskCount = this.queryRows("SELECT COUNT(DISTINCT task) as count FROM handoffs")[0];
114
+ return {
115
+ home: paths.home,
116
+ dbPath: paths.dbPath,
117
+ teamExportsDir: paths.teamExportsDir,
118
+ handoffCount: Number(handoffCount.count),
119
+ taskCount: Number(taskCount.count)
120
+ };
121
+ }
122
+ migrate() {
123
+ this.db.run(`
124
+ CREATE TABLE IF NOT EXISTS handoffs (
125
+ id TEXT PRIMARY KEY,
126
+ task TEXT NOT NULL,
127
+ created_at TEXT NOT NULL,
128
+ repo_path TEXT NOT NULL,
129
+ branch TEXT NOT NULL,
130
+ commit_hash TEXT NOT NULL,
131
+ markdown_path TEXT NOT NULL,
132
+ next_best_action TEXT NOT NULL,
133
+ blockers_json TEXT NOT NULL,
134
+ files_json TEXT NOT NULL,
135
+ status_json TEXT NOT NULL,
136
+ packet_json TEXT NOT NULL
137
+ );
138
+ `);
139
+ this.db.run(`
140
+ CREATE INDEX IF NOT EXISTS idx_handoffs_task_created
141
+ ON handoffs(task, created_at DESC);
142
+ `);
143
+ this.db.run(`
144
+ CREATE TABLE IF NOT EXISTS context_packs (
145
+ id TEXT PRIMARY KEY,
146
+ name TEXT NOT NULL,
147
+ created_at TEXT NOT NULL,
148
+ updated_at TEXT NOT NULL,
149
+ pack_json TEXT NOT NULL
150
+ );
151
+ `);
152
+ this.db.run(`
153
+ CREATE INDEX IF NOT EXISTS idx_context_packs_updated
154
+ ON context_packs(updated_at DESC);
155
+ `);
156
+ this.persist();
157
+ }
158
+ queryRows(sql, params = []) {
159
+ const stmt = this.db.prepare(sql, params);
160
+ const rows = [];
161
+ try {
162
+ while (stmt.step())
163
+ rows.push(stmt.getAsObject());
164
+ return rows;
165
+ }
166
+ finally {
167
+ stmt.free();
168
+ }
169
+ }
170
+ persist() {
171
+ writeFileSync(this.dbPath, this.db.export());
172
+ }
173
+ }
174
+ function rowToSummary(row) {
175
+ return {
176
+ id: String(row.id),
177
+ task: String(row.task),
178
+ createdAt: String(row.created_at),
179
+ repoPath: String(row.repo_path),
180
+ branch: String(row.branch),
181
+ commit: String(row.commit_hash),
182
+ markdownPath: String(row.markdown_path),
183
+ nextBestAction: String(row.next_best_action),
184
+ blockers: parseJsonArray(String(row.blockers_json)),
185
+ filesTouched: parseJsonArray(String(row.files_json)),
186
+ status: parseJsonArray(String(row.status_json))
187
+ };
188
+ }
189
+ function rowToPacket(row) {
190
+ const packet = JSON.parse(String(row.packet_json));
191
+ if (!packet.markdown && existsSync(String(row.markdown_path))) {
192
+ packet.markdown = readFileSync(String(row.markdown_path), "utf8");
193
+ }
194
+ return normalizeHandoffPacket(packet);
195
+ }
196
+ function rowToContextPack(row) {
197
+ const pack = JSON.parse(String(row.pack_json));
198
+ return normalizeContextPack({
199
+ ...pack,
200
+ id: String(row.id),
201
+ name: String(row.name),
202
+ createdAt: String(row.created_at),
203
+ updatedAt: String(row.updated_at)
204
+ });
205
+ }
206
+ function parseJsonArray(value) {
207
+ try {
208
+ const parsed = JSON.parse(value);
209
+ return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
210
+ }
211
+ catch {
212
+ return [];
213
+ }
214
+ }
215
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,242 @@
1
+ export type GitSnapshot = {
2
+ repoPath: string;
3
+ isGitRepo: boolean;
4
+ branch: string;
5
+ commit: string;
6
+ dirtyFiles: string[];
7
+ fileChanges?: FileChange[];
8
+ diffStat: string;
9
+ diffPatch: string;
10
+ diffPatchTruncated: boolean;
11
+ stagedDiffPatch?: string;
12
+ stagedDiffPatchTruncated?: boolean;
13
+ unstagedDiffPatch?: string;
14
+ unstagedDiffPatchTruncated?: boolean;
15
+ recentCommits: string[];
16
+ };
17
+ export type FileChangeStatus = "added" | "modified" | "deleted" | "renamed" | "copied" | "untracked" | "unknown";
18
+ export type FileChange = {
19
+ path: string;
20
+ oldPath?: string;
21
+ status: FileChangeStatus;
22
+ indexStatus?: string;
23
+ worktreeStatus?: string;
24
+ additions: number;
25
+ deletions: number;
26
+ staged: boolean;
27
+ unstaged: boolean;
28
+ untracked: boolean;
29
+ diff?: string;
30
+ };
31
+ export type WorkPhase = "planning" | "implementation" | "debugging" | "verification" | "blocked" | "handoff";
32
+ export type VerificationStatus = "passed" | "failed" | "unknown";
33
+ export type VerificationCommand = {
34
+ command: string;
35
+ status: VerificationStatus;
36
+ evidence?: string;
37
+ };
38
+ export type VerificationSummary = {
39
+ status: VerificationStatus;
40
+ commands: VerificationCommand[];
41
+ gaps: string[];
42
+ };
43
+ export type RepoStats = {
44
+ dirtyFiles: number;
45
+ stagedFiles: number;
46
+ unstagedFiles: number;
47
+ untrackedFiles: number;
48
+ additions: number;
49
+ deletions: number;
50
+ };
51
+ export type ContextSignal = {
52
+ kind: "decision" | "constraint" | "risk" | "anchor";
53
+ text: string;
54
+ };
55
+ export type ProvenanceKind = "user-authored" | "transcript-derived" | "diff-derived" | "command-derived" | "ai-inferred";
56
+ export type ProvenanceLabel = {
57
+ kind: ProvenanceKind;
58
+ confidence: "high" | "medium" | "low";
59
+ source: string;
60
+ };
61
+ export type MemoryFact = {
62
+ id: string;
63
+ text: string;
64
+ provenance: ProvenanceLabel;
65
+ };
66
+ export type StableIdentity = {
67
+ taskId: string;
68
+ repoId: string;
69
+ branchId: string;
70
+ commitId: string;
71
+ handoffId: string;
72
+ sessionId?: string;
73
+ sourceAgent?: SourceAgent;
74
+ };
75
+ export type TeamSyncPolicy = {
76
+ mode: "local-only" | "sync-ready";
77
+ rawTranscript: "included" | "excluded";
78
+ filePreviewRedaction: "enabled";
79
+ secretsRedaction: "enabled";
80
+ userControlledSync: true;
81
+ };
82
+ export type EngineeringMemory = {
83
+ version: 1;
84
+ identity: StableIdentity;
85
+ positioning: {
86
+ category: "handoff-ledger";
87
+ buyer: "ai-heavy-engineering-teams";
88
+ moat: "provenance-backed-engineering-memory";
89
+ };
90
+ intent: MemoryFact[];
91
+ decisions: MemoryFact[];
92
+ constraints: MemoryFact[];
93
+ verification: MemoryFact[];
94
+ risks: MemoryFact[];
95
+ nextActions: MemoryFact[];
96
+ changedFiles: MemoryFact[];
97
+ teamSync: TeamSyncPolicy;
98
+ };
99
+ export type AgentSignal = {
100
+ source: "codex" | "claude" | "unknown";
101
+ path: string;
102
+ modifiedAt: string;
103
+ snippets: string[];
104
+ };
105
+ export type SourceAgent = "codex" | "claude";
106
+ export type TranscriptEntry = {
107
+ role: "user" | "assistant" | "tool" | "system";
108
+ text: string;
109
+ timestamp?: string;
110
+ kind?: string;
111
+ };
112
+ export type SourceSession = {
113
+ source: SourceAgent;
114
+ id: string;
115
+ path: string;
116
+ cwd?: string;
117
+ updatedAt: string;
118
+ matchedCwd: boolean;
119
+ lineCount: number;
120
+ transcript: TranscriptEntry[];
121
+ transcriptExcerpt: string;
122
+ threadName?: string;
123
+ supplementalPaths?: string[];
124
+ };
125
+ export type HandoffSections = {
126
+ goal: string;
127
+ currentStatus: string[];
128
+ completed: string[];
129
+ inProgress: string[];
130
+ todos: string[];
131
+ blockers: string[];
132
+ filesTouched: string[];
133
+ commandsRun: string[];
134
+ errors: string[];
135
+ decisions: string[];
136
+ doNotRepeat: string[];
137
+ nextBestAction: string;
138
+ };
139
+ export type HandoffContinuitySummary = {
140
+ version: 1;
141
+ originalQuestion: string;
142
+ latestUserInstruction: string;
143
+ latestAssistantSummary: string;
144
+ agentPlan: string;
145
+ workPhase: WorkPhase;
146
+ verification: VerificationSummary;
147
+ repoStats: RepoStats;
148
+ contextSignals: ContextSignal[];
149
+ completedWork: string[];
150
+ inProgressWork: string[];
151
+ remainingWork: string[];
152
+ blockers: string[];
153
+ nextAction: string;
154
+ fileChanges: FileChange[];
155
+ commandsRun: string[];
156
+ errors: string[];
157
+ decisions: string[];
158
+ sourceSession?: {
159
+ source: SourceAgent;
160
+ id: string;
161
+ cwd?: string;
162
+ matchedCwd: boolean;
163
+ updatedAt: string;
164
+ transcriptItems: number;
165
+ };
166
+ repo: {
167
+ repoPath: string;
168
+ branch: string;
169
+ commit: string;
170
+ isGitRepo: boolean;
171
+ };
172
+ };
173
+ export type HandoffPacket = {
174
+ id: string;
175
+ task: string;
176
+ createdAt: string;
177
+ targetAgent?: string;
178
+ repo: GitSnapshot;
179
+ sources: AgentSignal[];
180
+ sourceSession?: SourceSession;
181
+ sections: HandoffSections;
182
+ handoffSummary?: HandoffContinuitySummary;
183
+ engineeringMemory?: EngineeringMemory;
184
+ markdown: string;
185
+ markdownPath: string;
186
+ };
187
+ export type HandoffSummary = {
188
+ id: string;
189
+ task: string;
190
+ createdAt: string;
191
+ repoPath: string;
192
+ branch: string;
193
+ commit: string;
194
+ markdownPath: string;
195
+ nextBestAction: string;
196
+ blockers: string[];
197
+ filesTouched: string[];
198
+ status: string[];
199
+ };
200
+ export type ContextBlockCategory = "intent" | "instruction" | "decision" | "constraint" | "verification" | "risk" | "next-action" | "changed-file" | "transcript";
201
+ export type ContextBlock = {
202
+ id: string;
203
+ sourceHandoffId: string;
204
+ sourceTask: string;
205
+ sourceCreatedAt: string;
206
+ category: ContextBlockCategory;
207
+ title: string;
208
+ text: string;
209
+ provenance: ProvenanceLabel;
210
+ estimatedChars: number;
211
+ };
212
+ export type ContextPackItem = {
213
+ id: string;
214
+ blockId: string;
215
+ block: ContextBlock;
216
+ order: number;
217
+ enabled: boolean;
218
+ };
219
+ export type ContextPack = {
220
+ id: string;
221
+ name: string;
222
+ createdAt: string;
223
+ updatedAt: string;
224
+ includeRawTranscript: boolean;
225
+ items: ContextPackItem[];
226
+ };
227
+ export type ContextPackOutput = {
228
+ pack: ContextPack;
229
+ markdown: string;
230
+ json: {
231
+ id: string;
232
+ name: string;
233
+ createdAt: string;
234
+ updatedAt: string;
235
+ includeRawTranscript: boolean;
236
+ estimatedChars: number;
237
+ warnings: string[];
238
+ items: ContextPackItem[];
239
+ };
240
+ estimatedChars: number;
241
+ warnings: string[];
242
+ };
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/dist/ui.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { type IncomingMessage } from "node:http";
2
+ export type UiOptions = {
3
+ host?: string;
4
+ port?: number;
5
+ };
6
+ export type FileViewResult = {
7
+ ok: true;
8
+ path: string;
9
+ absolutePath: string;
10
+ size: number;
11
+ language: string;
12
+ content: string;
13
+ truncated: boolean;
14
+ redacted?: boolean;
15
+ } | {
16
+ ok: false;
17
+ path?: string;
18
+ size?: number;
19
+ error: string;
20
+ };
21
+ export declare function isValidContextPackBody(body: Record<string, unknown>): boolean;
22
+ export declare function startUi(options?: UiOptions): Promise<void>;
23
+ export declare function isLocalRequest(req: Pick<IncomingMessage, "headers">): boolean;
24
+ export declare function readRepoFileForView(repoPath: string, filePath: string): FileViewResult;
25
+ export declare function resolveSafeRepoPath(repoPath: string, filePath: string): {
26
+ ok: true;
27
+ path: string;
28
+ } | {
29
+ ok: false;
30
+ error: string;
31
+ };