@floh-solutions/pharos-cli 0.24.0 → 0.26.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/README.md +97 -10
- package/dist/adopt-type.d.ts +58 -0
- package/dist/adopt-type.d.ts.map +1 -0
- package/dist/adopt-type.js +61 -0
- package/dist/adopt-type.js.map +1 -0
- package/dist/bridge.d.ts +156 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +157 -0
- package/dist/bridge.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +176 -31
- package/dist/cli.js.map +1 -1
- package/dist/commands/bridge.d.ts +30 -0
- package/dist/commands/bridge.d.ts.map +1 -0
- package/dist/commands/bridge.js +255 -0
- package/dist/commands/bridge.js.map +1 -0
- package/dist/commands/comment-github.d.ts +138 -0
- package/dist/commands/comment-github.d.ts.map +1 -0
- package/dist/commands/comment-github.js +427 -0
- package/dist/commands/comment-github.js.map +1 -0
- package/dist/commands/comment.d.ts.map +1 -1
- package/dist/commands/comment.js +114 -19
- package/dist/commands/comment.js.map +1 -1
- package/dist/commands/doctor.d.ts +169 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +241 -44
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/issue.d.ts +133 -0
- package/dist/commands/issue.d.ts.map +1 -1
- package/dist/commands/issue.js +292 -110
- package/dist/commands/issue.js.map +1 -1
- package/dist/commands/setup.d.ts +45 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +74 -0
- package/dist/commands/setup.js.map +1 -1
- package/dist/half-link.d.ts +14 -4
- package/dist/half-link.d.ts.map +1 -1
- package/dist/half-link.js +14 -4
- package/dist/half-link.js.map +1 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +123 -1
- package/dist/output.js.map +1 -1
- package/dist/session.d.ts +51 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +62 -11
- package/dist/session.js.map +1 -1
- package/dist/target.d.ts +40 -4
- package/dist/target.d.ts.map +1 -1
- package/dist/target.js +14 -3
- package/dist/target.js.map +1 -1
- package/package.json +4 -4
- package/skill/SKILL.md +167 -7
package/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pharos
|
|
3
|
-
description: "Use for AZURE DEVOPS work — when the user says Azure DevOps, ADO or dev.azure.com, or names an ADO work item by number (\"pick up 4821\", \"what's on 210\"). Covers reading or updating an ADO work item, ticket, bug, story or epic; the ADO board, backlog, sprint or iteration; what is assigned to you
|
|
3
|
+
description: "Use for AZURE DEVOPS work — when the user says Azure DevOps, ADO or dev.azure.com, or names an ADO work item by number (\"pick up 4821\", \"what's on 210\"). Covers reading or updating an ADO work item, ticket, bug, story or epic; the ADO board, backlog, sprint or iteration; what is assigned to you; reading or writing an ADO wiki page and its comments; linking a plan to an epic; attaching a file to a work item or taking one off; inline images in a field or wiki page; @mentioning somebody so they are notified; importing Markdown, Word or PDF as wiki pages; and whether a failed call is retryable. ALSO the GITHUB ISSUE ↔ work item EDGE: adopting an issue as a work item linked at both ends, bulk-adopting a repo, one reply reaching reporter and board, where they have drifted, closing both ends together, and changing a comment that ALREADY EXISTS: editing, deleting, reacting, hiding, pinning. NOT a GitHub CLI: listing or viewing an issue, or POSTING a comment, is `gh`'s job. NOT for other trackers — Argus, Jira, Linear."
|
|
4
4
|
license: Proprietary
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -59,8 +59,16 @@ wiki image <file> a picture for a PAGE or page comment. Different
|
|
|
59
59
|
wiki import <file...> .md .txt .docx .pdf .rtf .html -> pages. A
|
|
60
60
|
.pptx is refused, on purpose — see below
|
|
61
61
|
--under <path> --as <name>
|
|
62
|
-
comment list | add | edit | delete <target> is a work item id
|
|
63
|
-
comment react | unreact | reactors
|
|
62
|
+
comment list | add | edit | delete <target> is a work item id, a wiki path,
|
|
63
|
+
comment react | unreact | reactors OR a GitHub issue (contoso/widgets#45)
|
|
64
|
+
comment hide | unhide | pin | unpin GITHUB ONLY — Azure DevOps has neither
|
|
65
|
+
REACTIONS ARE NOT ONE VOCABULARY. Azure DevOps:
|
|
66
|
+
like dislike heart hooray smile confused. GitHub:
|
|
67
|
+
thumbs-up thumbs-down laugh hooray confused heart
|
|
68
|
+
rocket eyes. Passing one platform's name to the
|
|
69
|
+
other is refused, not translated
|
|
70
|
+
`comment add` is REFUSED on a GitHub issue — see
|
|
71
|
+
"Editing a GitHub comment" below
|
|
64
72
|
issue adopt <owner/name#45> a GitHub ISSUE becomes a work item, with BOTH
|
|
65
73
|
ends of the link written. --type --title --parent
|
|
66
74
|
issue link <owner/name#45> <id> join an existing pair — or finish a join that
|
|
@@ -76,6 +84,11 @@ issue backfill <owner/name> bulk adopt every issue the board does not link
|
|
|
76
84
|
yet. Needs --yes. --limit --state --label
|
|
77
85
|
issue close <id|owner/name#45> close BOTH ends, then RE-READ both to say what
|
|
78
86
|
actually moved. --to --reason --all
|
|
87
|
+
issue edit <owner/name#45> the issue's OWN fields, behind a lost-update
|
|
88
|
+
guard. Needs --yes. --title --text/--file/--stdin
|
|
89
|
+
--milestone --add-label --remove-label
|
|
90
|
+
--add-assignee --remove-assignee --if-title
|
|
91
|
+
--if-body. `gh issue edit` is the UNGUARDED one
|
|
79
92
|
hooks list | check | create | repoint | delete service hooks for realtime.
|
|
80
93
|
`check` needs --hub <url>; `list` shows the URL
|
|
81
94
|
already in use
|
|
@@ -87,6 +100,14 @@ setup org, project, token → keychain + shell profile
|
|
|
87
100
|
--repo owner/name --gh-account <login> bind a
|
|
88
101
|
repository to the GitHub account that reaches
|
|
89
102
|
it. BOTH or NEITHER — `issue` needs this first
|
|
103
|
+
bridge show|labels what an adopted issue BECOMES: which work item
|
|
104
|
+
type each GitHub label maps to. `labels --repo
|
|
105
|
+
owner/name` shows what is mapped, what an
|
|
106
|
+
unmapped one would default to, and which of
|
|
107
|
+
those it is
|
|
108
|
+
bridge map|unmap|digest edit that mapping (--label is an ID, not a name
|
|
109
|
+
— ids survive a rename), and when a digest is
|
|
110
|
+
written back to the work item
|
|
90
111
|
doctor what is installed on THIS machine, what is
|
|
91
112
|
missing, and what each missing thing costs
|
|
92
113
|
```
|
|
@@ -632,6 +653,25 @@ plainly commenting on an issue is `gh`'s job and `gh` is better at it; closing
|
|
|
632
653
|
one *end* is `gh issue close`. Pharos owns the one thing `gh` cannot see: which
|
|
633
654
|
work item tracks this issue, written so it survives in both databases.
|
|
634
655
|
|
|
656
|
+
The one place that line moved: **a comment that already exists** is reachable
|
|
657
|
+
through `pharos comment <verb> <owner/name#45>` — edit, delete, react, unreact,
|
|
658
|
+
reactors, hide, unhide, pin, unpin. Two reasons, and neither is symmetry for its
|
|
659
|
+
own sake. Editing or deleting one can destroy the link record, so it needs the
|
|
660
|
+
guard below rather than a bare `gh api`. And hiding or pinning has **no
|
|
661
|
+
first-class `gh` verb at all** — they are GraphQL mutations with no REST route,
|
|
662
|
+
which is the "nothing else can do this" test the rest of these verbs pass.
|
|
663
|
+
Posting a *new* comment is still not ours.
|
|
664
|
+
|
|
665
|
+
The second place it moved, and it is the only verb here that overlaps `gh` head
|
|
666
|
+
on: **`pharos issue edit` exists to REFUSE.** `gh issue edit` does the same
|
|
667
|
+
write and does it well — what it cannot do is notice that somebody changed the
|
|
668
|
+
thing you were overwriting. It reads nothing and compares nothing, so if a
|
|
669
|
+
colleague renamed the issue while you were composing, their rename is gone and
|
|
670
|
+
neither of you is told. That is fine for a human at a terminal and wrong for an
|
|
671
|
+
agent, which reads an issue, spends a minute thinking, and writes back into a
|
|
672
|
+
world that moved. **If you want an unguarded edit, use `gh issue edit` — it is
|
|
673
|
+
right there and it is better at it.**
|
|
674
|
+
|
|
635
675
|
Azure DevOps has its own GitHub integration and **the link it makes carries
|
|
636
676
|
nothing** — title, body, comments, labels and state stay on their own island,
|
|
637
677
|
and the transition only ever fires from a commit or a PR merge, never from
|
|
@@ -645,8 +685,52 @@ pharos issue say contoso/widgets#45 --file reply.md
|
|
|
645
685
|
pharos issue drift # where the two disagree
|
|
646
686
|
pharos issue backfill contoso/widgets --limit 25 --yes
|
|
647
687
|
pharos issue close 4821 --text "Shipped in 1.4.0."
|
|
688
|
+
pharos issue edit contoso/widgets#45 --title "Crash on resize" --yes
|
|
648
689
|
```
|
|
649
690
|
|
|
691
|
+
### Editing an issue, and the guard GitHub does not give us
|
|
692
|
+
|
|
693
|
+
**There is no conditional write.** `PATCH /repos/{o}/{r}/issues/{n}` answers
|
|
694
|
+
**400** to `If-Match` — measured, not assumed — so the `{"op":"test","path":
|
|
695
|
+
"/rev"}` guarantee behind every Azure DevOps patch has no GitHub equivalent.
|
|
696
|
+
Never send `If-Match` here yourself either: it is not inert, it fails the write,
|
|
697
|
+
and the 400 reads like a malformed body.
|
|
698
|
+
|
|
699
|
+
**And do not guard on `updated_at` or the ETag.** Both move when somebody merely
|
|
700
|
+
*comments* on the issue, so a guard keyed on either refuses a good edit for a
|
|
701
|
+
change that touched nothing — it fires on the case that is *not* a collision.
|
|
702
|
+
|
|
703
|
+
So the guard compares the **value of the field you are overwriting**: re-read
|
|
704
|
+
immediately before sending, and refuse only if that text moved. A comment cannot
|
|
705
|
+
cause it, which is what makes the refusal worth reading.
|
|
706
|
+
|
|
707
|
+
| you pass | the base is | what it protects |
|
|
708
|
+
|---|---|---|
|
|
709
|
+
| nothing | this command's own read | one round trip. Honest, and small |
|
|
710
|
+
| `--if-title` / `--if-body` / `--if-body-file` | what **you** saw | the whole gap between your read and your write |
|
|
711
|
+
|
|
712
|
+
Pass `--if-*` whenever you read the issue and then thought about it — that gap is
|
|
713
|
+
where a collision actually happens. The output says which window it guarded, as
|
|
714
|
+
`fields.guard.window`: `in-command` or `caller`.
|
|
715
|
+
|
|
716
|
+
A refusal is `kind: "conflict"`, exit **1**, and carries `conflicts` (base,
|
|
717
|
+
remote and proposed for each field) plus `attribution` naming who renamed it.
|
|
718
|
+
Re-read, fold their change into yours, edit again with `--if-title` set to what
|
|
719
|
+
you just read. **It is not atomic and nothing client-side can make it so** — it
|
|
720
|
+
narrows the race to one round trip rather than closing it.
|
|
721
|
+
|
|
722
|
+
Two things GitHub does *quietly*, which this verb reports and a bare `gh api`
|
|
723
|
+
would not:
|
|
724
|
+
|
|
725
|
+
| endpoint | the silence |
|
|
726
|
+
|---|---|
|
|
727
|
+
| `POST …/labels` | **creates** a repository label that does not exist — 200, grey, permanent, spelled exactly as you typed it. So an unknown label is REFUSED with the near misses named; `--create-label` is how you mean it |
|
|
728
|
+
| `POST …/assignees` | **ignores** a login it will not assign and still answers 201. Read `assignees.ignored` — a status code is not the answer here |
|
|
729
|
+
|
|
730
|
+
Labels and assignees go through those add/remove endpoints and never through the
|
|
731
|
+
whole-issue PATCH, which carries them as *whole arrays* — one label write would
|
|
732
|
+
otherwise blindly overwrite every label on the issue.
|
|
733
|
+
|
|
650
734
|
### Bind the repository first, or none of this runs
|
|
651
735
|
|
|
652
736
|
```bash
|
|
@@ -829,6 +913,71 @@ something none of this models. `close` does not compose `Closes #45` /
|
|
|
829
913
|
`Fixes AB#123` into a PR body either: those fire on a PR *merge*, so there would
|
|
830
914
|
be nothing to compose into and nothing to verify.
|
|
831
915
|
|
|
916
|
+
### Editing a GitHub comment, and the trailer you must not break
|
|
917
|
+
|
|
918
|
+
A comment that already exists is `pharos comment`, with the issue as the target.
|
|
919
|
+
The verb set is the one you already know from work items and wiki pages:
|
|
920
|
+
|
|
921
|
+
```bash
|
|
922
|
+
pharos comment list contoso/widgets#45 # ids, state, and what you MAY do
|
|
923
|
+
pharos comment edit contoso/widgets#45 900 --file fixed.md
|
|
924
|
+
pharos comment delete contoso/widgets#45 900 --yes
|
|
925
|
+
pharos comment react contoso/widgets#45 900 thumbs-up
|
|
926
|
+
pharos comment hide contoso/widgets#45 900 off-topic
|
|
927
|
+
pharos comment pin contoso/widgets#45 900
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
**Start with `list`.** It is the only way to learn a comment id, and it also
|
|
931
|
+
answers the question that saves a failed write: every row carries a `may` object
|
|
932
|
+
— `edit`, `delete`, `hide`, `pin`, `react` — read from GitHub's own view of what
|
|
933
|
+
this account may do. A comment you may not edit is `"edit": false` before you
|
|
934
|
+
try, not a 403 afterwards. Each row also carries `pharosAuthored` and
|
|
935
|
+
`workItemId`, so you can see at a glance which comment is the link.
|
|
936
|
+
|
|
937
|
+
Two ids come back per comment and **both are printed because neither can be
|
|
938
|
+
derived from the other**: `id` is the number that edit, delete and reactions
|
|
939
|
+
address, `nodeId` is what hide and pin take. Either is accepted anywhere a
|
|
940
|
+
comment is named; passing back the one the verb wants saves a request.
|
|
941
|
+
|
|
942
|
+
**An edit cannot double or strip the `pharos:v1` trailer, and this is enforced
|
|
943
|
+
rather than requested.** That trailer is the durable record of which work item
|
|
944
|
+
tracks this issue *and* the guard that stops the two platforms summarising each
|
|
945
|
+
other's summaries. So:
|
|
946
|
+
|
|
947
|
+
| what you send | what happens |
|
|
948
|
+
|---|---|
|
|
949
|
+
| new prose, no trailer | the existing trailer is **restored**, and `markerPreserved: true` says so |
|
|
950
|
+
| the body you read back, trailer intact | sent unchanged |
|
|
951
|
+
| two trailers | refused — `doubled` |
|
|
952
|
+
| a trailer naming a different work item | refused — `repointed`; `pharos issue link` is the verb for that |
|
|
953
|
+
| a trailer on a comment that had none | refused — `forged` |
|
|
954
|
+
|
|
955
|
+
You do not have to think about any of this: hand over the words you want and the
|
|
956
|
+
record survives. It is written down because the refusals name a reason, and the
|
|
957
|
+
reason is actionable.
|
|
958
|
+
|
|
959
|
+
**Deleting the comment that carries the trailer destroys the GitHub half of the
|
|
960
|
+
link.** It is allowed — a mis-adoption is a real thing — but the `--yes` refusal
|
|
961
|
+
says so first, names the work item, and gives you the `pharos issue link` command
|
|
962
|
+
that puts it back. Under `--dry-run` you get the same preview and exit 0. A
|
|
963
|
+
delete that finds the comment already gone reports `alreadyGone: true` and
|
|
964
|
+
succeeds, so a retry after a lost reply is safe.
|
|
965
|
+
|
|
966
|
+
**`hide` and `pin` exist on GitHub and nowhere else** — they are GraphQL
|
|
967
|
+
mutations with no REST route, which is why `gh` has no verb for them. Hiding
|
|
968
|
+
needs a classifier and there is no neutral default, because GitHub shows it
|
|
969
|
+
beside the hidden comment: `spam`, `abuse`, `off-topic`, `outdated`,
|
|
970
|
+
`duplicate`, `resolved`, `low-quality`. Ask for `off-topic` and `off-topic` is
|
|
971
|
+
what reads back. On a work item or a wiki page these four verbs are refused with
|
|
972
|
+
"Azure DevOps has neither" rather than as an unknown verb — there is no endpoint
|
|
973
|
+
to go looking for.
|
|
974
|
+
|
|
975
|
+
**`pharos comment add` is refused on a GitHub issue.** Posting is already
|
|
976
|
+
covered twice and which one you want depends on whether the board should hear:
|
|
977
|
+
`pharos issue say` writes to the reporter *and* the work item, `gh issue comment`
|
|
978
|
+
writes to GitHub only. A third door here would post on an adopted issue that the
|
|
979
|
+
work item never hears about — the exact asymmetry `say` exists to prevent.
|
|
980
|
+
|
|
832
981
|
## What `pharos` does NOT do — read this before you go looking
|
|
833
982
|
|
|
834
983
|
- **Free-text and code search.** Nothing here covers it. For work items,
|
|
@@ -839,10 +988,12 @@ be nothing to compose into and nothing to verify.
|
|
|
839
988
|
- **Wiki content search.** `wiki tree` then `wiki read` is the only way through;
|
|
840
989
|
there is no grep across pages.
|
|
841
990
|
- Pull requests, builds, pipelines.
|
|
842
|
-
- **
|
|
843
|
-
|
|
844
|
-
better and a second GitHub CLI would only drift from it. The
|
|
845
|
-
verbs are the edge
|
|
991
|
+
- **Almost anything on GitHub that is not the join.** No issue list, no issue
|
|
992
|
+
view, no *posting* a comment, no labels or milestones, no pull requests — `gh`
|
|
993
|
+
does all of it better and a second GitHub CLI would only drift from it. The
|
|
994
|
+
seven `issue` verbs are the edge. The one addition is a comment that already
|
|
995
|
+
exists (`pharos comment <verb> <owner/name#45>`): editing or deleting one can
|
|
996
|
+
break the link record, and hiding or pinning has no `gh` verb at all.
|
|
846
997
|
- **Jira, Linear, and the Argus board.** Not covered, not planned. "Task",
|
|
847
998
|
"todo" and "board" mean something else there.
|
|
848
999
|
|
|
@@ -1072,3 +1223,12 @@ an `issue` verb names `repos.json` rather than an environment variable.
|
|
|
1072
1223
|
```bash
|
|
1073
1224
|
pharos setup --repo contoso/widgets --gh-account alisina-tibata
|
|
1074
1225
|
```
|
|
1226
|
+
|
|
1227
|
+
**A verb whose target is a GitHub issue does not need `ADO_PAT` at all.**
|
|
1228
|
+
`pharos comment list|edit|delete|react|unreact|reactors|hide|unhide|pin|unpin
|
|
1229
|
+
<owner/name#n>` runs on `gh`'s credential alone, on a machine that has never had
|
|
1230
|
+
an Azure DevOps token. So a `config` error naming `ADO_PAT` from one of those is
|
|
1231
|
+
a defect worth reporting, not something to go and provision a token over. The
|
|
1232
|
+
two credentials are independent — separate keychain entries, and `pharos doctor`
|
|
1233
|
+
reports them separately — and `pharos issue` is the one family that genuinely
|
|
1234
|
+
needs both, because it writes to both platforms in one invocation.
|