codiedev 0.9.65 → 0.9.67

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.
@@ -15,6 +15,13 @@ export type CaptureSignals = {
15
15
  skill: string;
16
16
  count: number;
17
17
  }>;
18
+ /** Which skill ARTIFACT an invocation ran, when the loaded skill content
19
+ * carried a `codiedev:artifact=<id>` marker. Lets the server tell two
20
+ * authors' same-named skills apart. Absent when no marker was seen. */
21
+ skillInvocationArtifacts?: Array<{
22
+ skill: string;
23
+ artifactId: string;
24
+ }>;
18
25
  skillPulls: string[];
19
26
  toolCalls: Array<{
20
27
  name: string;
@@ -24,6 +24,17 @@ function parseCaptureSignals(content, source) {
24
24
  let parsedRecords = 0, truncated = false;
25
25
  let premiumRequests, nanoAiu;
26
26
  let cursorSubagents;
27
+ // The skill content a harness loads after an invocation follows it in the
28
+ // transcript; a marker there names the artifact the invocation ran.
29
+ const artifacts = new Map();
30
+ let lastInvoked = null;
31
+ const marker = (text) => {
32
+ if (!lastInvoked || artifacts.has(lastInvoked))
33
+ return;
34
+ const m = text.match(/codiedev:artifact=([a-z0-9]{16,64})/i);
35
+ if (m && artifacts.size < LIMIT)
36
+ artifacts.set(lastInvoked, m[1]);
37
+ };
27
38
  const addSkill = (set, value) => {
28
39
  const key = skillKey(value);
29
40
  if (!key || key.length > 200 || !/^[a-z0-9][a-z0-9_:/.-]*$/i.test(key))
@@ -33,8 +44,10 @@ function parseCaptureSignals(content, source) {
33
44
  return;
34
45
  }
35
46
  set.add(key);
36
- if (set === invocations)
47
+ if (set === invocations) {
37
48
  invocationCounts.set(key, (invocationCounts.get(key) ?? 0) + 1);
49
+ lastInvoked = key;
50
+ }
38
51
  };
39
52
  const command = (value) => {
40
53
  if (typeof value !== "string")
@@ -113,14 +126,19 @@ function parseCaptureSignals(content, source) {
113
126
  for (const part of blocks) {
114
127
  if (part?.type === "tool_use")
115
128
  tool(part.name, part.id, part.input);
129
+ if (part?.type === "tool_result")
130
+ marker(typeof part.content === "string" ? part.content : JSON.stringify(part.content ?? ""));
116
131
  if (part?.type === "text" && e.type === "user") {
117
132
  for (const match of String(part.text ?? "").matchAll(/<command-name>\/?([a-z0-9:_-]+)<\/command-name>/gi))
118
133
  addSkill(invocations, match[1]);
134
+ marker(String(part.text ?? ""));
119
135
  }
120
136
  }
121
- if (typeof blocks === "string" && e.type === "user")
137
+ if (typeof blocks === "string" && e.type === "user") {
122
138
  for (const match of blocks.matchAll(/<command-name>\/?([a-z0-9:_-]+)<\/command-name>/gi))
123
139
  addSkill(invocations, match[1]);
140
+ marker(blocks);
141
+ }
124
142
  if (e.type === "response_item" &&
125
143
  ["function_call", "custom_tool_call"].includes(e.payload?.type))
126
144
  tool(e.payload.name, e.payload.call_id, e.payload.arguments ?? e.payload.input);
@@ -150,6 +168,9 @@ function parseCaptureSignals(content, source) {
150
168
  skillInvocationCounts: [...invocationCounts]
151
169
  .map(([skill, count]) => ({ skill, count }))
152
170
  .sort((a, b) => a.skill.localeCompare(b.skill)),
171
+ ...(artifacts.size
172
+ ? { skillInvocationArtifacts: [...artifacts].map(([skill, artifactId]) => ({ skill, artifactId })).sort((a, b) => a.skill.localeCompare(b.skill)) }
173
+ : {}),
153
174
  skillPulls: [...pulls].sort(),
154
175
  toolCalls: [...tools]
155
176
  .map(([name, calls]) => ({ name, calls }))
package/dist/cli.d.ts CHANGED
@@ -10,7 +10,6 @@
10
10
  * codiedev inbox — list pings (use --unread to filter)
11
11
  * codiedev read <ping-id> — mark read + show full message
12
12
  * codiedev note "<text>" — capture a thought
13
- * codiedev promote <artifact-id> — promote an extracted artifact to authored
14
13
  * codiedev help — show this help
15
14
  */
16
15
  export {};
package/dist/cli.js CHANGED
@@ -11,7 +11,6 @@
11
11
  * codiedev inbox — list pings (use --unread to filter)
12
12
  * codiedev read <ping-id> — mark read + show full message
13
13
  * codiedev note "<text>" — capture a thought
14
- * codiedev promote <artifact-id> — promote an extracted artifact to authored
15
14
  * codiedev help — show this help
16
15
  */
17
16
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -23,15 +22,12 @@ const ask_1 = require("./commands/ask");
23
22
  const ping_1 = require("./commands/ping");
24
23
  const inbox_1 = require("./commands/inbox");
25
24
  const note_1 = require("./commands/note");
26
- const promote_1 = require("./commands/promote");
27
- const reverseTicket_1 = require("./commands/reverseTicket");
28
25
  const createTicket_1 = require("./commands/createTicket");
29
26
  const doctor_1 = require("./commands/doctor");
30
27
  const search_1 = require("./commands/search");
31
28
  const library_1 = require("./commands/library");
32
29
  const share_1 = require("./commands/share");
33
30
  const send_1 = require("./commands/send");
34
- const react_1 = require("./commands/react");
35
31
  const capture_1 = require("./commands/capture");
36
32
  const version_1 = require("./version");
37
33
  const HELP = `
@@ -64,14 +60,6 @@ Artifacts:
64
60
  team's collective memory. Returns an
65
61
  LLM-synthesized answer with citations
66
62
  pointing at sessions + artifacts.
67
- codiedev promote <artifact-id> Promote an auto-extracted artifact
68
- to an authored one
69
- codiedev reverse-ticket [<pr-url>] Generate a Jira ticket draft.
70
- No URL = branch mode (uses your current
71
- local git branch, no PR needed).
72
- Draft lands in /portal/agentic-ticketing.
73
- codiedev reverse-ticket --base <ref> Override the base ref in branch mode
74
- (defaults to origin/main).
75
63
  codiedev create-ticket [<prompt>] Forward-write a scoped ticket plan.
76
64
  Claude investigates the codebase, asks
77
65
  "single repo or multiple? where?", then
@@ -97,9 +85,6 @@ Discovery:
97
85
  [--type T] [--tag X] [--limit N]
98
86
  List artifacts in your workspace
99
87
 
100
- Feed:
101
- codiedev react <postId> <emoji> Toggle a reaction on a feed post
102
-
103
88
  Privacy:
104
89
  codiedev ignore <path> Never capture this folder or its children
105
90
  codiedev unignore <path> Stop ignoring a folder
@@ -270,20 +255,6 @@ codiedev note — capture a passing thought, linked to your session
270
255
  unignore: IGNORE_HELP,
271
256
  ignored: IGNORE_HELP,
272
257
  capture: IGNORE_HELP,
273
- promote: `
274
- codiedev promote — promote an auto-extracted artifact to authored
275
-
276
- Usage:
277
- codiedev promote <artifact-id> [--key filename.md]
278
-
279
- The session-capture pipeline auto-extracts spec/bugfix/decision
280
- artifacts from each agent session. Promote turns one of those into
281
- a first-class authored artifact your team can ping, pull, and
282
- update versions of.
283
-
284
- Find artifact-ids in the portal under Knowledge → Memory, or via
285
- the portal search.
286
- `.trim(),
287
258
  "create-ticket": `
288
259
  codiedev create-ticket — forward-write a scoped ticket plan
289
260
 
@@ -409,6 +380,18 @@ Run 'codiedev help <command>' for each, or see the quick list:
409
380
 
410
381
  Tokens are per-user. Rotate any time by revoking + creating a new one.
411
382
  `.trim();
383
+ // Retired commands: say so instead of "Unknown command", since agent
384
+ // instructions written by older installs may still reference them.
385
+ const REMOVED_COMMANDS = {
386
+ promote: "Share an auto-saved spec with 'Promote to team' in the portal's My artifacts list.",
387
+ "reverse-ticket": "Use 'codiedev create-ticket' to draft Jira tickets.",
388
+ reverseTicket: "Use 'codiedev create-ticket' to draft Jira tickets.",
389
+ react: "React to feed posts in the portal.",
390
+ };
391
+ function removedCommand(command) {
392
+ console.error(`'codiedev ${command}' has been removed. ${REMOVED_COMMANDS[command] ?? ""}`.trim());
393
+ process.exit(1);
394
+ }
412
395
  async function main() {
413
396
  const [, , command, ...rest] = process.argv;
414
397
  if (!command || command === "--help" || command === "-h") {
@@ -486,11 +469,10 @@ async function main() {
486
469
  await (0, note_1.runNote)(rest);
487
470
  return;
488
471
  case "promote":
489
- await (0, promote_1.runPromote)(rest);
490
- return;
491
472
  case "reverse-ticket":
492
473
  case "reverseTicket":
493
- await (0, reverseTicket_1.runReverseTicket)(rest);
474
+ case "react":
475
+ removedCommand(command);
494
476
  return;
495
477
  case "create-ticket":
496
478
  case "createTicket":
@@ -509,9 +491,6 @@ async function main() {
509
491
  case "send":
510
492
  await (0, send_1.runSend)(rest);
511
493
  return;
512
- case "react":
513
- await (0, react_1.runReact)(rest);
514
- return;
515
494
  case "ignore":
516
495
  case "unignore":
517
496
  case "ignored":
@@ -132,24 +132,6 @@ function hasCodiedevInstructions(instructionsPath) {
132
132
  return false;
133
133
  }
134
134
  }
135
- function hasGhCli() {
136
- try {
137
- (0, child_process_1.execSync)("gh --version", { stdio: ["pipe", "pipe", "pipe"] });
138
- return true;
139
- }
140
- catch {
141
- return false;
142
- }
143
- }
144
- function hasGlabCli() {
145
- try {
146
- (0, child_process_1.execSync)("glab --version", { stdio: ["pipe", "pipe", "pipe"] });
147
- return true;
148
- }
149
- catch {
150
- return false;
151
- }
152
- }
153
135
  async function runDoctor(_args) {
154
136
  const checks = [];
155
137
  console.log("\nCodiedev doctor — checking your setup…\n");
@@ -514,22 +496,6 @@ async function runDoctor(_args) {
514
496
  else {
515
497
  checks.push({ name: "GitHub Copilot", status: "warn", detail: "not installed on this machine" });
516
498
  }
517
- // 8. gh / glab CLIs (optional — only needed for reverse-ticket from a
518
- // specific PR/MR URL; branch mode works without either).
519
- checks.push({
520
- name: "GitHub CLI (`gh`) for reverse-ticket from a PR url",
521
- status: hasGhCli() ? "pass" : "warn",
522
- detail: hasGhCli()
523
- ? "installed"
524
- : "not installed — only needed for `codiedev reverse-ticket <github-pr-url>`",
525
- });
526
- checks.push({
527
- name: "GitLab CLI (`glab`) for reverse-ticket from an MR url",
528
- status: hasGlabCli() ? "pass" : "warn",
529
- detail: hasGlabCli()
530
- ? "installed"
531
- : "not installed — only needed for `codiedev reverse-ticket <gitlab-mr-url>`",
532
- });
533
499
  report(checks);
534
500
  const failures = checks.filter((c) => c.status === "fail");
535
501
  if (failures.length > 0) {
@@ -38,6 +38,7 @@ exports.runPull = runPull;
38
38
  const fs = __importStar(require("fs"));
39
39
  const path = __importStar(require("path"));
40
40
  const shared_1 = require("./shared");
41
+ const skillMarker_1 = require("../skillMarker");
41
42
  function parseArgs(args) {
42
43
  let key;
43
44
  let version;
@@ -104,6 +105,10 @@ async function runPull(args) {
104
105
  }
105
106
  }
106
107
  const a = res.artifact;
108
+ // A skill carries its identity onto disk so its runs attribute exactly
109
+ // (see skillMarker.ts). Docs are written verbatim.
110
+ const isSkill = a.kind ? a.kind === "skill" : (0, skillMarker_1.looksLikeSkill)(a.markdown);
111
+ const markdown = isSkill ? (0, skillMarker_1.stampSkillMarker)(a.markdown, a._id) : a.markdown;
107
112
  (0, shared_1.recordAgentEvent)(config, {
108
113
  tool: "codiedev_pull",
109
114
  ok: true,
@@ -111,7 +116,7 @@ async function runPull(args) {
111
116
  });
112
117
  if (out) {
113
118
  const absolute = path.isAbsolute(out) ? out : path.resolve(process.cwd(), out);
114
- fs.writeFileSync(absolute, a.markdown, "utf8");
119
+ fs.writeFileSync(absolute, markdown, "utf8");
115
120
  console.log(`✓ Pulled ${a.key} v${a.version ?? 1} (${a.type}) → ${absolute}`);
116
121
  console.log(` title: ${a.title}`);
117
122
  console.log(` lifecycle: ${a.lifecycle ?? "draft"}`);
@@ -119,8 +124,8 @@ async function runPull(args) {
119
124
  }
120
125
  else {
121
126
  // Stream to stdout — preserves shell pipes like `codiedev pull spec-214.md | less`.
122
- process.stdout.write(a.markdown);
123
- if (!a.markdown.endsWith("\n"))
127
+ process.stdout.write(markdown);
128
+ if (!markdown.endsWith("\n"))
124
129
  process.stdout.write("\n");
125
130
  }
126
131
  }
@@ -37,6 +37,7 @@ exports.parseArgs = parseArgs;
37
37
  exports.pushFile = pushFile;
38
38
  exports.runPush = runPush;
39
39
  const fs = __importStar(require("fs"));
40
+ const skillMarker_1 = require("../skillMarker");
40
41
  const path = __importStar(require("path"));
41
42
  const shared = __importStar(require("./shared"));
42
43
  const shared_1 = require("./shared");
@@ -120,7 +121,8 @@ function parseArgs(args) {
120
121
  return { file, type, kind, tags, force, as, private: priv };
121
122
  }
122
123
  async function pushFile(config, opts) {
123
- const markdown = fs.readFileSync(opts.absPath, "utf8");
124
+ // Never upload another artifact's identity marker (skillMarker.ts).
125
+ const markdown = (0, skillMarker_1.stripSkillMarker)(fs.readFileSync(opts.absPath, "utf8"));
124
126
  const gitRemoteUrl = (0, utils_1.getGitRemoteUrl)(process.cwd()) ?? undefined;
125
127
  return shared.apiRequest("POST", "/api/cli/push", {
126
128
  config,