codiedev 0.7.3 → 0.7.4

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.
@@ -36,6 +36,7 @@ function parseArgs(args) {
36
36
  let base;
37
37
  let forcedKey;
38
38
  let noTruncate = false;
39
+ let dirty = false;
39
40
  for (let i = 0; i < args.length; i++) {
40
41
  const a = args[i];
41
42
  if ((a === "--with" || a === "-w") && i + 1 < args.length) {
@@ -53,17 +54,20 @@ function parseArgs(args) {
53
54
  else if (a === "--full") {
54
55
  noTruncate = true;
55
56
  }
57
+ else if (a === "--dirty") {
58
+ dirty = true;
59
+ }
56
60
  else if (!a.startsWith("--") && !prUrl) {
57
61
  prUrl = a;
58
62
  }
59
63
  }
60
- return { prUrl, base, forcedKey, noTruncate };
64
+ return { prUrl, base, forcedKey, noTruncate, dirty };
61
65
  }
62
66
  async function runReverseTicket(args) {
63
- const { prUrl, base, forcedKey, noTruncate } = parseArgs(args);
67
+ const { prUrl, base, forcedKey, noTruncate, dirty } = parseArgs(args);
64
68
  // No PR URL → branch mode (mid-session, no PR exists yet).
65
69
  if (!prUrl) {
66
- return runBranchMode({ explicitBase: base, forcedKey });
70
+ return runBranchMode({ explicitBase: base, forcedKey, dirty });
67
71
  }
68
72
  const parsed = parsePrUrl(prUrl);
69
73
  if (!parsed) {
@@ -237,22 +241,38 @@ async function runBranchMode(opts) {
237
241
  }
238
242
  };
239
243
  const shQuote = (s) => `'${s.replace(/'/g, "'\\''")}'`;
240
- // Capture all work relative to the base ref: committed + uncommitted-tracked
241
- // + new untracked. Matches "ticket my current changes" intent.
242
- const trackedRaw = git(`diff --name-only ${baseSha}`);
244
+ // Default scope is committed-only files and content reachable from HEAD,
245
+ // not from the working tree. Without `HEAD` as the second arg, `git diff
246
+ // <ref>` compares <ref> to the working tree, which silently rolls in
247
+ // uncommitted modifications and (via ls-files --others) untracked leftovers
248
+ // from prior branches. That produced audit-grade leaks where a one-commit
249
+ // copy-button branch generated a draft describing an unrelated auth rebrand
250
+ // that was sitting dirty in the working tree.
251
+ //
252
+ // --dirty re-enables the old behavior for the "ticket my current WIP"
253
+ // intent — explicit opt-in, since the user is asserting the dirty state is
254
+ // theirs and on-topic.
255
+ const includeDirty = opts.dirty === true;
256
+ const trackedRaw = git(`diff --name-only ${baseSha}${includeDirty ? "" : " HEAD"}`);
243
257
  const trackedFiles = trackedRaw ? trackedRaw.split("\n").filter(Boolean) : [];
244
- const untrackedRaw = safeGit(() => git("ls-files --others --exclude-standard"));
258
+ const untrackedRaw = includeDirty
259
+ ? safeGit(() => git("ls-files --others --exclude-standard"))
260
+ : undefined;
245
261
  const untrackedFiles = untrackedRaw
246
262
  ? untrackedRaw.split("\n").filter(Boolean)
247
263
  : [];
248
264
  const filesChanged = Array.from(new Set([...trackedFiles, ...untrackedFiles]));
249
265
  if (filesChanged.length === 0) {
250
- console.error(`No changes detected between ${baseRef} and your working tree on ${branch}.`);
266
+ const scope = includeDirty ? "your working tree" : "HEAD";
267
+ console.error(`No changes detected between ${baseRef} and ${scope} on ${branch}.`);
268
+ if (!includeDirty) {
269
+ console.error("Pass --dirty to also include uncommitted + untracked changes.");
270
+ }
251
271
  process.exit(1);
252
272
  }
253
273
  let stat = "";
254
274
  try {
255
- const trackedStat = git(`diff --stat=200 ${baseSha}`);
275
+ const trackedStat = git(`diff --stat=200 ${baseSha}${includeDirty ? "" : " HEAD"}`);
256
276
  const untrackedStatLines = untrackedFiles.map((f) => {
257
277
  const wc = shellTolerant(`wc -l < ${shQuote(f)}`);
258
278
  const n = parseInt(wc.split(/\s+/)[0] || "0", 10) || 0;
@@ -269,9 +289,10 @@ async function runBranchMode(opts) {
269
289
  let diff = "";
270
290
  try {
271
291
  const sourceTracked = trackedFiles.filter((f) => !isNoise(f));
292
+ const headRef = includeDirty ? "" : " HEAD";
272
293
  const trackedDiff = sourceTracked.length > 0
273
- ? git(`diff ${baseSha} -- ${sourceTracked.map(shQuote).join(" ")}`)
274
- : git(`diff ${baseSha}`);
294
+ ? git(`diff ${baseSha}${headRef} -- ${sourceTracked.map(shQuote).join(" ")}`)
295
+ : git(`diff ${baseSha}${headRef}`);
275
296
  const sourceUntracked = untrackedFiles.filter((f) => !isNoise(f));
276
297
  const untrackedDiffs = sourceUntracked.map((f) => shellTolerant(`git diff --no-index --no-color -- /dev/null ${shQuote(f)}`));
277
298
  diff = [trackedDiff, ...untrackedDiffs]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codiedev",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Connect Claude Code, Codex, Cursor, or VS Code Copilot to CodieDev for org-wide session capture and artifact collaboration",
5
5
  "bin": {
6
6
  "codiedev": "./dist/cli.js",