@floh-solutions/pharos-cli 0.23.0 → 0.24.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 +318 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +23 -0
- package/dist/capabilities.js.map +1 -1
- package/dist/cli.d.ts +4 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +235 -31
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.d.ts +11 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +351 -8
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/issue.d.ts +40 -0
- package/dist/commands/issue.d.ts.map +1 -0
- package/dist/commands/issue.js +2188 -0
- package/dist/commands/issue.js.map +1 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +114 -0
- package/dist/commands/setup.js.map +1 -1
- package/dist/half-link.d.ts +147 -0
- package/dist/half-link.d.ts.map +1 -0
- package/dist/half-link.js +247 -0
- package/dist/half-link.js.map +1 -0
- package/dist/issue-scan.d.ts +383 -0
- package/dist/issue-scan.d.ts.map +1 -0
- package/dist/issue-scan.js +455 -0
- package/dist/issue-scan.js.map +1 -0
- package/dist/output.d.ts +18 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +171 -0
- package/dist/output.js.map +1 -1
- package/dist/session.d.ts +50 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +70 -0
- package/dist/session.js.map +1 -1
- package/package.json +4 -3
- package/skill/SKILL.md +268 -9
package/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pharos
|
|
3
|
-
description: "Use for AZURE DEVOPS work
|
|
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 in Azure DevOps; reading or writing an ADO project 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 description, comment or wiki page; @mentioning somebody so they are actually notified; importing Markdown, Word or PDF files as wiki pages; and whether a failed ADO call is worth retrying. 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 the reporter and the board at once, where they have drifted, and closing both ends together. NOT a GitHub CLI: listing, viewing or commenting on an issue is `gh`'s job. NOT for other trackers — the Argus board, Jira or Linear."
|
|
4
4
|
license: Proprietary
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -61,19 +61,39 @@ wiki import <file...> .md .txt .docx .pdf .rtf .html -> pages. A
|
|
|
61
61
|
--under <path> --as <name>
|
|
62
62
|
comment list | add | edit | delete <target> is a work item id OR a wiki path
|
|
63
63
|
comment react | unreact | reactors like dislike heart hooray smile confused
|
|
64
|
+
issue adopt <owner/name#45> a GitHub ISSUE becomes a work item, with BOTH
|
|
65
|
+
ends of the link written. --type --title --parent
|
|
66
|
+
issue link <owner/name#45> <id> join an existing pair — or finish a join that
|
|
67
|
+
half-happened. Only the missing half is written
|
|
68
|
+
issue say <owner/name#45> ONE message, TWO audiences: the whole of it to
|
|
69
|
+
the reporter on GitHub, a summary and that
|
|
70
|
+
comment's URL to the board. --summary
|
|
71
|
+
issue trail <id|owner/name#45> the whole trail from EITHER end, with the
|
|
72
|
+
evidence for each half. Read-only
|
|
73
|
+
issue drift where the two platforms DISAGREE — the report no
|
|
74
|
+
other tool can produce. --repo --limit --wiql
|
|
75
|
+
issue backfill <owner/name> bulk adopt every issue the board does not link
|
|
76
|
+
yet. Needs --yes. --limit --state --label
|
|
77
|
+
issue close <id|owner/name#45> close BOTH ends, then RE-READ both to say what
|
|
78
|
+
actually moved. --to --reason --all
|
|
64
79
|
hooks list | check | create | repoint | delete service hooks for realtime.
|
|
65
80
|
`check` needs --hub <url>; `list` shows the URL
|
|
66
81
|
already in use
|
|
67
82
|
plan <file> an implementation plan → a work item tree
|
|
68
83
|
setup org, project, token → keychain + shell profile
|
|
69
84
|
--install ask|all|a,b offer the optional
|
|
70
|
-
capabilities (LibreOffice, poppler, converter
|
|
85
|
+
capabilities (LibreOffice, poppler, converter,
|
|
86
|
+
the GitHub CLI)
|
|
87
|
+
--repo owner/name --gh-account <login> bind a
|
|
88
|
+
repository to the GitHub account that reaches
|
|
89
|
+
it. BOTH or NEITHER — `issue` needs this first
|
|
71
90
|
doctor what is installed on THIS machine, what is
|
|
72
91
|
missing, and what each missing thing costs
|
|
73
92
|
```
|
|
74
93
|
|
|
75
94
|
Text input: `--text` / `--file` / `--stdin`. Global: `--pretty` for a human,
|
|
76
|
-
`--yes` for destructive verbs, `--dry-run` to preview
|
|
95
|
+
`--yes` for destructive verbs, `--dry-run` to preview, `--max-writes <n>` to
|
|
96
|
+
change the per-invocation write cap (default 20; `0` is read-only).
|
|
77
97
|
|
|
78
98
|
**`ADO_ORG`, `ADO_PROJECT` and `ADO_PAT` are already in the environment** after
|
|
79
99
|
setup. Do not check them before working; a missing one announces itself as
|
|
@@ -83,8 +103,10 @@ setup. Do not check them before working; a missing one announces itself as
|
|
|
83
103
|
commands further down name them with confidence they have not earned on yours.
|
|
84
104
|
`pharos doctor` answers that in one call: what is present, its version and where
|
|
85
105
|
it resolved, what is missing, and what each missing thing actually costs. It is
|
|
86
|
-
read-only
|
|
87
|
-
|
|
106
|
+
read-only and works before anything is configured — so it is also the right
|
|
107
|
+
first move when something behaves oddly. Offline too, with one exception it
|
|
108
|
+
names: `gh auth status` validates every token against github.com and there is
|
|
109
|
+
no flag that stops it, so that probe runs only when `gh` is installed.
|
|
88
110
|
|
|
89
111
|
`pharos setup --install ask` then offers to install them, driving Homebrew, apt
|
|
90
112
|
or winget rather than vendoring anything. **Nothing installs without that flag**
|
|
@@ -596,6 +618,217 @@ leading slash**. Two things follow:
|
|
|
596
618
|
website, that is why. `wiki links` and `unlink` both ask about **both** shapes,
|
|
597
619
|
so old links still resolve and can still be removed.
|
|
598
620
|
|
|
621
|
+
## GitHub issues: the join, and only the join
|
|
622
|
+
|
|
623
|
+
**These verbs are newer than the CLI on most machines. Check before you promise
|
|
624
|
+
one.** `pharos issue` shipped *after* **0.23.0**, so if `pharos --version` prints
|
|
625
|
+
0.23.0 or lower it is not there and every verb below is an unknown command —
|
|
626
|
+
`npm i -g @floh-solutions/pharos-cli@latest` is the fix. This skill and the CLI
|
|
627
|
+
update by different routes and drift apart in both directions; `pharos doctor`
|
|
628
|
+
prints both versions.
|
|
629
|
+
|
|
630
|
+
**This is not a GitHub CLI and must not become one.** Listing, viewing and
|
|
631
|
+
plainly commenting on an issue is `gh`'s job and `gh` is better at it; closing
|
|
632
|
+
one *end* is `gh issue close`. Pharos owns the one thing `gh` cannot see: which
|
|
633
|
+
work item tracks this issue, written so it survives in both databases.
|
|
634
|
+
|
|
635
|
+
Azure DevOps has its own GitHub integration and **the link it makes carries
|
|
636
|
+
nothing** — title, body, comments, labels and state stay on their own island,
|
|
637
|
+
and the transition only ever fires from a commit or a PR merge, never from
|
|
638
|
+
closing an issue. That gap is the whole reason these verbs exist.
|
|
639
|
+
|
|
640
|
+
```bash
|
|
641
|
+
pharos issue adopt contoso/widgets#45 --parent 39 # an issue → a work item, both ends
|
|
642
|
+
pharos issue link contoso/widgets#45 4821 # join a pair that already exists
|
|
643
|
+
pharos issue trail 4821 # …or trail contoso/widgets#45
|
|
644
|
+
pharos issue say contoso/widgets#45 --file reply.md
|
|
645
|
+
pharos issue drift # where the two disagree
|
|
646
|
+
pharos issue backfill contoso/widgets --limit 25 --yes
|
|
647
|
+
pharos issue close 4821 --text "Shipped in 1.4.0."
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
### Bind the repository first, or none of this runs
|
|
651
|
+
|
|
652
|
+
```bash
|
|
653
|
+
pharos setup --repo contoso/widgets --gh-account alisina-tibata
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
**Both flags or neither**, and there is deliberately **no fallback to whichever
|
|
657
|
+
account `gh` has active**: two accounts can each see a repository of the same
|
|
658
|
+
name, so the wrong one answers **200** for a different repository — a wrong
|
|
659
|
+
answer rather than an error.
|
|
660
|
+
|
|
661
|
+
An unbound repository is `"kind": "config"` on exit 2, naming
|
|
662
|
+
`~/.config/pharos/repos.json` — never a guess — **and it lists the repositories
|
|
663
|
+
that ARE bound**, so a typo is visible without reading the file. That check runs
|
|
664
|
+
before everything else here, so it is the first thing to fix. `gh` itself is
|
|
665
|
+
optional: without it every `issue` verb is refused by name with the reason and
|
|
666
|
+
the Azure DevOps verbs are untouched. `pharos doctor` reports both.
|
|
667
|
+
|
|
668
|
+
A failure that came from GitHub says **`"platform": "github"`**, because these
|
|
669
|
+
verbs touch two platforms in one call and which one refused is the first thing
|
|
670
|
+
to know. Its absence means Azure DevOps or this tool, as everywhere else.
|
|
671
|
+
|
|
672
|
+
### `adopt` is safe to re-run. `say` is NOT. Do not generalise from one.
|
|
673
|
+
|
|
674
|
+
**Adopting the same issue twice never creates a second work item.** What it
|
|
675
|
+
does instead depends on the state the pair is in, and the exit code tells you
|
|
676
|
+
which:
|
|
677
|
+
|
|
678
|
+
| exit **0**, `created: false` | the issue carries a marker. You get the work item it names and nothing is written — the state you asked for already holds |
|
|
679
|
+
| exit **3**, `halfLinked: true` | a work item already links this issue and the issue says nothing about it. Refused, carrying `recover` — the link wants **finishing**, not repeating |
|
|
680
|
+
| exit **3**, `workItemIds` with two entries | two work items claim one issue. Refused, both named, no `recover`: picking one would be inventing an answer |
|
|
681
|
+
|
|
682
|
+
Azure DevOps is written **first**, because the work item id does not exist until
|
|
683
|
+
the create lands, so the one failure `adopt` can leave is always the same shape:
|
|
684
|
+
the board end written, the GitHub end not.
|
|
685
|
+
|
|
686
|
+
```jsonc
|
|
687
|
+
{ "error": { "createdWorkItem": 4821, "halfLinked": true, "wrote": ["hyperlink"],
|
|
688
|
+
"recover": "pharos issue link contoso/widgets#45 4821" } }
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
**Read more than `kind` on that error**: a work item now exists, and reading
|
|
692
|
+
only the kind loses its id. `recover` is the literal command that finishes the
|
|
693
|
+
job, and nothing needs undoing first.
|
|
694
|
+
|
|
695
|
+
**Re-running `adopt` there is safe but it is not the repair** — it refuses,
|
|
696
|
+
because the row above is exactly the state it detects, and the refusal hands
|
|
697
|
+
back the same `recover` string. Take it either from the failure or from the
|
|
698
|
+
refusal; they are the same command. `link` writes only the half that is missing,
|
|
699
|
+
which makes it both the fix here and the ordinary way to join a pair that
|
|
700
|
+
already exists. `pharos issue drift` finds this state later if nobody acted on
|
|
701
|
+
it at the time — it reports it as `one-sided`, carrying the same repair.
|
|
702
|
+
|
|
703
|
+
Every `adopt` reports `boardCheck`. `{"ran": true}` means the board was searched
|
|
704
|
+
for a work item that already tracks this issue; `{"ran": false}` carries the
|
|
705
|
+
reason it could not be, and then a half-link made on **another machine** would
|
|
706
|
+
not have been seen — `pharos issue drift --repo <owner/name>` asks the same
|
|
707
|
+
question deliberately.
|
|
708
|
+
|
|
709
|
+
`say` is the opposite, and that is the trap. **GitHub is written first there**,
|
|
710
|
+
because the board's comment carries the GitHub comment's URL and that does not
|
|
711
|
+
exist until the POST returns. So a failure on the board half leaves a **public
|
|
712
|
+
comment already posted**, and re-running posts a second one:
|
|
713
|
+
|
|
714
|
+
```jsonc
|
|
715
|
+
{ "error": { "halfSaid": true, "wrote": ["github-comment"],
|
|
716
|
+
"github": { "commentUrl": "https://github.com/…#issuecomment-950" },
|
|
717
|
+
"recover": "pharos comment add 4821 --stdin", "adoComment": "…" } }
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
Feed `adoComment` into `recover`. Do not re-run `say`.
|
|
721
|
+
|
|
722
|
+
### `say` — one message, two audiences
|
|
723
|
+
|
|
724
|
+
| | GitHub | Azure DevOps |
|
|
725
|
+
|---|---|---|
|
|
726
|
+
| who reads it | the reporter, who has **no** Azure DevOps account and never will | the team |
|
|
727
|
+
| what they get | the full explanation | a summary, and the URL of the comment carrying the rest |
|
|
728
|
+
|
|
729
|
+
**The asymmetry is the verb.** The same words in both places is `gh issue
|
|
730
|
+
comment` followed by `pharos comment add`, and neither of those knows the other
|
|
731
|
+
happened. Without `--summary` the board gets the first paragraph cut to 200
|
|
732
|
+
characters — a guess, and allowed to be one *only* because the comment's URL
|
|
733
|
+
travels with it. GitHub is the record of what was said; the board never is.
|
|
734
|
+
|
|
735
|
+
**Never pass a message that already carries a `<!-- pharos:v1 … -->` trailer.**
|
|
736
|
+
It is refused (exit 3) before any call, on `say` and on `close`'s closing note
|
|
737
|
+
alike. That trailer means the text is Pharos's own output coming back round — a
|
|
738
|
+
comment you read and re-posted — and it is how a fan-out starts summarising its
|
|
739
|
+
own summaries. Every comment these verbs post carries one on the way out; you
|
|
740
|
+
never write one in.
|
|
741
|
+
|
|
742
|
+
`say` starts from the **issue** end only. A work item may hyperlink several
|
|
743
|
+
issues, so a bare id names no single reporter — `pharos issue trail <id>` is how
|
|
744
|
+
you find out which one you meant.
|
|
745
|
+
|
|
746
|
+
### `trail`, and the evidence worth reading
|
|
747
|
+
|
|
748
|
+
Read-only, and it answers from **either** end with the same output shape. The
|
|
749
|
+
field to read is `evidence`: `["hyperlink","marker"]` is a complete link, and
|
|
750
|
+
either one **alone** is a link that only half exists — a finding, not a detail.
|
|
751
|
+
The halves live in different places on purpose: a `Hyperlink` relation on the
|
|
752
|
+
work item, and one comment on the issue carrying `AB#4821` plus the
|
|
753
|
+
machine-readable trailer.
|
|
754
|
+
|
|
755
|
+
**The marker goes in a comment, never the issue body.** Editing a reporter's
|
|
756
|
+
body collides with them and needs write access nobody has on a community issue.
|
|
757
|
+
|
|
758
|
+
### `drift` — the report no other tool can produce
|
|
759
|
+
|
|
760
|
+
`gh` lists issues and Azure DevOps lists work items; **neither holds both
|
|
761
|
+
sides**, so neither can say *these two disagree*. Four kinds, because they want
|
|
762
|
+
four different actions:
|
|
763
|
+
|
|
764
|
+
| kind | what it means |
|
|
765
|
+
|---|---|
|
|
766
|
+
| `state` | both ends exist and disagree about whether the work is finished |
|
|
767
|
+
| `missing-issue` | the work item names an issue GitHub does not have |
|
|
768
|
+
| `one-sided` | one platform carries the link and the other does not — what a failed `adopt` leaves. Carries the `pharos issue link …` that repairs it |
|
|
769
|
+
| `unreadable` | the GitHub end could not be read, so nothing about this pair is known |
|
|
770
|
+
|
|
771
|
+
**It scans links, not issues.** An unadopted issue is not drift — that is
|
|
772
|
+
`backfill`'s question. On a repo with four hundred of them, counting "not
|
|
773
|
+
linked" as a problem buries three real findings under three hundred and
|
|
774
|
+
eighty-eight rows of noise.
|
|
775
|
+
|
|
776
|
+
**"Finished" is read from the project, never guessed**: each work item is judged
|
|
777
|
+
against its own type's categories and the report says which source it used —
|
|
778
|
+
`Resolved` is terminal on a Bug and open on a User Story. When the catalogue
|
|
779
|
+
cannot be read the stock names are used *and said out loud*, because a row is
|
|
780
|
+
uninterpretable without knowing what was counted as finished. An unreadable
|
|
781
|
+
repository is information rather than a fault and never fails the command.
|
|
782
|
+
|
|
783
|
+
### `backfill` — the adoption path for the repo that already has 400 issues
|
|
784
|
+
|
|
785
|
+
```bash
|
|
786
|
+
pharos issue backfill contoso/widgets # previews, then REFUSES (exit 3)
|
|
787
|
+
pharos issue backfill contoso/widgets --dry-run # the same preview, exit 0
|
|
788
|
+
pharos issue backfill contoso/widgets --label bug --parent 39 --limit 25 --max-writes 50 --yes
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
**Read the preview before adding `--yes`.** It names the repository, the `gh`
|
|
792
|
+
account it would be reached as, **and the Azure DevOps organisation and project
|
|
793
|
+
the work items would land on** — nothing in the design pairs a repo with a
|
|
794
|
+
board, and a mis-aimed `adopt` is one work item where a mis-aimed `backfill
|
|
795
|
+
--yes` is four hundred, each with a public comment naming a board its reporter
|
|
796
|
+
has nothing to do with.
|
|
797
|
+
|
|
798
|
+
**Each adoption is two writes**, so four hundred issues is eight hundred against
|
|
799
|
+
a default cap of 20. That cost is worked out *before* anything is written and a
|
|
800
|
+
run that cannot finish is refused, naming both ways forward — rather than
|
|
801
|
+
stopping at write nineteen, which is the outcome you can reason about least.
|
|
802
|
+
|
|
803
|
+
**It is resumable and needs no state file.** The link *is* the progress record:
|
|
804
|
+
a second run finds the ones the first adopted already linked and carries on, in
|
|
805
|
+
issue-number order. `--state` defaults to `open`, because adopting a closed
|
|
806
|
+
issue creates a work item that is finished before anybody looks at it.
|
|
807
|
+
|
|
808
|
+
### `close` — the ending of the trail
|
|
809
|
+
|
|
810
|
+
Closes **both** ends, comments on each pointing at the other, then **re-reads
|
|
811
|
+
both** and reports what actually moved. Two 200s are not proof: a workflow rule
|
|
812
|
+
can refuse a transition on a field the API happily accepted, so **`verified` is
|
|
813
|
+
what was there afterwards** rather than what was sent. Read it.
|
|
814
|
+
|
|
815
|
+
**There is no hardcodable `Closed`.** The state comes from the project's own
|
|
816
|
+
categories — exactly one terminal state for that type is used, and *several* is
|
|
817
|
+
a refusal naming them and `--to`, because `Done` and `Removed` are both finished
|
|
818
|
+
and mean opposite things. If the catalogue cannot be read at all it refuses
|
|
819
|
+
rather than guessing.
|
|
820
|
+
|
|
821
|
+
`--to`, **not** `--state`: `--state` already means `open|closed|all` on
|
|
822
|
+
`backfill`. Closing an already-closed pair writes nothing and exits 0. A work
|
|
823
|
+
item linking several issues is refused unless `--all` says so — "close 4821"
|
|
824
|
+
should not read as "close four strangers' issues".
|
|
825
|
+
|
|
826
|
+
**Pull requests are out of scope and are refused by name.** On GitHub's API
|
|
827
|
+
every PR is also an issue, so `adopt` on a PR number would otherwise mirror
|
|
828
|
+
something none of this models. `close` does not compose `Closes #45` /
|
|
829
|
+
`Fixes AB#123` into a PR body either: those fire on a PR *merge*, so there would
|
|
830
|
+
be nothing to compose into and nothing to verify.
|
|
831
|
+
|
|
599
832
|
## What `pharos` does NOT do — read this before you go looking
|
|
600
833
|
|
|
601
834
|
- **Free-text and code search.** Nothing here covers it. For work items,
|
|
@@ -606,6 +839,12 @@ leading slash**. Two things follow:
|
|
|
606
839
|
- **Wiki content search.** `wiki tree` then `wiki read` is the only way through;
|
|
607
840
|
there is no grep across pages.
|
|
608
841
|
- Pull requests, builds, pipelines.
|
|
842
|
+
- **Anything on GitHub that is not the join.** No issue list, no issue view, no
|
|
843
|
+
plain comment, no labels or milestones, no pull requests — `gh` does all of it
|
|
844
|
+
better and a second GitHub CLI would only drift from it. The seven `issue`
|
|
845
|
+
verbs are the edge and deliberately nothing else.
|
|
846
|
+
- **Jira, Linear, and the Argus board.** Not covered, not planned. "Task",
|
|
847
|
+
"todo" and "board" mean something else there.
|
|
609
848
|
|
|
610
849
|
**There is no Azure DevOps MCP server here any more, and that is deliberate.**
|
|
611
850
|
It authenticated through the Azure CLI, so it opened a browser mid-task — which
|
|
@@ -617,9 +856,9 @@ routing around it: several things here exist in no other Azure DevOps tool at
|
|
|
617
856
|
all — wiki page comments and reactions, attachment upload AND removal, inline
|
|
618
857
|
images for a work item field or a wiki page, mentioning somebody in a form that
|
|
619
858
|
actually notifies, importing a Word document or a PDF as a page, editing or
|
|
620
|
-
deleting a work item comment, service hooks,
|
|
621
|
-
`test` op on `/rev` so a
|
|
622
|
-
overwritten. Those are what the
|
|
859
|
+
deleting a work item comment, service hooks, the GitHub-issue join and the
|
|
860
|
+
drift report over it, and applying a change under a `test` op on `/rev` so a
|
|
861
|
+
teammate who wrote first cannot be silently overwritten. Those are what the
|
|
623
862
|
guards are, and they are the reason to come back here rather than hand-roll.
|
|
624
863
|
|
|
625
864
|
## Start every task with one command
|
|
@@ -739,7 +978,12 @@ true` means stop re-checking the token.
|
|
|
739
978
|
| `0` | it worked | carry on |
|
|
740
979
|
| `1` | the call failed | check `kind`; retry only if it is `rateLimit` (wait `retryAfterMs`) or transient |
|
|
741
980
|
| `2` | called wrong, or not configured | **never retry unchanged.** Fix the call, or the setup |
|
|
742
|
-
| `3` | a guard here refused | re-run with `--yes` — after deciding it is right |
|
|
981
|
+
| `3` | a guard here refused | re-run with `--yes`, or raise `--max-writes` — after deciding it is right |
|
|
982
|
+
|
|
983
|
+
**A failure carrying `"platform": "github"` came from GitHub**, not from Azure
|
|
984
|
+
DevOps and not from here — `pharos issue` touches two platforms in one call, and
|
|
985
|
+
which one refused decides whether the fix is a token, a repo binding or a field.
|
|
986
|
+
Its absence means the other side, as it always did.
|
|
743
987
|
|
|
744
988
|
`"kind": "conflict"` means somebody wrote first. Your work is still valid:
|
|
745
989
|
re-read, re-apply. It carries both revisions — and note that **posting a comment
|
|
@@ -801,6 +1045,12 @@ it is about to break. Sub-pages move with their parent.
|
|
|
801
1045
|
not only in a chat log nobody else can read.
|
|
802
1046
|
5. Move the state when the work moves, not at the end.
|
|
803
1047
|
|
|
1048
|
+
**When the work started as a GitHub issue the loop gains two ends and changes
|
|
1049
|
+
one step**: `pharos issue adopt` before step 1, `pharos issue close` after step
|
|
1050
|
+
5, and at step 4 the reply to the *reporter* is `pharos issue say` rather than a
|
|
1051
|
+
comment on the work item — a comment on the item is invisible to somebody with
|
|
1052
|
+
no Azure DevOps account, which is every reporter.
|
|
1053
|
+
|
|
804
1054
|
**Every person uses their own token.** Board attribution is per-person, so
|
|
805
1055
|
anything you do is recorded against whoever owns `ADO_PAT`. Never suggest
|
|
806
1056
|
sharing one.
|
|
@@ -813,3 +1063,12 @@ profile that **scripted** shells read, and verifies both permission scopes —
|
|
|
813
1063
|
Work Items and Wiki are separate in Azure DevOps, and a token missing the second
|
|
814
1064
|
works fine until the first wiki write days later. A **new** shell is needed
|
|
815
1065
|
afterwards.
|
|
1066
|
+
|
|
1067
|
+
**The GitHub half is configured separately and follows a different rule.** The
|
|
1068
|
+
environment carries no fourth secret: the credential comes from `gh`, and which
|
|
1069
|
+
account reaches which repository is a binding on disk, so a `config` error from
|
|
1070
|
+
an `issue` verb names `repos.json` rather than an environment variable.
|
|
1071
|
+
|
|
1072
|
+
```bash
|
|
1073
|
+
pharos setup --repo contoso/widgets --gh-account alisina-tibata
|
|
1074
|
+
```
|