diff --git a/README.md b/README.md index 099abcb..b9a1f78 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Get your API token at [app.garnet.ai](https://app.garnet.ai). Start with the Act />

-

The action's own comment shape (renderer v6.9.5); the companion GitHub App comment adds true coverage and cross-run comparison.

+

The action's own comment shape. The renderer emits contract v6.10.0; this capture is from v6.9.5, before the meta block split into a finding line and a quiet provenance line. The companion GitHub App comment adds true coverage and cross-run comparison.

## What Garnet sees @@ -145,7 +145,7 @@ Full installation guides for every path are in the [Garnet docs](https://docs.ga One comment per PR, one fold per job, updated in place as each job's profile lands: - **Headline** — `Execution Profiles recorded for N job(s), triggered by `, linking the commit. -- **Metadata line** — an italic blockquote: `N destinations · recorded at the kernel by Garnet · `, one fact per `·` segment. +- **Meta block** — two blockquote lines. The italic finding line first: `N destinations` on a first record, the job segments and `compared with ` on a comparison, `No changes since ` when nothing moved. Then one quiet line: `recorded at the kernel by Garnet · `, at minute precision. One fact per `·` segment. - **One fold per job** — headed `workflow / job ↗ · N destinations`, the job id linking to its Actions run. Inside: one block holding every recorded root of the job's tree; independent roots are separated by a blank line. Plain tree nodes are recorded process names; observed actions render as shaped terminals — `○ destination` for network, defanged at the final dot. A process with an action directly beneath it renders **bold**; `(…)` brackets carry factual context only — `(step: "Run tests")`, `(dns resolver)`, `(cloud metadata)`, `(github infra)`, `(garnet sensor)`, `(ran from /tmp/…)`. A job with no recorded egress stays a plain row keeping its Garnet profile link. - **Per-job permalink** — `View this job's Execution Profile in Garnet →`, opening the job's [public run report](https://app.garnet.ai/public/runs/31257440827?profile=019fe15d-b34f-7803-820a-ecf58404a278) (`?profile=` selector required — a bare run URL returns 404). - **The explainer** — a `💡 How to read this` fold at the bottom teaches the tree with an annotated example: @@ -163,6 +163,8 @@ names on the path = processes · ○ = observed action · (…) = context Once a pull request has two recorded commits, the comment compares against the previous profiled commit: the metadata line carries `compared with `, changed job rows lead with the bold delta (`+1 −2 destinations`), unchanged rows read `· N destinations · unchanged`, and a changed job's tree renders as a diff headed `@@ (previous) vs (current) @@`. `+` marks a destination only in the current record, `−` one only in the previous record; the marks and the row's delta always reconcile exactly. Jobs recorded previously but not on this commit sit in one collapsed `jobs no longer recorded` fold with their destination counts. +The deltas on the meta line and on the fold rows count your workflow's destinations. Movement in the runner's own background is counted where it happened: the root line above those marks carries `(runner background · +A −B)`, so every mark stays visible and every number counts what sits beneath it. + The same full-detail record is appended to the GitHub Actions Job Summary as the **Garnet Execution Summary** (see this [example run](https://github.com/garnet-org/action/actions/runs/23175135499)). ## Under the hood @@ -183,6 +185,12 @@ The same full-detail record is appended to the GitHub Actions Job Summary as the | `debug` | No | `false` | Enable debug mode and upload logs as artifacts | | `preview` | No | `false` | Render the full-fidelity Step Summary record (assertions + evidence); preview shape is unstable and may change without a major version bump | +### Environment variables + +| Variable | Default | Description | +| ------------------------------------- | ------- | -------------------------------------------------------------------------------------------------- | +| `GARNET_JIBRIL_STOP_TIMEOUT_SECONDS` | `1800` | Seconds the Jibril systemd unit gets to flush its events on stop. The main step writes it as a `TimeoutStopSec` drop-in; the post step reads the unit's effective value and bounds its own wait to it. Raise it for long jobs whose profile goes missing after a stop. | + ¹ Required at runtime, with one exception: on `pull_request` runs from forked repositories, GitHub exposes no secrets, so the action emits a notice, skips recording, and the job continues. An OIDC alternative is landing behind the `GARNET_ACTION_ENABLE_OIDC_AUTH` flag; until that flag is on, the token is the auth path. --- diff --git a/docs/runtime-review-v6.2.md b/docs/runtime-review-v6.2.md index 44bce29..8524a42 100644 --- a/docs/runtime-review-v6.2.md +++ b/docs/runtime-review-v6.2.md @@ -1,8 +1,37 @@ -# Runtime Review v6.2 — surfaces, framing, and the preview flag +# Runtime Review v6.2 — historical record of the v6.1 → v6.2 step -Contract source of truth: `garnet-org/runtime-review-testbed` `docs/ux-contract.md` -(v6.2). The testbed's byte-gated goldens are the spec; this action's renderer -(`src/runtime-review.js`) is a port of the testbed reference renderer. +Status: **superseded.** The contract has moved to v6.10.0. This page is kept +for the reasoning behind the v6.2 step, not as a description of what the +action renders today. + +Contract source of truth: `garnet-org/runtime-review-testbed` +`contract/vocab.json` **6.10.0** + `docs/ux-contract.md`. The testbed's +byte-gated goldens are the spec. This action's renderer +(`src/runtime-review.js`) is a port of the testbed reference renderer and +vendors the contract byte-identically as `src/runtime-review-vocab.js`; read +that file for the strings the renderer actually emits. + +## What v6.10.0 says instead + +Everything in the "What changed in the PR comment" section below is +superseded. The current shape: + +- Headline: `**Execution Profiles recorded for N job(s), triggered by + **` — bold body text, no heading, no product name. +- Meta block: two blockquote lines. The italic finding line first (the + destination total, or the job segments and `compared with `, or + `No changes since `), then one quiet line + `recorded at the kernel by Garnet · ` at minute precision. The + words `as of` no longer render. +- One fold per job, one block per fold, holding every recorded root of that + job. Fold rows carry `· N destination(s)`; changed rows lead with a bold + `+A −R` split that counts your workflow's destinations. Movement in the + runner's background is counted by a `(runner background · +A −B)` label on + the root above those marks. +- Observed actions render as `○ ` leaves. The explainer teaches + one execution chain: a path from a root down to an observed action. +- Fold summaries carry counts and identity only — the `reached` sentence is + gone. ## Two surfaces, one renderer @@ -13,7 +42,7 @@ Contract source of truth: `garnet-org/runtime-review-testbed` `docs/ux-contract. It is a faithful, readable projection of the Run Profile artifact: could you reconstruct the profile's story from it? That is the test it must pass. -## What changed in the PR comment (v6.1 → v6.2) +## What changed in the PR comment (v6.1 → v6.2) — superseded, see above - Marker block: canonical marker, self marker, then ``. - Actor-conditional heading: standalone mode (this action, `github-actions[bot]`) @@ -32,7 +61,7 @@ Contract source of truth: `garnet-org/runtime-review-testbed` `docs/ux-contract. absent in the waiting state. - Job fold summaries use the verb **reached** (never `contacted`). -## Step Summary: delta vs Djalal's markdown printer (jibril) +## Step Summary: delta vs Djalal's markdown printer (jibril) — v6.2 shape Djalal's most recent Go markdown printer (`pkg/printers/profiler/markdown.go`, "Garnet - Runtime Report") was destination-first and full-fidelity: Profile @@ -41,8 +70,10 @@ telemetry — but it also carried verdict framing (✅/❌ headline, per-row sta icons, bad-first sorting) and a lossy remote-name dedupe ("omitted destinations"). -The v6.x Step Summary restores Djalal's faithful-record shape while removing -only the verdict framing: +The v6.2 Step Summary restored Djalal's faithful-record shape while removing +only the verdict framing. The v6.10.0 Step Summary keeps that intent, but the +table is lineage-first (`Process Tree | Destinations`), not the +destination-first table described here: - Egress table is **destination-first** (`Destination | Port | Lineage Tree`), one row per recorded destination in the profile's own @@ -77,6 +108,6 @@ with their own fixtures so prod bytes cannot drift while preview evolves. The action renders from the JSON Run Profile, so jibril's own Go markdown printer output ("Garnet - Runtime Report", ✅/❌ headline, `contacted`) is no longer user-visible through this action — no runtime coupling breaks. If that -printer's output resurfaces on a user-facing path, it should adopt the v6.2 -`VOCAB` strings. Ashkaal is the schema layer (field names) and is untouched by +printer's output resurfaces on a user-facing path, it should adopt the +contract strings vendored in `src/runtime-review-vocab.js`. Ashkaal is the schema layer (field names) and is untouched by renderer vocabulary. diff --git a/docs/tokenless-path-spec.md b/docs/tokenless-path-spec.md index f6046d6..f3c6729 100644 --- a/docs/tokenless-path-spec.md +++ b/docs/tokenless-path-spec.md @@ -1,30 +1,47 @@ # Tokenless path for the Garnet Action — design spec (draft) -Status: **draft for review** — no product code changes in this PR. +Status: **draft, not implemented.** Read it as a design proposal, not as +behavior. Two things have moved under it since it was written: + +- The contract of record is now `garnet-org/runtime-review-testbed` + `contract/vocab.json` **6.10.0** + `docs/ux-contract.md`, vendored in this + repo as `src/runtime-review-vocab.js`. Every v6.1/v6.2 string and section + reference below is stale. The v6.2 amendment this spec asks for was never + ratified: 6.10.0 contains no tokenless, local-only, or upgrade-CTA + vocabulary. The permalink it calls + `View Run Profile in Garnet ↗` is today + `View this job's Execution Profile in Garnet →`, and the record is an + Execution Profile, not a Run Profile. +- `api_token` is already `required: false` in `action.yaml` (§3 landed), but + the local-only branch did not: `src/action.js` still throws + "Input 'api_token' is required…" when neither a token nor OIDC produces + control-plane auth. The fork-PR path taken since is OIDC behind + `GARNET_ACTION_ENABLE_OIDC_AUTH`, not the tokenless mode described here. Tracking: [ENG-1329](https://linear.app/garnet-labs/issue/ENG-1329/tokenless-path-for-github-action) (tokenless path) and the fallback half of [ENG-1346](https://linear.app/garnet-labs/issue/ENG-1346) (simpler comment shape + token-optional local-only fallback). Sequenced against [ENG-1355](https://linear.app/garnet-labs/issue/ENG-1355) (v6.x renderer port -to this repo; ENG-1345 was canceled into it). Contract of record: -`garnet-org/runtime-review-testbed` `docs/ux-contract.md` **v6.1** (testbed -PRs #52/#53/#55/#59). Prior analysis: Devin session +to this repo; ENG-1345 was canceled into it). Contract of record when this +spec was written: `garnet-org/runtime-review-testbed` `docs/ux-contract.md` +**v6.1** (testbed PRs #52/#53/#55/#59). Prior analysis: Devin session `022557ef6b7d4534b9c5085147f23d67` (`token-optional-and-plg-review.md`) and testbed `docs/step-summary.md` §"Tokenless-by-default fallback". ## 1. Motivation (PLG: value before signup) -Today `api_token` is `required: true` and the main step throws when it is -empty (`src/action.js` — "Input 'api_token' is required…"). The two biggest +When this spec was written `api_token` was `required: true` and the main step +threw when it was empty (`src/action.js` — "Input 'api_token' is required…"). +The input is optional now; the throw is still there. The two biggest consequences: - **Adoption friction**: a user must sign up, create a project, copy a token, and add a repo secret *before first value*. The README one-liner cannot be a one-liner. - **Fork PRs always fail**: forks never receive repository secrets, so the - action degrades to "no runtime monitoring" on exactly the PRs where an - OSS maintainer most wants runtime evidence. + action records nothing on exactly the PRs where an OSS maintainer most + wants runtime evidence. The goal: `uses: garnet-org/action@v2` with **no inputs** produces a complete local Runtime Review — GitHub Step Summary always, standalone PR comment when