@floh-solutions/pharos-cli 0.12.0 → 0.14.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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +133 -14
- package/dist/cli.js.map +1 -1
- package/dist/commands/catalog.d.ts +72 -0
- package/dist/commands/catalog.d.ts.map +1 -0
- package/dist/commands/catalog.js +283 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/link.d.ts +2 -0
- package/dist/commands/link.d.ts.map +1 -1
- package/dist/commands/link.js +141 -2
- package/dist/commands/link.js.map +1 -1
- package/dist/commands/task.d.ts +13 -0
- package/dist/commands/task.d.ts.map +1 -1
- package/dist/commands/task.js +106 -4
- package/dist/commands/task.js.map +1 -1
- package/package.json +3 -3
- package/skill/SKILL.md +141 -2
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { isRevisedDateSentinel } from "@floh-solutions/ado-core";
|
|
2
|
+
import { emit, emitText, usageError } from "../output.js";
|
|
3
|
+
/**
|
|
4
|
+
* Fields that change on **every** revision and say nothing about the work.
|
|
5
|
+
*
|
|
6
|
+
* Azure DevOps rewrites these on any edit, so an unfiltered history is mostly
|
|
7
|
+
* `System.Rev 4 -> 5` and `System.AuthorizedDate` — the actual change buried
|
|
8
|
+
* among them. `--all` puts them back for anyone debugging the feed itself.
|
|
9
|
+
*
|
|
10
|
+
* `System.RevisedDate` is in here for a second reason worth knowing: on the
|
|
11
|
+
* CURRENT revision it is the sentinel `9999-01-01`, not a date. Printing it
|
|
12
|
+
* unfiltered makes the newest entry look like it was edited in the year 9999.
|
|
13
|
+
*/
|
|
14
|
+
const BOOKKEEPING = new Set([
|
|
15
|
+
"System.Rev",
|
|
16
|
+
"System.AuthorizedDate",
|
|
17
|
+
"System.RevisedDate",
|
|
18
|
+
"System.ChangedDate",
|
|
19
|
+
"System.AuthorizedAs",
|
|
20
|
+
"System.ChangedBy",
|
|
21
|
+
"System.Watermark",
|
|
22
|
+
"System.PersonId",
|
|
23
|
+
]);
|
|
24
|
+
/**
|
|
25
|
+
* `pharos history <id>` — what changed, when, and who did it.
|
|
26
|
+
*
|
|
27
|
+
* **`/updates`, not `/revisions`.** A revision is a full snapshot of the item
|
|
28
|
+
* at a point in time, so answering "what changed" from revisions means diffing
|
|
29
|
+
* them yourself, N times, client-side. `/updates` is the diff — Azure DevOps
|
|
30
|
+
* hands back `oldValue`/`newValue` per field per revision, which is the shape
|
|
31
|
+
* of the question actually being asked.
|
|
32
|
+
*/
|
|
33
|
+
export async function runHistory(io, session, positionals, options) {
|
|
34
|
+
const raw = positionals[0];
|
|
35
|
+
if (raw === undefined)
|
|
36
|
+
throw usageError("Which work item? `pharos history <id>`.");
|
|
37
|
+
if (!/^\d+$/.test(raw))
|
|
38
|
+
throw usageError(`"${raw}" is not a work item id.`, { given: raw });
|
|
39
|
+
const response = await session.client.http.request({
|
|
40
|
+
method: "GET",
|
|
41
|
+
path: `wit/workItems/${raw}/updates`,
|
|
42
|
+
scope: "project",
|
|
43
|
+
});
|
|
44
|
+
const updates = (response.value ?? [])
|
|
45
|
+
.map((update) => shapeUpdate(update, options.all))
|
|
46
|
+
// A revision that changed only bookkeeping is not a change anybody made.
|
|
47
|
+
.filter((entry) => entry.changes.length > 0 || entry.relationsAdded > 0 || entry.relationsRemoved > 0)
|
|
48
|
+
.reverse()
|
|
49
|
+
.slice(0, options.top);
|
|
50
|
+
const result = { id: Number(raw), revisions: updates.length, updates };
|
|
51
|
+
return session.pretty ? emitText(io, renderHistory(result)) : emit(io, result);
|
|
52
|
+
}
|
|
53
|
+
function shapeUpdate(update, all) {
|
|
54
|
+
const changes = [];
|
|
55
|
+
for (const [field, change] of Object.entries(update.fields ?? {})) {
|
|
56
|
+
if (!all && BOOKKEEPING.has(field))
|
|
57
|
+
continue;
|
|
58
|
+
changes.push({ field, from: change.oldValue ?? null, to: change.newValue ?? null });
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
rev: update.rev,
|
|
62
|
+
by: update.revisedBy?.displayName ?? null,
|
|
63
|
+
at: whenItHappened(update),
|
|
64
|
+
changes,
|
|
65
|
+
relationsAdded: update.relations?.added?.length ?? 0,
|
|
66
|
+
relationsRemoved: update.relations?.removed?.length ?? 0,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* When a revision actually happened — **not `revisedDate`, on the newest one.**
|
|
71
|
+
*
|
|
72
|
+
* On the CURRENT revision `System.RevisedDate` is the sentinel `9999-01-01`,
|
|
73
|
+
* because that revision has not been superseded yet. Printing it straight
|
|
74
|
+
* through dated the most recent change to the year 9999, which is what the
|
|
75
|
+
* first run of this command did.
|
|
76
|
+
*
|
|
77
|
+
* `System.ChangedDate` in the same update is the real moment, so it is the
|
|
78
|
+
* fallback. `isRevisedDateSentinel` is `ado-core`'s — the same check the mirror
|
|
79
|
+
* uses — rather than a second string comparison that could drift from it.
|
|
80
|
+
*/
|
|
81
|
+
function whenItHappened(update) {
|
|
82
|
+
const revised = update.revisedDate;
|
|
83
|
+
if (revised !== undefined && !isRevisedDateSentinel(revised))
|
|
84
|
+
return revised;
|
|
85
|
+
const changed = update.fields?.["System.ChangedDate"]?.newValue;
|
|
86
|
+
if (typeof changed === "string" && changed !== "")
|
|
87
|
+
return changed;
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
function renderHistory(result) {
|
|
91
|
+
const lines = [`#${result.id} — ${result.updates.length} change(s), newest first`];
|
|
92
|
+
for (const update of result.updates) {
|
|
93
|
+
lines.push("", `rev ${update.rev} · ${update.by ?? "someone"} · ${update.at ?? "?"}`);
|
|
94
|
+
for (const change of update.changes) {
|
|
95
|
+
lines.push(` ${change.field}: ${short(change.from)} -> ${short(change.to)}`);
|
|
96
|
+
}
|
|
97
|
+
if (update.relationsAdded > 0)
|
|
98
|
+
lines.push(` +${update.relationsAdded} relation(s)`);
|
|
99
|
+
if (update.relationsRemoved > 0)
|
|
100
|
+
lines.push(` -${update.relationsRemoved} relation(s)`);
|
|
101
|
+
}
|
|
102
|
+
return lines.join("\n");
|
|
103
|
+
}
|
|
104
|
+
/** A value, short enough to sit on one line of a change log. */
|
|
105
|
+
function short(value) {
|
|
106
|
+
if (value === null || value === undefined)
|
|
107
|
+
return "(none)";
|
|
108
|
+
if (typeof value === "object") {
|
|
109
|
+
const display = value.displayName;
|
|
110
|
+
if (typeof display === "string")
|
|
111
|
+
return display;
|
|
112
|
+
return JSON.stringify(value).slice(0, 60);
|
|
113
|
+
}
|
|
114
|
+
const text = String(value).replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim();
|
|
115
|
+
return text.length > 60 ? `${text.slice(0, 57)}…` : text;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* `pharos iterations` and `pharos areas`.
|
|
119
|
+
*
|
|
120
|
+
* **The dates are the reason this exists.** `query --sprint "Sprint 1"` could
|
|
121
|
+
* always FILTER by an iteration, but nothing could list them or say when one
|
|
122
|
+
* runs — so "which sprint are we in" and "how long is left" were unanswerable
|
|
123
|
+
* without the web UI. Both are attributes on the classification node and both
|
|
124
|
+
* come back here.
|
|
125
|
+
*
|
|
126
|
+
* ## Two spellings of the same sprint, and only one of them works
|
|
127
|
+
*
|
|
128
|
+
* A classification NODE path is `\Tibata\Iteration\Sprint 1`. The FIELD value
|
|
129
|
+
* on a work item is `Tibata\Sprint 1` — no `Iteration` segment. Passing the
|
|
130
|
+
* node path to `System.IterationPath` is a 400 that reads as though the sprint
|
|
131
|
+
* does not exist. Both are printed for exactly that reason: `path` is the node,
|
|
132
|
+
* `fieldPath` is what `--sprint` and `--field System.IterationPath=` take.
|
|
133
|
+
*/
|
|
134
|
+
export async function runClassification(io, session, kind, options) {
|
|
135
|
+
const root = await session.client.http.request({
|
|
136
|
+
method: "GET",
|
|
137
|
+
path: `wit/classificationnodes/${kind}`,
|
|
138
|
+
scope: "project",
|
|
139
|
+
query: { $depth: options.depth },
|
|
140
|
+
});
|
|
141
|
+
const flat = flatten(root, session.client.project ?? "");
|
|
142
|
+
const result = {
|
|
143
|
+
kind: kind.toLowerCase(),
|
|
144
|
+
count: flat.length,
|
|
145
|
+
[kind === "Iterations" ? "iterations" : "areas"]: flat,
|
|
146
|
+
};
|
|
147
|
+
return session.pretty ? emitText(io, renderNodes(flat)) : emit(io, result);
|
|
148
|
+
}
|
|
149
|
+
function flatten(root, project) {
|
|
150
|
+
const out = [];
|
|
151
|
+
const now = Date.now();
|
|
152
|
+
const walk = (node, depth) => {
|
|
153
|
+
const path = node.path ?? `\\${node.name}`;
|
|
154
|
+
const start = node.attributes?.startDate ?? null;
|
|
155
|
+
const finish = node.attributes?.finishDate ?? null;
|
|
156
|
+
out.push({
|
|
157
|
+
name: node.name,
|
|
158
|
+
path,
|
|
159
|
+
fieldPath: toFieldPath(path, project),
|
|
160
|
+
depth,
|
|
161
|
+
startDate: start,
|
|
162
|
+
finishDate: finish,
|
|
163
|
+
current: start === null || finish === null
|
|
164
|
+
? null
|
|
165
|
+
: Date.parse(start) <= now && now <= Date.parse(finish) + DAY,
|
|
166
|
+
});
|
|
167
|
+
for (const child of node.children ?? [])
|
|
168
|
+
walk(child, depth + 1);
|
|
169
|
+
};
|
|
170
|
+
walk(root, 0);
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
/** A finish date is a DAY, and the sprint is current until the end of it. */
|
|
174
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
175
|
+
/**
|
|
176
|
+
* `\Tibata\Iteration\Sprint 1` -> `Tibata\Sprint 1`.
|
|
177
|
+
*
|
|
178
|
+
* Drops the leading slash and the `Iteration`/`Area` segment that only the
|
|
179
|
+
* classification tree uses. See ``runClassification`` for why this matters.
|
|
180
|
+
*/
|
|
181
|
+
function toFieldPath(nodePath, project) {
|
|
182
|
+
const parts = nodePath.replace(/^\\/, "").split("\\");
|
|
183
|
+
const filtered = parts.filter((part, index) => !(index === 1 && (part === "Iteration" || part === "Area")));
|
|
184
|
+
return filtered.length > 0 ? filtered.join("\\") : project;
|
|
185
|
+
}
|
|
186
|
+
function renderNodes(nodes) {
|
|
187
|
+
return nodes
|
|
188
|
+
.map((node) => {
|
|
189
|
+
const dates = node.startDate === null
|
|
190
|
+
? ""
|
|
191
|
+
: ` ${node.startDate.slice(0, 10)} → ${(node.finishDate ?? "").slice(0, 10)}`;
|
|
192
|
+
const current = node.current === true ? " ← current" : "";
|
|
193
|
+
return `${" ".repeat(node.depth)}${node.name}${dates}${current}`;
|
|
194
|
+
})
|
|
195
|
+
.join("\n");
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* `pharos links` — every relation type this organisation actually has.
|
|
199
|
+
*
|
|
200
|
+
* **`link` knows six; this org has eighteen.** The six are the ones worth a
|
|
201
|
+
* named flag, and they are not the whole vocabulary — measured on the live org:
|
|
202
|
+
* 21 relation types, 18 of them work item links, so twelve are unreachable by
|
|
203
|
+
* flag including `Affects`, `TestedBy`, the whole `Remote.*` family, and
|
|
204
|
+
* `Duplicate-Reverse` (an outright asymmetry, since `Duplicate-Forward` has a
|
|
205
|
+
* flag). Without this verb there was no way to find that out from the shell.
|
|
206
|
+
*
|
|
207
|
+
* The output marks which ones `link`/`unlink` can reach, so the answer to "can
|
|
208
|
+
* I make this link" is in the same reply as "does this link exist".
|
|
209
|
+
*/
|
|
210
|
+
export async function runLinkTypes(io, session) {
|
|
211
|
+
const response = await session.client.http.request({
|
|
212
|
+
method: "GET",
|
|
213
|
+
path: "wit/workitemrelationtypes",
|
|
214
|
+
scope: "org",
|
|
215
|
+
});
|
|
216
|
+
const { LINK_KINDS } = await import("./link.js");
|
|
217
|
+
const byRel = new Map(Object.entries(LINK_KINDS).map(([flag, kind]) => [kind.rel, flag]));
|
|
218
|
+
const types = (response.value ?? []).map((type) => ({
|
|
219
|
+
referenceName: type.referenceName,
|
|
220
|
+
name: type.name,
|
|
221
|
+
usage: type.attributes?.["usage"] ?? null,
|
|
222
|
+
/** The `--flag` that reaches it, or `null` when only the API can. */
|
|
223
|
+
flag: byRel.get(type.referenceName) ?? null,
|
|
224
|
+
}));
|
|
225
|
+
const result = {
|
|
226
|
+
count: types.length,
|
|
227
|
+
reachableByFlag: types.filter((type) => type.flag !== null).length,
|
|
228
|
+
types,
|
|
229
|
+
};
|
|
230
|
+
return session.pretty
|
|
231
|
+
? emitText(io, types
|
|
232
|
+
.map((type) => `${(type.flag === null ? "" : `--${type.flag}`).padEnd(14)}${type.referenceName}`)
|
|
233
|
+
.join("\n"))
|
|
234
|
+
: emit(io, result);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* `pharos fields [--type <T>]` — what a field will actually accept.
|
|
238
|
+
*
|
|
239
|
+
* **`types` answers this for STATE and for nothing else.** Priority's range and
|
|
240
|
+
* Activity's option list are process configuration, not constants — which is
|
|
241
|
+
* why the macOS app fetches them rather than hardcoding them — and from the
|
|
242
|
+
* shell the only way to discover one was to send a value and read the failure.
|
|
243
|
+
*
|
|
244
|
+
* `--type` is strongly recommended: a field's allowed values belong to the TYPE,
|
|
245
|
+
* not the project. `Activity` exists on `Task` and on neither `Epic` nor
|
|
246
|
+
* `Issue` in the Basic process, so "which fields are there" has no
|
|
247
|
+
* project-wide answer.
|
|
248
|
+
*/
|
|
249
|
+
export async function runFields(io, session, options) {
|
|
250
|
+
const path = options.type === undefined
|
|
251
|
+
? "wit/fields"
|
|
252
|
+
: `wit/workitemtypes/${encodeURIComponent(options.type)}/fields`;
|
|
253
|
+
const response = await session.client.http.request({
|
|
254
|
+
method: "GET",
|
|
255
|
+
path,
|
|
256
|
+
scope: "project",
|
|
257
|
+
query: options.type === undefined ? {} : { $expand: "allowedValues" },
|
|
258
|
+
});
|
|
259
|
+
let fields = (response.value ?? []).map((field) => ({
|
|
260
|
+
referenceName: field.referenceName,
|
|
261
|
+
name: field.name,
|
|
262
|
+
type: field.type ?? null,
|
|
263
|
+
readOnly: field.readOnly ?? false,
|
|
264
|
+
required: field.alwaysRequired ?? false,
|
|
265
|
+
allowedValues: field.allowedValues ?? [],
|
|
266
|
+
helpText: field.helpText ?? null,
|
|
267
|
+
}));
|
|
268
|
+
if (options.constrained) {
|
|
269
|
+
fields = fields.filter((field) => field.allowedValues.length > 0);
|
|
270
|
+
}
|
|
271
|
+
const result = { type: options.type ?? null, count: fields.length, fields };
|
|
272
|
+
return session.pretty
|
|
273
|
+
? emitText(io, fields
|
|
274
|
+
.map((field) => {
|
|
275
|
+
const values = field.allowedValues.length === 0
|
|
276
|
+
? ""
|
|
277
|
+
: ` [${field.allowedValues.map(String).join(", ")}]`;
|
|
278
|
+
return `${field.referenceName.padEnd(46)}${field.type ?? ""}${values}`;
|
|
279
|
+
})
|
|
280
|
+
.join("\n"))
|
|
281
|
+
: emit(io, result);
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/link.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ export declare const LINK_KINDS: Record<string, {
|
|
|
33
33
|
}>;
|
|
34
34
|
export interface LinkCommandOptions {
|
|
35
35
|
kinds: Record<string, number | undefined>;
|
|
36
|
+
/** A wiki page path — the one link target that is not a work item. */
|
|
37
|
+
wiki: string | undefined;
|
|
36
38
|
comment: string | undefined;
|
|
37
39
|
}
|
|
38
40
|
export declare function runLink(io: Io, session: Session, positionals: readonly string[], options: LinkCommandOptions): Promise<ExitCode>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"AAUA,OAAO,EAAuC,KAAK,QAAQ,EAAE,KAAK,EAAE,EAAE,MAAM,cAAc,CAAC;AAC3F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAOzE,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC1C,sEAAsE;IACtE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAqED,wBAAsB,OAAO,CAC3B,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,QAAQ,CAAC,CA8DnB;AAsDD,wBAAsB,SAAS,CAC7B,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,QAAQ,CAAC,CAoCnB"}
|
package/dist/commands/link.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RelationNotFoundError, addRelation, removeRelationPatch, } from "@floh-solutions/ado-core";
|
|
1
|
+
import { RelationNotFoundError, addRelation, addWikiPageLink, removeRelationPatch, wikiPageArtifactUri, } from "@floh-solutions/ado-core";
|
|
2
2
|
import { emit, emitText, refusal, usageError } from "../output.js";
|
|
3
3
|
/**
|
|
4
4
|
* `pharos link` and `pharos unlink` — the relations between work items.
|
|
@@ -35,6 +35,42 @@ export const LINK_KINDS = {
|
|
|
35
35
|
successor: { rel: "System.LinkTypes.Dependency-Forward", describes: "a successor of" },
|
|
36
36
|
duplicate: { rel: "System.LinkTypes.Duplicate-Forward", describes: "a duplicate of" },
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* `--wiki <path>` — attach a wiki page to a work item as an **artifact link**.
|
|
40
|
+
*
|
|
41
|
+
* **This closes a circle that was open, and it is the gap that mattered most.**
|
|
42
|
+
* `pharos task` reads linked wiki pages and their discussion — that is the
|
|
43
|
+
* command's headline, *"the plan a colleague wrote is usually on a linked wiki
|
|
44
|
+
* page rather than in the description"* — and until now nothing in this CLI
|
|
45
|
+
* could MAKE that link. The skill's own loop said to: *"write it: `pharos wiki
|
|
46
|
+
* write /Plans/<name> --stdin`, then link it to the epic so the next person
|
|
47
|
+
* finds it the same way you did."* An agent following that instruction hit a
|
|
48
|
+
* wall the documentation did not mention, and the link had to be made in the
|
|
49
|
+
* web UI or the macOS app.
|
|
50
|
+
*
|
|
51
|
+
* Everything needed already existed — `addWikiPageLink`, `wikiPageArtifactUri`
|
|
52
|
+
* and `parseWikiPageArtifactUri` in `ado-core`, and `session.wikiForLinking()`
|
|
53
|
+
* here. Only the verb was missing.
|
|
54
|
+
*
|
|
55
|
+
* ## The URI is the identity, and it is not a URL
|
|
56
|
+
*
|
|
57
|
+
* A wiki artifact link is `vstfs:///Wiki/WikiPage/<project>%2F<wiki>%2F<path>`
|
|
58
|
+
* — the page's PATH, encoded, with no id anywhere. That has one consequence
|
|
59
|
+
* worth stating out loud: **moving or renaming a page silently breaks every
|
|
60
|
+
* link to it**, because the path was the identity. `wiki move` and `wiki
|
|
61
|
+
* rename` already require `--yes` for exactly this reason.
|
|
62
|
+
*/
|
|
63
|
+
async function wikiTarget(session, path) {
|
|
64
|
+
const normalised = path.startsWith("/") ? path : `/${path}`;
|
|
65
|
+
const wiki = await session.wikiForLinking();
|
|
66
|
+
return {
|
|
67
|
+
uri: wikiPageArtifactUri(wiki.projectId, wiki.wikiId, normalised),
|
|
68
|
+
name: wiki.name,
|
|
69
|
+
path: normalised,
|
|
70
|
+
projectId: wiki.projectId,
|
|
71
|
+
wikiId: wiki.wikiId,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
38
74
|
/** Exactly one link kind, or a refusal that lists them. */
|
|
39
75
|
function soleKind(kinds) {
|
|
40
76
|
const given = Object.entries(kinds).filter(([, id]) => id !== undefined);
|
|
@@ -60,6 +96,9 @@ function id(raw, usage) {
|
|
|
60
96
|
}
|
|
61
97
|
export async function runLink(io, session, positionals, options) {
|
|
62
98
|
const from = id(positionals[0], "Which work item? `pharos link <id> --parent <id>`.");
|
|
99
|
+
if (options.wiki !== undefined) {
|
|
100
|
+
return linkWikiPage(io, session, from, options);
|
|
101
|
+
}
|
|
63
102
|
const { flag, target } = soleKind(options.kinds);
|
|
64
103
|
const kind = LINK_KINDS[flag];
|
|
65
104
|
if (target === from) {
|
|
@@ -99,8 +138,48 @@ export async function runLink(io, session, positionals, options) {
|
|
|
99
138
|
title: titleOf(to),
|
|
100
139
|
});
|
|
101
140
|
}
|
|
141
|
+
/** `pharos link <id> --wiki <path>` — see ``wikiTarget``. */
|
|
142
|
+
async function linkWikiPage(io, session, from, options) {
|
|
143
|
+
const target = await wikiTarget(session, options.wiki);
|
|
144
|
+
const item = await session.client.workItems.get(from, { expand: "relations" });
|
|
145
|
+
// Same identity rule the work item path uses: the artifact URI IS the
|
|
146
|
+
// identity, so an exact match is "already linked" and not a second link.
|
|
147
|
+
const existing = relationsOf(item).find((relation) => relation.url === target.uri);
|
|
148
|
+
if (existing !== undefined) {
|
|
149
|
+
return report(io, session, {
|
|
150
|
+
applied: false,
|
|
151
|
+
unchanged: true,
|
|
152
|
+
from,
|
|
153
|
+
wiki: target.name,
|
|
154
|
+
page: target.path,
|
|
155
|
+
relationship: "wiki",
|
|
156
|
+
message: `${target.path} is already linked to #${from}.`,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
if (session.previewOnly) {
|
|
160
|
+
return report(io, session, {
|
|
161
|
+
applied: false,
|
|
162
|
+
dryRun: true,
|
|
163
|
+
from,
|
|
164
|
+
wiki: target.name,
|
|
165
|
+
page: target.path,
|
|
166
|
+
relationship: "wiki",
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
await session.client.workItems.updateWithRev(from, item.rev, [addWikiPageLink(target.projectId, target.wikiId, target.path, options.comment)], { suppressNotifications: true });
|
|
170
|
+
return report(io, session, {
|
|
171
|
+
applied: true,
|
|
172
|
+
from,
|
|
173
|
+
wiki: target.name,
|
|
174
|
+
page: target.path,
|
|
175
|
+
relationship: "wiki",
|
|
176
|
+
});
|
|
177
|
+
}
|
|
102
178
|
export async function runUnlink(io, session, positionals, options) {
|
|
103
179
|
const from = id(positionals[0], "Which work item? `pharos unlink <id> --parent <id>`.");
|
|
180
|
+
if (options.wiki !== undefined) {
|
|
181
|
+
return unlinkWikiPage(io, session, from, options);
|
|
182
|
+
}
|
|
104
183
|
const { flag, target } = soleKind(options.kinds);
|
|
105
184
|
const kind = LINK_KINDS[flag];
|
|
106
185
|
const item = await session.client.workItems.get(from, { expand: "relations" });
|
|
@@ -127,6 +206,52 @@ export async function runUnlink(io, session, positionals, options) {
|
|
|
127
206
|
await session.client.workItems.update(from, ops, { suppressNotifications: true });
|
|
128
207
|
return report(io, session, { applied: true, removed: true, from, to: target, relationship: flag });
|
|
129
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* `pharos unlink <id> --wiki <path>`.
|
|
211
|
+
*
|
|
212
|
+
* Removed as a **resource** target rather than a work item one — the artifact
|
|
213
|
+
* URI is matched exactly, which is what `RelationTarget`'s `resource` kind is
|
|
214
|
+
* for. Same `test`-on-`/rev` guard as every other removal here, for the same
|
|
215
|
+
* reason: Azure DevOps removes by POSITION, so a stale index cuts a different
|
|
216
|
+
* link and still returns 200.
|
|
217
|
+
*/
|
|
218
|
+
async function unlinkWikiPage(io, session, from, options) {
|
|
219
|
+
const target = await wikiTarget(session, options.wiki);
|
|
220
|
+
const item = await session.client.workItems.get(from, { expand: "relations" });
|
|
221
|
+
let ops;
|
|
222
|
+
try {
|
|
223
|
+
ops = removeRelationPatch(relationsOf(item), item.rev, {
|
|
224
|
+
kind: "resource",
|
|
225
|
+
url: target.uri,
|
|
226
|
+
rel: "ArtifactLink",
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
if (error instanceof RelationNotFoundError) {
|
|
231
|
+
throw refusal(`${target.path} is not linked to #${from}.`, { from, page: target.path, wiki: target.name, relationship: "wiki" });
|
|
232
|
+
}
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
if (session.previewOnly) {
|
|
236
|
+
return report(io, session, {
|
|
237
|
+
applied: false,
|
|
238
|
+
dryRun: true,
|
|
239
|
+
from,
|
|
240
|
+
wiki: target.name,
|
|
241
|
+
page: target.path,
|
|
242
|
+
relationship: "wiki",
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
await session.client.workItems.update(from, ops, { suppressNotifications: true });
|
|
246
|
+
return report(io, session, {
|
|
247
|
+
applied: true,
|
|
248
|
+
removed: true,
|
|
249
|
+
from,
|
|
250
|
+
wiki: target.name,
|
|
251
|
+
page: target.path,
|
|
252
|
+
relationship: "wiki",
|
|
253
|
+
});
|
|
254
|
+
}
|
|
130
255
|
function relationsOf(item) {
|
|
131
256
|
const relations = item.relations;
|
|
132
257
|
return relations ?? [];
|
|
@@ -143,8 +268,22 @@ function report(io, session, result) {
|
|
|
143
268
|
// is the kind of line that makes somebody doubt what actually happened.
|
|
144
269
|
if (typeof result["message"] === "string")
|
|
145
270
|
return emitText(io, result["message"]);
|
|
146
|
-
const describes = LINK_KINDS[result.relationship]?.describes ?? result.relationship;
|
|
147
271
|
const verb = result["removed"] === true ? "no longer" : result.applied ? "now" : "would be";
|
|
272
|
+
// A wiki page has no id to print, and `LINK_KINDS` has no entry for it — the
|
|
273
|
+
// work item sentence would read "#undefined is now wiki #39".
|
|
274
|
+
//
|
|
275
|
+
// It also needs its own verb rather than the table's. "is" + "would be" reads
|
|
276
|
+
// "is would be linked", which is exactly the sort of line that makes somebody
|
|
277
|
+
// doubt whether the write happened.
|
|
278
|
+
if (result.relationship === "wiki") {
|
|
279
|
+
const wikiVerb = result["removed"] === true
|
|
280
|
+
? "is no longer"
|
|
281
|
+
: result.applied
|
|
282
|
+
? "is now"
|
|
283
|
+
: "would be";
|
|
284
|
+
return emitText(io, `${String(result["page"])} ${wikiVerb} linked to #${result.from}`);
|
|
285
|
+
}
|
|
286
|
+
const describes = LINK_KINDS[result.relationship]?.describes ?? result.relationship;
|
|
148
287
|
return emitText(io, `#${result.to} is ${verb} ${describes} #${result.from}`);
|
|
149
288
|
}
|
|
150
289
|
//# sourceMappingURL=link.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,mBAAmB,GAGpB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAA0B,MAAM,cAAc,CAAC;AAG3F;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAuD;IAC5E,MAAM,EAAE,EAAE,GAAG,EAAE,oCAAoC,EAAE,SAAS,EAAE,eAAe,EAAE;IACjF,KAAK,EAAE,EAAE,GAAG,EAAE,oCAAoC,EAAE,SAAS,EAAE,YAAY,EAAE;IAC7E,OAAO,EAAE,EAAE,GAAG,EAAE,0BAA0B,EAAE,SAAS,EAAE,YAAY,EAAE;IACrE,WAAW,EAAE,EAAE,GAAG,EAAE,qCAAqC,EAAE,SAAS,EAAE,kBAAkB,EAAE;IAC1F,SAAS,EAAE,EAAE,GAAG,EAAE,qCAAqC,EAAE,SAAS,EAAE,gBAAgB,EAAE;IACtF,SAAS,EAAE,EAAE,GAAG,EAAE,oCAAoC,EAAE,SAAS,EAAE,gBAAgB,EAAE;CACtF,CAAC;
|
|
1
|
+
{"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/task.d.ts
CHANGED
|
@@ -18,6 +18,19 @@ export interface TaskOptions {
|
|
|
18
18
|
wikiContent: boolean;
|
|
19
19
|
wikiComments: boolean;
|
|
20
20
|
relatedTitles: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* How many generations of children to fetch as well. `0` is this item alone,
|
|
23
|
+
* which is the default and what every earlier version did.
|
|
24
|
+
*
|
|
25
|
+
* **Why this exists.** The header above claims `task` is one call, and for a
|
|
26
|
+
* leaf it is. For an EPIC it was one call plus one per child: measured on
|
|
27
|
+
* Epic #39, nine calls and ~38 KB to answer one question about one epic. The
|
|
28
|
+
* `related[]` array already names the children, so an agent knew *what* they
|
|
29
|
+
* were — and still had to fetch each one to know what any of them SAID.
|
|
30
|
+
*/
|
|
31
|
+
depth: number;
|
|
32
|
+
/** Flatten identities and drop board-extension noise — see ``compact``. */
|
|
33
|
+
compact: boolean;
|
|
21
34
|
}
|
|
22
35
|
export declare function runTask(io: Io, session: Session, positionals: readonly string[], options: TaskOptions): Promise<ExitCode>;
|
|
23
36
|
//# sourceMappingURL=task.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8B,KAAK,QAAQ,EAAE,KAAK,EAAE,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8B,KAAK,QAAQ,EAAE,KAAK,EAAE,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB;;;;;;;;;OASG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;CAClB;AAeD,wBAAsB,OAAO,CAC3B,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,QAAQ,CAAC,CAkBnB"}
|