airgen-cli 0.20.1 → 0.20.3

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.
@@ -199,8 +199,8 @@ export function registerRequirementCommands(program, client) {
199
199
  if (opts.section)
200
200
  body.sectionId = opts.section;
201
201
  if (opts.addTags || opts.removeTags) {
202
- // Read-modify-write for add/remove tags — use original ref for GET (resolvedId may be composite)
203
- const existing = await client.get(`/requirements/${tenant}/${project}/${encodeURIComponent(id)}`);
202
+ // Read-modify-write for add/remove tags
203
+ const existing = await client.get(`/requirements/${tenant}/${project}/${encodeURIComponent(resolvedId)}`);
204
204
  let currentTags = existing.record?.tags ?? [];
205
205
  if (opts.addTags) {
206
206
  const toAdd = opts.addTags.split(",").map(t => t.trim());
@@ -25,7 +25,7 @@ export function registerTraceabilityCommands(program, client) {
25
25
  if (opts.type)
26
26
  links = links.filter(l => l.linkType === opts.type);
27
27
  const total = links.length;
28
- if (opts.limit)
28
+ if (opts.limit && opts.limit.toLowerCase() !== "all")
29
29
  links = links.slice(0, parseInt(opts.limit, 10));
30
30
  if (isJsonMode()) {
31
31
  output({ data: links, meta: { totalItems: total, showing: links.length } });
@@ -211,6 +211,12 @@ export function registerTraceabilityCommands(program, client) {
211
211
  try {
212
212
  // Delete old link, create reversed
213
213
  await client.delete(`/trace-links/${tenant}/${project}/${link.id}`);
214
+ }
215
+ catch {
216
+ console.error(` Skipped: link ${link.id} not deletable (may be an embedded linkset link)`);
217
+ continue;
218
+ }
219
+ try {
214
220
  await client.post("/trace-links", {
215
221
  tenant, projectKey: project,
216
222
  sourceRequirementId: link.targetRequirementId,
@@ -222,7 +228,7 @@ export function registerTraceabilityCommands(program, client) {
222
228
  console.log(` Fixed: reversed to ${targetRef(link)} --${link.linkType}--> ${sourceRef(link)}`);
223
229
  }
224
230
  catch (err) {
225
- console.error(` Failed to fix: ${err.message}`);
231
+ console.error(` Delete succeeded but reverse create failed: ${err.message}`);
226
232
  }
227
233
  }
228
234
  }
package/dist/resolve.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  /**
2
- * Resolve any requirement identifier to its full ID.
2
+ * Resolve any requirement identifier to a ref suitable for API paths.
3
3
  *
4
- * Accepts: full ID, ref, short ID (REQ-XXX), or hashId.
5
- * Returns the full colon-separated ID (tenant:project:REQ-XXX).
4
+ * Accepts: full composite ID (tenant:project:REF), ref (STK-REQ-001),
5
+ * short ID, or hashId.
6
+ *
7
+ * Returns the ref string (e.g. STK-REQ-001) — NOT the full composite ID,
8
+ * since the API route already includes tenant and project in the path.
6
9
  */
7
10
  import type { AirgenClient } from "./client.js";
8
11
  export declare function resolveRequirementId(client: AirgenClient, tenant: string, project: string, identifier: string): Promise<string>;
package/dist/resolve.js CHANGED
@@ -1,19 +1,23 @@
1
1
  /**
2
- * Resolve any requirement identifier to its full ID.
2
+ * Resolve any requirement identifier to a ref suitable for API paths.
3
3
  *
4
- * Accepts: full ID, ref, short ID (REQ-XXX), or hashId.
5
- * Returns the full colon-separated ID (tenant:project:REQ-XXX).
4
+ * Accepts: full composite ID (tenant:project:REF), ref (STK-REQ-001),
5
+ * short ID, or hashId.
6
+ *
7
+ * Returns the ref string (e.g. STK-REQ-001) — NOT the full composite ID,
8
+ * since the API route already includes tenant and project in the path.
6
9
  */
7
10
  export async function resolveRequirementId(client, tenant, project, identifier) {
8
- // Already a full ID (contains colons)
11
+ // Full composite ID (tenant:project:REF) — extract the ref part
9
12
  if (identifier.includes(":")) {
10
- return identifier;
13
+ const parts = identifier.split(":");
14
+ return parts[parts.length - 1];
11
15
  }
12
16
  // Try as ref first (GET /requirements/{tenant}/{project}/{ref})
13
17
  try {
14
- const data = await client.get(`/requirements/${tenant}/${project}/${identifier}`);
15
- if (data.record?.id)
16
- return data.record.id;
18
+ const data = await client.get(`/requirements/${tenant}/${project}/${encodeURIComponent(identifier)}`);
19
+ if (data.record?.ref)
20
+ return data.record.ref;
17
21
  }
18
22
  catch {
19
23
  // Not found by ref — continue
@@ -27,10 +31,10 @@ export async function resolveRequirementId(client, tenant, project, identifier)
27
31
  for (const r of reqs) {
28
32
  // Match by short ID (the REQ-XXX part of tenant:project:REQ-XXX)
29
33
  if (r.id?.endsWith(`:${identifier}`))
30
- return r.id;
34
+ return r.ref ?? identifier;
31
35
  // Match by hashId
32
36
  if (r.hashId === identifier)
33
- return r.id;
37
+ return r.ref ?? identifier;
34
38
  }
35
39
  if (page >= (data.meta?.totalPages ?? 1))
36
40
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "airgen-cli",
3
- "version": "0.20.1",
3
+ "version": "0.20.3",
4
4
  "description": "AIRGen CLI — requirements engineering from the command line",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",