docs: rephrase the vale warnings that have a better wording
Words the alex and Microsoft styles flag where a plainer one reads as well: disabled/special/invalid as a state, primitive, trap, hang, several, click, first-person FAQ questions, hyphenated adverb pairs. Left as they are: Let's Encrypt, quoted UI labels and phrases, the generated forge CLI reference, and the middle-click gesture.
This commit is contained in:
parent
3606de1c23
commit
5db38a596e
29 changed files with 62 additions and 62 deletions
|
|
@ -13,7 +13,7 @@ declarations.
|
|||
|
||||
- **Bringing a fresh swarm online?** → [`getting-started/setup.md`](getting-started/setup.md)
|
||||
(the hand steps after the first switch).
|
||||
- **What does the dashboard look like, and how do I use it?** →
|
||||
- **What does the dashboard look like, and how to use it?** →
|
||||
[`web-ui/`](web-ui/README.md) — the operator-facing starting point;
|
||||
its own sub-pages ([`shape`](web-ui/shape.md),
|
||||
[`dashboard`](web-ui/dashboard.md), [`agent`](web-ui/agent.md),
|
||||
|
|
@ -57,9 +57,9 @@ declarations.
|
|||
- **How do I give an agent a GitHub account (`gh` + `git push`)? how's
|
||||
the PAT injected?** → [`integrations/github.md`](integrations/github.md)
|
||||
(operator content up top; the `gh`/git-push + notification-poller
|
||||
mechanics are in a collapsed "Implementation" section at the bottom).
|
||||
mechanics are in a collapsed section on how it is implemented at the bottom).
|
||||
- **What's `/knowledge`? How does the swarm-wide knowledge repo sync,
|
||||
and how do I contribute a document?** → [`integrations/knowledge.md`](integrations/knowledge.md).
|
||||
and how to contribute a document?** → [`integrations/knowledge.md`](integrations/knowledge.md).
|
||||
- **What does `hivectl` do? Provisioning, gateway users, container
|
||||
shells?** → [`tools/hivectl.md`](tools/hivectl.md) (the curated guide);
|
||||
[`tools/hivectl-cli.md`](tools/hivectl-cli.md) for the exhaustive,
|
||||
|
|
@ -71,7 +71,7 @@ declarations.
|
|||
discovery work?** → [`networking/gateway.md`](networking/gateway.md).
|
||||
- **How does DNS resolution work in agent containers? What's the
|
||||
bridge network for?** → [`networking/network.md`](networking/network.md).
|
||||
- **How do I connect two hives into a swarm?** → [`swarm/`](swarm/README.md)
|
||||
- **How are two hives connected into a swarm?** → [`swarm/`](swarm/README.md)
|
||||
(peer hives, TLS trust).
|
||||
- **Where do agent snapshots go? How does the swarm's `btrfs receive`
|
||||
endpoint authenticate a pushing hive?** →
|
||||
|
|
@ -86,18 +86,18 @@ declarations.
|
|||
sealed?** → [`swarm/bao.md`](swarm/bao.md).
|
||||
- **How does an agent get a prompt at set times, and why doesn't it fire
|
||||
twice after downtime?** → [`swarm/schedules.md`](swarm/schedules.md).
|
||||
- **How do I set an agent's model or effort from the swarm, and what happens
|
||||
- **How to set an agent's model or effort from the swarm, and what happens
|
||||
to its own pick?** → [`swarm/inference.md`](swarm/inference.md).
|
||||
- **How will a PR get checked against its repo's own yes/no rules before
|
||||
a full review?** → [`swarm/review-classifier.md`](swarm/review-classifier.md)
|
||||
(planned, not implemented yet).
|
||||
- **Does an agent config PR build before it's merged?** →
|
||||
[`swarm/builder.md`](swarm/builder.md).
|
||||
- **How do I create an agent from a ready-made set of permissions and
|
||||
- **How to create an agent from a ready-made set of permissions and
|
||||
settings?** → [`swarm/archetypes.md`](swarm/archetypes.md).
|
||||
- **How long do CI runs take, per repo and PR, and where does the board get
|
||||
it?** → [`swarm/ci-metrics.md`](swarm/ci-metrics.md).
|
||||
- **How do I log an agent in to claude from the swarm UI, and why doesn't a
|
||||
- **How to log an agent in to claude from the swarm UI, and why doesn't a
|
||||
stale stored copy log it out again?** →
|
||||
[`swarm/claude-login.md`](swarm/claude-login.md).
|
||||
- **How does an agent get a todo when someone assigns it an issue, and lose it
|
||||
|
|
@ -111,7 +111,7 @@ declarations.
|
|||
queue sources, scheduler internals?** → [`scheduler/coordinator.md`](scheduler/coordinator.md).
|
||||
- **How does the CI runner work? How does it register?** →
|
||||
[`scheduler/ci.md`](scheduler/ci.md).
|
||||
- **How do I export Claude Code metrics (tokens, cost, tool calls) to
|
||||
- **How are Claude Code metrics (tokens, cost, tool calls) exported to
|
||||
Prometheus/Grafana?** → [`scheduler/observability.md`](scheduler/observability.md).
|
||||
|
||||
## Crate reference
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ system-level facts live.
|
|||
degrades safely to "no agents" (covers a fresh install that hasn't
|
||||
synced yet).
|
||||
- **Reconcile** — runs alongside the periodic meta/flake regeneration.
|
||||
Adds newly-spawned agents, drops removed ones. Reconcile keeps agents
|
||||
Adds newly spawned agents, drops removed ones. Reconcile keeps agents
|
||||
whose config repo exists but that haven't spawned yet, so the gap until
|
||||
the container appears doesn't churn the file.
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ state dirs work as for every other agent.
|
|||
permissions alone, the same mechanism for every agent
|
||||
([`docs/turn-loop/mcp.md`](../turn-loop/mcp.md)). Ruth's permissions
|
||||
are the default plus `manage_root_agent`, stored for her like any grant.
|
||||
- **State dirs** — _not_ special-cased: `HYPERHIVE_STATE_DIR` is
|
||||
- **State dirs** — _not_ treated as an exception: `HYPERHIVE_STATE_DIR` is
|
||||
injected uniformly via `systemd.globalEnvironment` for every
|
||||
container including the manager, so all token/state paths resolve
|
||||
through it the same way everywhere.
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ target hive to deploy it.
|
|||
An agent created from an [archetype](../swarm/archetypes.md) gets no
|
||||
config repo: its hive builds it from the archetype's module.
|
||||
|
||||
Changing what the template seeded isn't a special case: like every
|
||||
Changing what the template seeded isn't an exception: like every
|
||||
later change, it's a PR on that config repo, made from a clone and
|
||||
merged by an operator on the forge (see [Config changes](#config-changes)).
|
||||
|
||||
|
|
@ -376,7 +376,7 @@ Differences from sub-agents:
|
|||
authoritative applied repo (see "Root-agent view of applied" below).
|
||||
- Its socket comes from the generic per-agent registration, in the same
|
||||
per-agent runtime dir as any other agent (`/run/hyperhive/agents/ruth/`),
|
||||
not a special manager-only path.
|
||||
not a separate manager-only path.
|
||||
|
||||
**Migration note** (for older hosts): drop any `containers.root =
|
||||
{ ... }` block from your host NixOS config, and any `services.hyperhive.ruthless`
|
||||
|
|
@ -406,7 +406,7 @@ and nothing in the tree constructs it; this removal dropped the push path
|
|||
genuinely needs to interrupt an agent's turn loop, not because
|
||||
anything live uses it today.
|
||||
|
||||
**A previously-running container crashing** used to be exactly that
|
||||
**A previously running container crashing** used to be exactly that
|
||||
case (`ContainerCrash`, routed to the root agent via
|
||||
`Coordinator::notify_manager`) — it no longer drives any agent turn at
|
||||
all. `crash_watch` now only `tracing::warn!`s `"container crash
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ Where state lives, what survives what, and how it's bounded.
|
|||
|
||||
## For operators
|
||||
|
||||
The short answer to "will I lose anything": **destroying an agent
|
||||
The short answer to "does anything disappear": **destroying an agent
|
||||
keeps its state, purging it doesn't.**
|
||||
|
||||
- **`DESTR0Y`** (the default action) stops and removes the container
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ What the granter is, why it's root-equivalent, and the store's TLS:
|
|||
## 2 · Your SSO account
|
||||
|
||||
_On the host running authelia._ Until this runs, `auth.<swarm.domain>` serves
|
||||
a login page that refuses everyone: its only subject is a disabled placeholder.
|
||||
a login page that refuses everyone: its only subject is an inactive placeholder.
|
||||
|
||||
```bash
|
||||
swarmctl user add mara --display-name Mara --email mara@example.com --group admins
|
||||
|
|
@ -95,7 +95,7 @@ settings. Leave it empty and agents refer to you by name only.
|
|||
## 4 · Ruth
|
||||
|
||||
hive-c0re creates no agent at startup. You create ruth, the manager agent,
|
||||
like any other: open the swarm UI start page and click the paperclip, which
|
||||
like any other: open the swarm UI start page and select the paperclip, which
|
||||
opens the create form with `ruth` filled in and the `manage_root_agent`
|
||||
permission checked: that permission mounts the other agents into her
|
||||
container so she can recover them. The form declares her, creates her
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ read directly without a delivery — same `mark_read` call, no wake.
|
|||
|
||||
### Activation gates (graceful no-ops)
|
||||
|
||||
The poller starts disabled and stays that way for any of:
|
||||
The poller starts switched off and stays that way for any of:
|
||||
|
||||
- `HIVE_FORGE_URL` not set or not parseable as a URL (a hand-run
|
||||
harness; hive-c0re sets it from `swarm.forge.domain` on every hive).
|
||||
|
|
@ -215,7 +215,7 @@ The poller starts disabled and stays that way for any of:
|
|||
best-effort enrichment fetches of server-provided subject URLs;
|
||||
both unlikely; treated as fatal-to-the-task only).
|
||||
|
||||
Disabled = the spawned task returns immediately. All other failure
|
||||
Switched off = the spawned task returns immediately. All other failure
|
||||
modes (HTTP errors, parse errors, mark-read failures) are
|
||||
best-effort: logged at debug/warn and retried next tick.
|
||||
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ surprising behaviour:
|
|||
- **`services.hyperhive.swarm.matrix.gatewayHost != ""`** — same footgun as `forge.domain`:
|
||||
empty string renders `.<hive>`-shaped garbage in both nginx
|
||||
`server_name` (treated as wildcard catch-all, surprising) and
|
||||
`/etc/hosts` (invalid entry). `null` is the right opt-out shape;
|
||||
`/etc/hosts` (malformed entry). `null` is the right opt-out shape;
|
||||
a config assertion rejects empty string explicitly.
|
||||
SSO is unconditional, so the three below are requirements of running a
|
||||
homeserver at all rather than of a setting:
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ The catch-all `_` vhost answers any other `Host` with `444` (connection closed,
|
|||
|
||||
Only the host that **runs** authelia declares `auth.<swarm>`; a hive that merely uses SSO knows `swarm.authelia.url` but doesn't answer for that name. The server name must be exactly `swarm.authelia.domain` — authelia checks that `authelia_url` sits inside its session cookie domain at startup, and refuses to boot otherwise. The vhost carries no `auth_request` (that would put the login page behind the login it serves) and passes `X-Forwarded-{Proto,Host,Uri,For}`, because authelia decides by the original request.
|
||||
|
||||
⚠️ `auth.<swarm>` answering with the **sso unavailable** page means authelia isn't answering at all — check `journalctl -M swarm-authelia -u authelia-swarm`. While the user set is empty, a disabled placeholder user keeps authelia's user store non-empty, so it boots fine and serves a login page that refuses everyone; add the first account with `swarmctl user add …` ([`setup.md`](../getting-started/setup.md)).
|
||||
⚠️ `auth.<swarm>` answering with the **sso unavailable** page means authelia isn't answering at all — check `journalctl -M swarm-authelia -u authelia-swarm`. While the user set is empty, an inactive placeholder user keeps authelia's user store non-empty, so it boots fine and serves a login page that refuses everyone; add the first account with `swarmctl user add …` ([`setup.md`](../getting-started/setup.md)).
|
||||
|
||||
Per-agent UIs stay sub-path; forge and matrix get sub-domains → [Sub-domain shape](#sub-domain-shape-rationale).
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ Which makes it the highest-value target in the swarm by a wide margin,
|
|||
and means it should get the treatment a backup host gets --- restricted
|
||||
access, and a decision (rather than an omission) on encryption at rest.
|
||||
|
||||
The trap is the label: this box holds backup-grade data while nobody
|
||||
The pitfall is the label: this box holds backup-grade data while nobody
|
||||
calls it a backup, so it can end up with backup-grade _exposure_ and
|
||||
non-backup-grade _controls_. Nobody puts a migration staging area on
|
||||
the access-review list.
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace, not the wire surface.
|
|||
|
||||
## Recipient sentinels
|
||||
|
||||
The broker reserves a few recipient names, which have special
|
||||
The broker reserves a few recipient names, which have a fixed
|
||||
meaning that ordinary agent labels can never collide with — agent
|
||||
name validation rejects any character outside `[a-z0-9_-]`, so the
|
||||
angle-bracket and asterisk shapes below are structurally safe.
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ an input only because a docs tree has no runtime dependencies.
|
|||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
The `storePath` trap is worth spelling out, because it's not confined
|
||||
The `storePath` pitfall is worth spelling out, because it's not confined
|
||||
to options the operator writes: **any** option of type `package` fed a
|
||||
store-path _string_ coerces through `lib.toDerivation`, i.e.
|
||||
`builtins.storePath`. `environment.systemPackages` and
|
||||
|
|
@ -465,7 +465,7 @@ connects to the compositor at `127.0.0.1:<vnc_port>`.
|
|||
Same reasoning as the best-effort oneshots in `docs/process/conventions.md`.
|
||||
- **`[core] idle-time=0`**: disables weston's 300-second idle
|
||||
timeout. Without it the VNC desktop fades to black and
|
||||
desktop-shell shows its click-to-unlock screen — useless for an
|
||||
desktop-shell shows its unlock screen — useless for an
|
||||
agent desktop viewed over `/screen`. `idle-time=0` updates the
|
||||
idle timer with a 0ms delay, which
|
||||
`wl_event_source_timer_update` treats as "disarm," so the
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ internals, container design, and the full security writeup.
|
|||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
Several jobs run on every PR (and on `workflow_dispatch` for manual
|
||||
The jobs run on every PR (and on `workflow_dispatch` for manual
|
||||
re-triggers), defined in
|
||||
[`.forgejo/workflows/ci.yml`](../../.forgejo/workflows/ci.yml). The first four
|
||||
below are required checks (forge branch protection) — a hit on any of them
|
||||
|
|
@ -270,7 +270,7 @@ A malicious `default.nix` or build script in a PR can therefore:
|
|||
|
||||
No forge admin token enters the container: swarm-controller holds it and publishes only the registration token, which only `swarm-ci-runner-register.service` loads, so a job step can't read it. A build process can still reach the forge over the network, and it runs as the runner's own user, so it can read `.runner` and act as this runner; it can't issue admin API calls.
|
||||
|
||||
Note: `nix flake check --no-build` (eval-only) reduces the attack surface but doesn't eliminate it — `builtins.fetchGit`, `builtins.fetchurl`, and import-from-derivation can reach the network and filesystem during evaluation. The CI workflow's `nix flake check` job builds every check derivation, which is the higher-risk path.
|
||||
Note: `nix flake check --no-build` (eval-only) reduces the exposure but doesn't eliminate it — `builtins.fetchGit`, `builtins.fetchurl`, and import-from-derivation can reach the network and filesystem during evaluation. The CI workflow's `nix flake check` job builds every check derivation, which is the higher-risk path.
|
||||
|
||||
### Mitigation
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ resource/lease semantics).
|
|||
|
||||
hive-c0re submits every container operation (rebuild, first-spawn, power
|
||||
changes) to the global job-DAG queue (`hive-c0re/src/job_queue/`)
|
||||
as a **DAG of primitive nodes**. One scheduler task drives all DAGs;
|
||||
as a **DAG of basic nodes**. One scheduler task drives all DAGs;
|
||||
concurrency comes from the resource classes below, not from multiple workers.
|
||||
Special cases like graceful stop, deferred starts, and the boot sweep
|
||||
Exceptions like graceful stop, deferred starts, and the boot sweep
|
||||
need no bespoke code paths — each takes the shape of a DAG built
|
||||
from the same primitive nodes.
|
||||
from the same basic nodes.
|
||||
|
||||
### Two levels: DAG and node
|
||||
|
||||
|
|
|
|||
|
|
@ -273,13 +273,13 @@ X" string to set, so mapping every level takes one rule each. A level button
|
|||
then filters on `level` **or** the matching `severity_text`, and the store
|
||||
answers the second half. Each enabled rule appends an `OR
|
||||
<field>:<op>"<value>"` term to the query a level button emits, beside the
|
||||
`level:…` term that matches nothing here. Clicking "info" goes from
|
||||
`level:…` term that matches nothing here. Selecting "info" goes from
|
||||
|
||||
```
|
||||
level:contains_common_case("info","information","informational","notice")
|
||||
```
|
||||
|
||||
to that OR `severity_text:="INFO"`, which our rows do match.
|
||||
to that OR `severity_text:="INFO"`, which the rows here do match.
|
||||
|
||||
`Unspecified` is deliberately left out of those rules. It's VictoriaLogs' own
|
||||
rendering of an absent severity, and it's what the **Log rows with no
|
||||
|
|
@ -684,6 +684,6 @@ unaffected either way; gauges have no temporality. The hive-tier collector
|
|||
runs a `deltatocumulative` processor ahead of export, so a delta
|
||||
`hive-metric` counter still lands in VictoriaMetrics as a cumulative
|
||||
series — the standard `rate()`/`increase()` idioms work on it exactly like
|
||||
any other counter in this system, no special query needed.
|
||||
any other counter in this system, no extra query needed.
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ them, and the notification router, not the controller, decides what they mean.
|
|||
|
||||
A `config-pr` delivery reporting a PR merged into `main` queues a deploy
|
||||
of its `merge_commit_sha` on the one hive whose wanted state places the
|
||||
agent; with no such hive, or several, the controller deploys nothing. See
|
||||
agent; with no such hive, or more than one, the controller deploys nothing. See
|
||||
[config-changes.md § Config changes](../agent-lifecycle/config-changes.md#config-changes).
|
||||
A merge whose `closed` delivery never arrives deploys nothing either; the
|
||||
operator recovers by redelivering that delivery from the forge hook page,
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ constrain what a policy says. What bounds it:
|
|||
restart, with the keys `init` printed.
|
||||
|
||||
⚠️ **A sealed store still answers.** The container is up and the port
|
||||
responds while every read times out — the failure looks like a hang, not like
|
||||
responds while every read times out — the failure looks like a stall, not like
|
||||
a store that was never initialised.
|
||||
|
||||
## TLS
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ A flow is a graph of nodes joined by edges: one `source` node naming the forge
|
|||
event types it starts from, `match` nodes that pass when every condition
|
||||
holds, `todo` nodes that emit one todo op per recipient, and `request_reviewer`
|
||||
nodes that ask for a review. A match node can have more than one child, and
|
||||
each one runs, so one event can reach several leaves. A flow must be a tree:
|
||||
each one runs, so one event can reach more than one leaf. A flow must be a tree:
|
||||
one source, one parent for every other node, every node reachable, no children
|
||||
under a `todo` or a `request_reviewer`. The most is 64 nodes, 16
|
||||
levels deep, and 100 custom flows. A `todo` node sends to the agents an event
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ publishes it as
|
|||
It answers only swarm-controller's OIDC client
|
||||
(`swarm.controller.queueClientId`) and refuses every other token `403`.
|
||||
|
||||
On first boot this module seeds the users database with a disabled placeholder subject, so authelia has a non-empty store to start against before any real account exists (`swarm-authelia.nix:873`). Authelia generates session and storage keys in the container on
|
||||
On first boot this module seeds the users database with an inactive placeholder subject, so authelia has a non-empty store to start against before any real account exists (`swarm-authelia.nix:873`). Authelia generates session and storage keys in the container on
|
||||
first boot and never rotates them automatically; replacing one
|
||||
invalidates data already written (sessions, the encrypted store), so
|
||||
that's an operator action.
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ sign-out pages; the hive dashboard and the per-agent page have the same menu.
|
|||
|
||||
Every dropdown (a form's select, the refresh interval, the history window) opens a
|
||||
list in the swarm UI's own theme, not the browser's, and works the same in every
|
||||
current browser. Open it with a click, or with the arrow keys, **Enter** or
|
||||
current browser. Open it with a press, or with the arrow keys, **Enter** or
|
||||
**Space** while it has focus. Then the arrow keys, **Home**, **End**, **Page Up**
|
||||
and **Page Down** move through the options, and **Enter**, **Space** or a click take
|
||||
the highlighted one. **Escape**, **Tab** or a click elsewhere shut the list without
|
||||
and **Page Down** move through the options, and **Enter**, **Space** or a press take
|
||||
the highlighted one. **Escape**, **Tab** or a press elsewhere shut the list without
|
||||
changing anything. Typing the start of an option's name picks it, also with the list
|
||||
shut. A dropdown inside a dialog opens above the dialog and the dialog doesn't cut it off.
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ shut. A dropdown inside a dialog opens above the dialog and the dialog doesn't c
|
|||
| `/alerts` | the alerts the swarm's Grafana holds now: the firing ones, with a button for the pending, no-data and error ones and a link to Grafana's own alert list; read through the controller with a Viewer service-account token |
|
||||
| `/jobs` | the controller's job graph — where agent creation and credential mints show progress |
|
||||
| `/schedules` | the scheduled prompts: add, edit, pause, resume and remove |
|
||||
| `/messages` | the swarm-wide message feed: every message between agents, and to them from the operator, reminders and compaction, with a history window and a filter on sender or recipient; a folded **broadcast** card above the feed sends one message to several agents at once |
|
||||
| `/messages` | the swarm-wide message feed: every message between agents, and to them from the operator, reminders and compaction, with a history window and a filter on sender or recipient; a folded **broadcast** card above the feed sends one message to more than one agent at once |
|
||||
| `/notifications` | the notification router's flows: a switch for each built-in, every flow drawn as a graph, and an editor for custom flows |
|
||||
| `/issues` | a cross-repo issue report |
|
||||
| `/review` | the review classifier: its recent runs, a try-out on a real PR, and its settings |
|
||||
|
|
@ -488,7 +488,7 @@ its newest 100 builds, so a link to an older one shows a note instead.
|
|||
|
||||
The messages page (`/messages`) has a **broadcast** card above the message list. It
|
||||
starts folded; select its header to open it. The card holds a composer that sends one message
|
||||
to several agents at once, and the messages show up in the list below as they
|
||||
to more than one agent at once, and the messages show up in the list below as they
|
||||
go. Folding it again keeps what you typed and ticked. Pick the
|
||||
agents from a grid of their icons. **running** shows the agents that report
|
||||
themselves running and **all** shows every agent; the browser keeps the choice.
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ distinct output shape — pick by what you need:
|
|||
Rule of thumb: **`view` first** when you're about to act on a thread (it
|
||||
shows everything and clears the unread guard so your follow-up `comment`
|
||||
isn't rejected); the JSON verbs (`issue`/`pr`) when a script needs one
|
||||
field; `pr status` when the only question is "can I merge it."
|
||||
field; `pr status` when the only question is whether it can merge.
|
||||
|
||||
### Contributing to a read-only repo (`clone` + `pr create --agit`)
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue