@cogit/cli 0.25.7 → 0.27.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cogit",
3
3
  "displayName": "cogit",
4
- "version": "0.25.7",
4
+ "version": "0.27.0",
5
5
  "description": "Git remembers what changed. cogit remembers why.",
6
6
  "author": {
7
7
  "name": "Eren Sertkaya"
package/README.md CHANGED
@@ -25,6 +25,8 @@ Claude Code today.
25
25
  - **Intent, Shape, Code**: a message that landed commits shows why it happened, a small
26
26
  picture of what the change does (a diagram, a before/after or interface table, an example
27
27
  or plain steps), and the diff, in one place.
28
+ - **Captured work**: when a session ends, a small model drafts a few user-level items from
29
+ what it left undone; you accept, dismiss or close them (`cogit captures`, and on the map).
28
30
  - **Pull request descriptions with the decisions**: `cogit pr` writes the goal, the
29
31
  decisions and the rejected options, never the raw chat.
30
32
  - **Teams share the record through git**: after a pull, your teammates' sessions are on the
@@ -79,7 +81,7 @@ cogit open .
79
81
 
80
82
  - [Getting started](docs/guide/getting-started.md): what `init` asks, your first session,
81
83
  setting up a team
82
- - [The map](docs/guide/map.md): sessions, branches, the inbox, unread work, files, search,
84
+ - [The map](docs/guide/map.md): sessions, branches, the inbox, files, search,
83
85
  resuming and forking a session
84
86
  - [Reading the lineage](docs/guide/reading-the-lineage.md): `log`, `show`, `blame`, `why`,
85
87
  `search`
@@ -21109,16 +21109,12 @@ function projectPaths(root) {
21109
21109
  conversations: join6(base, "conversations"),
21110
21110
  conversation: (id) => join6(base, "conversations", `${id}.jsonl.gz`),
21111
21111
  state: (id) => join6(base, "state", `${id}.json`),
21112
- /**
21113
- * Which messages this user has marked read (Story 10.3). Local per-user
21114
- * state: never committed, never shared (`state/` stays ignored by both
21115
- * policies).
21116
- */
21117
- readState: join6(base, "state", "read.json"),
21118
21112
  /** Inbox rows the user dismissed, per session (Story 11.1); also local. */
21119
21113
  inboxState: join6(base, "state", "inbox.json"),
21120
21114
  /** How the user left the map: open sessions and dragged row widths; also local. */
21121
21115
  mapView: join6(base, "state", "map.json"),
21116
+ /** The curated captured-work list (Story 15.1); local, never committed. */
21117
+ captures: join6(base, "state", "captures.json"),
21122
21118
  /** What the detached hook children (build, side run) printed; local, capped. */
21123
21119
  detachedLog: join6(base, "state", "detached.log"),
21124
21120
  /** Commits waiting for their message's record before a Shape; local. */
@@ -21210,7 +21206,7 @@ async function migrateProject(root) {
21210
21206
  const next = renameGitignoreLines(text);
21211
21207
  if (next !== text) await atomicWrite(gitignore, next).catch(() => void 0);
21212
21208
  }
21213
- const { installGitHooks: installGitHooks2 } = await import("./git-hooks-AMCDWEHG.js");
21209
+ const { installGitHooks: installGitHooks2 } = await import("./git-hooks-4VS72KY5.js");
21214
21210
  await installGitHooks2(dir).catch(() => void 0);
21215
21211
  return true;
21216
21212
  }
@@ -21334,6 +21330,12 @@ var Config = external_exports.object({
21334
21330
  * records. Off writes nothing; the map then says so.
21335
21331
  */
21336
21332
  shapes: external_exports.boolean().default(true),
21333
+ /**
21334
+ * Whether the side model distils each session's leftover work into a short
21335
+ * curated list (Story 15.1). Off writes nothing; items already in the store
21336
+ * are kept and come back when it is turned on again.
21337
+ */
21338
+ captures: external_exports.boolean().default(true),
21337
21339
  /**
21338
21340
  * Whether SessionStart hands the agent the lineage of the previous session and
21339
21341
  * how to read the record (`log` / `show`). On by default; costs only tokens.
@@ -24238,6 +24240,7 @@ var PANEL_EDITABLE_KEYS = [
24238
24240
  "recordHeadless",
24239
24241
  "tryBeforeNotes",
24240
24242
  "shapes",
24243
+ "captures",
24241
24244
  "language",
24242
24245
  "shareConversations",
24243
24246
  "recordCommit"
@@ -24609,26 +24612,6 @@ async function blame(opts) {
24609
24612
  return hits;
24610
24613
  }
24611
24614
 
24612
- // src/store/changes.ts
24613
- async function readProjectChanges(root, hashes) {
24614
- const wanted = [...new Set(hashes)];
24615
- if (wanted.length === 0) return /* @__PURE__ */ new Map();
24616
- const gitRoot = await findGitRoot(root);
24617
- if (gitRoot === void 0) return /* @__PURE__ */ new Map();
24618
- const raw = await readCommitChanges(gitRoot, wanted);
24619
- if (gitRoot === root) return raw;
24620
- const files = projectFiles(
24621
- gitRoot,
24622
- root,
24623
- new Map([...raw].map(([hash2, change]) => [hash2, change.files]))
24624
- );
24625
- const out = /* @__PURE__ */ new Map();
24626
- for (const [hash2, change] of raw) {
24627
- out.set(hash2, { ...change, files: files.get(hash2) ?? [] });
24628
- }
24629
- return out;
24630
- }
24631
-
24632
24615
  // src/store/events.ts
24633
24616
  import { appendFile as appendFile2, mkdir as mkdir5, readFile as readFile7 } from "fs/promises";
24634
24617
  import { dirname as dirname7 } from "path";
@@ -24736,114 +24719,6 @@ function seedEvents(nodes, at) {
24736
24719
  return events;
24737
24720
  }
24738
24721
 
24739
- // src/store/read-state.ts
24740
- var READ_STATE_SCHEMA = 1;
24741
- var MESSAGE_ID2 = /^h[0-9a-f]{12}$/;
24742
- var ReadState = external_exports.object({
24743
- schema: external_exports.literal(READ_STATE_SCHEMA),
24744
- /** Read message ids (`h` plus 12 hex). */
24745
- read: external_exports.array(external_exports.string().regex(MESSAGE_ID2)).default([])
24746
- });
24747
- async function readReadState(root) {
24748
- const read = await readJson(projectPaths(root).readState);
24749
- if (!read.found || "error" in read) return /* @__PURE__ */ new Set();
24750
- const parsed = ReadState.safeParse(read.value);
24751
- return new Set(parsed.success ? parsed.data.read : []);
24752
- }
24753
- async function setMessageRead(root, id, read) {
24754
- if (!MESSAGE_ID2.test(id)) throw new Error(`not a message id: ${id}`);
24755
- const p = projectPaths(root);
24756
- await withLock(
24757
- p.lock("read-state"),
24758
- async () => {
24759
- const ids = await readReadState(root);
24760
- if (read) ids.add(id);
24761
- else ids.delete(id);
24762
- await atomicWriteJson(p.readState, {
24763
- schema: READ_STATE_SCHEMA,
24764
- read: [...ids].sort()
24765
- });
24766
- },
24767
- { timeoutMs: 2e3 }
24768
- );
24769
- }
24770
-
24771
- // src/view/change.ts
24772
- function messageChange(commits, changes) {
24773
- if (commits === void 0 || commits.length === 0) return void 0;
24774
- const seen = /* @__PURE__ */ new Set();
24775
- const files = /* @__PURE__ */ new Set();
24776
- let added = 0;
24777
- let removed = 0;
24778
- for (const hash2 of commits) {
24779
- const change = changes.get(hash2);
24780
- if (change === void 0 || seen.has(change.full)) continue;
24781
- seen.add(change.full);
24782
- added += change.added;
24783
- removed += change.removed;
24784
- for (const file2 of change.files) files.add(file2);
24785
- }
24786
- if (seen.size === 0) return void 0;
24787
- return { added, removed, files: files.size };
24788
- }
24789
- function attachChanges(sessions, changes) {
24790
- if (changes.size === 0) return sessions.map((session) => session);
24791
- return sessions.map((session) => {
24792
- let changed = false;
24793
- const nodes = session.nodes.map((node2) => {
24794
- if (node2.kind !== "message") return node2;
24795
- const change = messageChange(node2.commits, changes);
24796
- if (change === void 0) {
24797
- if (node2.change === void 0) return node2;
24798
- changed = true;
24799
- const { change: _dropped, ...rest } = node2;
24800
- return rest;
24801
- }
24802
- changed = true;
24803
- return { ...node2, change };
24804
- });
24805
- return changed ? { ...session, nodes } : session;
24806
- });
24807
- }
24808
- function changeLines(change) {
24809
- return change.added + change.removed;
24810
- }
24811
- function isBigChange(change, threshold) {
24812
- return changeLines(change) >= threshold;
24813
- }
24814
- function unreadMessages(sessions, read) {
24815
- const out = [];
24816
- for (const session of sessions) {
24817
- for (const node2 of session.nodes) {
24818
- if (node2.kind !== "message" || node2.change === void 0) continue;
24819
- if (read.has(node2.id)) continue;
24820
- out.push({
24821
- sessionId: session.sessionId,
24822
- sessionTitle: session.title,
24823
- sessionStartedAt: session.startedAt,
24824
- messageId: node2.id,
24825
- label: node2.label ?? node2.id,
24826
- title: node2.title,
24827
- ...node2.at === void 0 ? {} : { at: node2.at },
24828
- change: node2.change
24829
- });
24830
- }
24831
- }
24832
- return out.sort(
24833
- (a, b) => changeLines(b.change) - changeLines(a.change) || b.change.files - a.change.files || a.title.localeCompare(b.title) || a.messageId.localeCompare(b.messageId)
24834
- );
24835
- }
24836
- function countBigUnread(sessions, read, threshold) {
24837
- return unreadMessages(sessions, read).filter((message) => isBigChange(message.change, threshold)).length;
24838
- }
24839
- function grouped(value) {
24840
- return String(Math.max(0, Math.trunc(value))).replace(/\B(?=(\d{3})+(?!\d))/g, " ");
24841
- }
24842
- function formatChange(change) {
24843
- const files = `${change.files} file${change.files === 1 ? "" : "s"}`;
24844
- return `+${grouped(change.added)} \u2212${grouped(change.removed)} \xB7 ${files}`;
24845
- }
24846
-
24847
24722
  // src/view/files.ts
24848
24723
  function timeOf(at) {
24849
24724
  if (at === void 0) return Number.NEGATIVE_INFINITY;
@@ -25342,43 +25217,6 @@ async function log(opts) {
25342
25217
  for (const line of formatLog(model, opts.branchesOnly === true)) opts.io.out(line);
25343
25218
  return model;
25344
25219
  }
25345
- async function logUnread(opts) {
25346
- const root = await openProject(opts.dir);
25347
- const sessions = await loadEffectiveSessions(root, opts.io);
25348
- const hashes = new Set(
25349
- sessions.flatMap((entry) => entry.messages.flatMap((message) => message.commits ?? []))
25350
- );
25351
- const changes = hashes.size === 0 ? /* @__PURE__ */ new Map() : await readProjectChanges(root, hashes);
25352
- const read = await readReadState(root);
25353
- const unread = unreadMessages(
25354
- sessions.map(({ session, messages }) => ({
25355
- sessionId: session.sessionId,
25356
- title: session.title,
25357
- startedAt: session.startedAt,
25358
- nodes: messages.map((message) => ({
25359
- ...message,
25360
- change: messageChange(message.commits, changes)
25361
- }))
25362
- })),
25363
- read
25364
- );
25365
- if (opts.json === true) {
25366
- opts.io.out(JSON.stringify(unread, null, 2));
25367
- return unread;
25368
- }
25369
- for (const line of formatUnread(unread)) opts.io.out(line);
25370
- return unread;
25371
- }
25372
- function formatUnread(messages) {
25373
- if (messages.length === 0) return ["No unread messages with linked commits."];
25374
- return messages.map((message) => {
25375
- const parts = [
25376
- ` ${shortHash(message.messageId)} ${message.label} ${clock(message.at)} ${formatChange(message.change)} ${oneLine3(message.title)}`
25377
- ];
25378
- parts.push(` \xB7 ${oneLine3(message.sessionTitle)}`);
25379
- return parts.join("");
25380
- });
25381
- }
25382
25220
  function normalizeFilePath(file2) {
25383
25221
  return file2.replace(/\\/g, "/").replace(/^(\.\/)+/, "").replace(/\/+$/, "");
25384
25222
  }
@@ -25721,7 +25559,7 @@ async function onSessionEnd(ctx) {
25721
25559
  // package.json
25722
25560
  var package_default = {
25723
25561
  name: "@cogit/cli",
25724
- version: "0.25.7",
25562
+ version: "0.27.0",
25725
25563
  description: "Git remembers what changed. cogit remembers why.",
25726
25564
  license: "MIT",
25727
25565
  keywords: [
@@ -26369,6 +26207,7 @@ export {
26369
26207
  TOKEN_HEADER_NAME,
26370
26208
  isPanelEditableKey,
26371
26209
  VIEW_SCHEMA,
26210
+ buildMessages,
26372
26211
  lastActive,
26373
26212
  statusCard,
26374
26213
  sessionTitle,
@@ -26377,11 +26216,6 @@ export {
26377
26216
  builtBy,
26378
26217
  embedViewModel,
26379
26218
  blame,
26380
- readProjectChanges,
26381
- readReadState,
26382
- setMessageRead,
26383
- attachChanges,
26384
- countBigUnread,
26385
26219
  buildFileHistory,
26386
26220
  modelSessions,
26387
26221
  loadEffectiveSessions,
@@ -26392,7 +26226,6 @@ export {
26392
26226
  show,
26393
26227
  formatShow,
26394
26228
  log,
26395
- logUnread,
26396
26229
  logFile,
26397
26230
  why,
26398
26231
  compareVersions,