codiedev 0.7.4 → 0.7.6
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.
- package/dist/__tests__/scope.test.d.ts +1 -0
- package/dist/__tests__/scope.test.js +24 -0
- package/dist/commands/push.js +5 -0
- package/dist/commands/reverseTicket.js +11 -32
- package/dist/scope.d.ts +8 -0
- package/dist/scope.js +15 -0
- package/dist/utils.js +16 -0
- package/package.json +6 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const scope_1 = require("../scope");
|
|
5
|
+
(0, vitest_1.describe)("formatScope", () => {
|
|
6
|
+
(0, vitest_1.it)("formats matched-repo case", () => {
|
|
7
|
+
(0, vitest_1.expect)((0, scope_1.formatScope)({
|
|
8
|
+
workspaceName: "Sonifi",
|
|
9
|
+
matchedRepo: { fullName: "Signal-and-Code/codiedev-ea" },
|
|
10
|
+
})).toBe("→ Sonifi (matched Signal-and-Code/codiedev-ea)");
|
|
11
|
+
});
|
|
12
|
+
(0, vitest_1.it)("formats no-match case", () => {
|
|
13
|
+
(0, vitest_1.expect)((0, scope_1.formatScope)({ workspaceName: "Sonifi", matchedRepo: null })).toBe("→ Sonifi (default profile, no repo match)");
|
|
14
|
+
});
|
|
15
|
+
(0, vitest_1.it)("handles unknown workspace gracefully", () => {
|
|
16
|
+
(0, vitest_1.expect)((0, scope_1.formatScope)({ workspaceName: "", matchedRepo: null })).toBe("→ unknown workspace");
|
|
17
|
+
});
|
|
18
|
+
(0, vitest_1.it)("handles unknown workspace with matched repo", () => {
|
|
19
|
+
(0, vitest_1.expect)((0, scope_1.formatScope)({
|
|
20
|
+
workspaceName: "",
|
|
21
|
+
matchedRepo: { fullName: "Foo/Bar" },
|
|
22
|
+
})).toBe("→ unknown workspace");
|
|
23
|
+
});
|
|
24
|
+
});
|
package/dist/commands/push.js
CHANGED
|
@@ -37,6 +37,8 @@ exports.runPush = runPush;
|
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
const shared_1 = require("./shared");
|
|
40
|
+
const utils_1 = require("../utils");
|
|
41
|
+
const scope_1 = require("../scope");
|
|
40
42
|
const VALID_TYPES = new Set([
|
|
41
43
|
"spec",
|
|
42
44
|
"bugfix",
|
|
@@ -110,6 +112,7 @@ async function runPush(args) {
|
|
|
110
112
|
process.exit(1);
|
|
111
113
|
}
|
|
112
114
|
const filename = path.basename(absolute);
|
|
115
|
+
const gitRemoteUrl = (0, utils_1.getGitRemoteUrl)(process.cwd()) ?? undefined;
|
|
113
116
|
try {
|
|
114
117
|
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/push", {
|
|
115
118
|
config,
|
|
@@ -120,8 +123,10 @@ async function runPush(args) {
|
|
|
120
123
|
kind,
|
|
121
124
|
tags: tags.length > 0 ? tags : undefined,
|
|
122
125
|
force,
|
|
126
|
+
gitRemoteUrl,
|
|
123
127
|
},
|
|
124
128
|
});
|
|
129
|
+
(0, scope_1.printScope)({ workspaceName: res.workspaceName, matchedRepo: res.matchedRepo });
|
|
125
130
|
const tagSummary = res.tags && res.tags.length > 0 ? ` tags=[${res.tags.join(", ")}]` : "";
|
|
126
131
|
console.log(`✓ Pushed ${filename} (kind=${res.kind}${tagSummary}).`);
|
|
127
132
|
console.log(` Visible under: ${res.destination}`);
|
|
@@ -36,7 +36,6 @@ function parseArgs(args) {
|
|
|
36
36
|
let base;
|
|
37
37
|
let forcedKey;
|
|
38
38
|
let noTruncate = false;
|
|
39
|
-
let dirty = false;
|
|
40
39
|
for (let i = 0; i < args.length; i++) {
|
|
41
40
|
const a = args[i];
|
|
42
41
|
if ((a === "--with" || a === "-w") && i + 1 < args.length) {
|
|
@@ -54,20 +53,17 @@ function parseArgs(args) {
|
|
|
54
53
|
else if (a === "--full") {
|
|
55
54
|
noTruncate = true;
|
|
56
55
|
}
|
|
57
|
-
else if (a === "--dirty") {
|
|
58
|
-
dirty = true;
|
|
59
|
-
}
|
|
60
56
|
else if (!a.startsWith("--") && !prUrl) {
|
|
61
57
|
prUrl = a;
|
|
62
58
|
}
|
|
63
59
|
}
|
|
64
|
-
return { prUrl, base, forcedKey, noTruncate
|
|
60
|
+
return { prUrl, base, forcedKey, noTruncate };
|
|
65
61
|
}
|
|
66
62
|
async function runReverseTicket(args) {
|
|
67
|
-
const { prUrl, base, forcedKey, noTruncate
|
|
63
|
+
const { prUrl, base, forcedKey, noTruncate } = parseArgs(args);
|
|
68
64
|
// No PR URL → branch mode (mid-session, no PR exists yet).
|
|
69
65
|
if (!prUrl) {
|
|
70
|
-
return runBranchMode({ explicitBase: base, forcedKey
|
|
66
|
+
return runBranchMode({ explicitBase: base, forcedKey });
|
|
71
67
|
}
|
|
72
68
|
const parsed = parsePrUrl(prUrl);
|
|
73
69
|
if (!parsed) {
|
|
@@ -241,38 +237,22 @@ async function runBranchMode(opts) {
|
|
|
241
237
|
}
|
|
242
238
|
};
|
|
243
239
|
const shQuote = (s) => `'${s.replace(/'/g, "'\\''")}'`;
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
|
|
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"}`);
|
|
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}`);
|
|
257
243
|
const trackedFiles = trackedRaw ? trackedRaw.split("\n").filter(Boolean) : [];
|
|
258
|
-
const untrackedRaw =
|
|
259
|
-
? safeGit(() => git("ls-files --others --exclude-standard"))
|
|
260
|
-
: undefined;
|
|
244
|
+
const untrackedRaw = safeGit(() => git("ls-files --others --exclude-standard"));
|
|
261
245
|
const untrackedFiles = untrackedRaw
|
|
262
246
|
? untrackedRaw.split("\n").filter(Boolean)
|
|
263
247
|
: [];
|
|
264
248
|
const filesChanged = Array.from(new Set([...trackedFiles, ...untrackedFiles]));
|
|
265
249
|
if (filesChanged.length === 0) {
|
|
266
|
-
|
|
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
|
-
}
|
|
250
|
+
console.error(`No changes detected between ${baseRef} and your working tree on ${branch}.`);
|
|
271
251
|
process.exit(1);
|
|
272
252
|
}
|
|
273
253
|
let stat = "";
|
|
274
254
|
try {
|
|
275
|
-
const trackedStat = git(`diff --stat=200 ${baseSha}
|
|
255
|
+
const trackedStat = git(`diff --stat=200 ${baseSha}`);
|
|
276
256
|
const untrackedStatLines = untrackedFiles.map((f) => {
|
|
277
257
|
const wc = shellTolerant(`wc -l < ${shQuote(f)}`);
|
|
278
258
|
const n = parseInt(wc.split(/\s+/)[0] || "0", 10) || 0;
|
|
@@ -289,10 +269,9 @@ async function runBranchMode(opts) {
|
|
|
289
269
|
let diff = "";
|
|
290
270
|
try {
|
|
291
271
|
const sourceTracked = trackedFiles.filter((f) => !isNoise(f));
|
|
292
|
-
const headRef = includeDirty ? "" : " HEAD";
|
|
293
272
|
const trackedDiff = sourceTracked.length > 0
|
|
294
|
-
? git(`diff ${baseSha}
|
|
295
|
-
: git(`diff ${baseSha}
|
|
273
|
+
? git(`diff ${baseSha} -- ${sourceTracked.map(shQuote).join(" ")}`)
|
|
274
|
+
: git(`diff ${baseSha}`);
|
|
296
275
|
const sourceUntracked = untrackedFiles.filter((f) => !isNoise(f));
|
|
297
276
|
const untrackedDiffs = sourceUntracked.map((f) => shellTolerant(`git diff --no-index --no-color -- /dev/null ${shQuote(f)}`));
|
|
298
277
|
diff = [trackedDiff, ...untrackedDiffs]
|
package/dist/scope.d.ts
ADDED
package/dist/scope.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatScope = formatScope;
|
|
4
|
+
exports.printScope = printScope;
|
|
5
|
+
function formatScope(info) {
|
|
6
|
+
if (!info.workspaceName)
|
|
7
|
+
return "→ unknown workspace";
|
|
8
|
+
if (info.matchedRepo) {
|
|
9
|
+
return `→ ${info.workspaceName} (matched ${info.matchedRepo.fullName})`;
|
|
10
|
+
}
|
|
11
|
+
return `→ ${info.workspaceName} (default profile, no repo match)`;
|
|
12
|
+
}
|
|
13
|
+
function printScope(info) {
|
|
14
|
+
console.log(formatScope(info));
|
|
15
|
+
}
|
package/dist/utils.js
CHANGED
|
@@ -330,6 +330,22 @@ asking the team who knows about X, proposing a change. Always pass an
|
|
|
330
330
|
\`link_share\` (fyi), or \`rfc\` (proposing a change). Attach a \`filename\`
|
|
331
331
|
to link a specific artifact and \`mentions\` to tag teammates.
|
|
332
332
|
|
|
333
|
+
**Default feed-post shape.** When the user explicitly says "push/share/post
|
|
334
|
+
to the feed", default to this shape unless they ask for something else:
|
|
335
|
+
- **Title** ≤10 words: *what + why now*. Imperative or declarative — never
|
|
336
|
+
"Check this out".
|
|
337
|
+
- **Body** — three short lines, grounded in the current session and the
|
|
338
|
+
artifact:
|
|
339
|
+
- **Why this exists** — 1–2 sentences from session context (the problem
|
|
340
|
+
or insight that produced the artifact).
|
|
341
|
+
- **What's in it** — 1 sentence pulled from the artifact's frontmatter
|
|
342
|
+
\`description:\` (skills) or first paragraph (specs). Don't restate
|
|
343
|
+
the whole file — the card preview carries the detail.
|
|
344
|
+
- **Ask** — 1 sentence. *Use it / review it / ping me with thoughts.*
|
|
345
|
+
- **Filename**: always attach so the card preview renders.
|
|
346
|
+
This is the default. If the user wants a one-liner or a different
|
|
347
|
+
structure, follow their lead.
|
|
348
|
+
|
|
333
349
|
**Search before pushing.** For any "save this as …" request, call
|
|
334
350
|
\`codiedev_search\` first with a relevant query. If prior art exists, pull
|
|
335
351
|
it and iterate rather than duplicating.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codiedev",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
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",
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "tsc",
|
|
11
11
|
"dev": "tsc --watch",
|
|
12
|
-
"prepublishOnly": "tsc"
|
|
12
|
+
"prepublishOnly": "tsc",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"test:watch": "vitest"
|
|
13
15
|
},
|
|
14
16
|
"files": [
|
|
15
17
|
"dist",
|
|
@@ -39,7 +41,8 @@
|
|
|
39
41
|
},
|
|
40
42
|
"devDependencies": {
|
|
41
43
|
"@types/node": "^20.0.0",
|
|
42
|
-
"typescript": "^5.4.0"
|
|
44
|
+
"typescript": "^5.4.0",
|
|
45
|
+
"vitest": "^3.2.4"
|
|
43
46
|
},
|
|
44
47
|
"dependencies": {
|
|
45
48
|
"@modelcontextprotocol/sdk": "^1.29.0"
|