Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Get your API token at [app.garnet.ai](https://app.garnet.ai). Start with the Act
/>
</p>

<p align="center"><sub>The action's own comment shape (renderer v6.9.5); the companion GitHub App comment adds true coverage and cross-run comparison.</sub></p>
<p align="center"><sub>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.</sub></p>

## What Garnet sees

Expand Down Expand Up @@ -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 <sha7>`, linking the commit.
- **Metadata line** — an italic blockquote: `N destinations · recorded at the kernel by Garnet · <UTC timestamp>`, 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 <sha7>` on a comparison, `No changes since <sha7>` when nothing moved. Then one quiet line: `recorded at the kernel by Garnet · <UTC timestamp>`, 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:
Expand All @@ -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 <sha7>`, 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 sha7> (previous) vs <sha7> (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
Expand All @@ -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.

---
Expand Down
51 changes: 41 additions & 10 deletions docs/runtime-review-v6.2.md
Original file line number Diff line number Diff line change
@@ -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
<sha7>**` — 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 <sha7>`, or
`No changes since <sha7>`), then one quiet line
`recorded at the kernel by Garnet · <timestamp>` 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 `○ <destination>` 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

Expand All @@ -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 `<!-- garnet:commit {full sha} -->`.
- Actor-conditional heading: standalone mode (this action, `github-actions[bot]`)
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
33 changes: 25 additions & 8 deletions docs/tokenless-path-spec.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down