Skip to content
Merged
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
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Kapi Action

A GitHub Action that runs [kapi](https://github.com/neokapi/neokapi) commands — converge translations, gate content quality, plan cost — and delivers the results — as a commit, a pull request, or a report on the PR that caused the work.
A GitHub Action that runs [kapi](https://github.com/neokapi/neokapi) commands — catch up translations, gate content quality, plan cost — and delivers the results — as a commit, a pull request, or a report on the PR that caused the work.

## Prerequisites

Expand All @@ -10,7 +10,7 @@ This action requires the `kapi` CLI to be installed. Use [`neokapi/setup-kapi@v1

### Bring translations up to date

`kapi up` is the convergence verb, and the Action's default. In a server-connected project — a recipe with a `server:` block — it pushes, converges on the Bowrain server (org keys, shared TM, team review), and pulls the produced targets back. With no server it runs the same loop locally.
`kapi up` runs the kapi loop, and is the Action's default. In a server-connected project — a recipe with a `server:` block — it pushes, catches up on the Bowrain server (org keys, shared TM, team review), and pulls the produced targets back. With no server it runs the same loop locally.

```yaml
name: Translations
Expand All @@ -35,12 +35,12 @@ jobs:

### Outcomes

A convergence run ends in one of three states, and the Action treats them differently:
A `kapi up` run ends in one of three states, and the Action treats them differently:

| Run state | What it means | What the Action does |
|---|---|---|
| **converged** | Every gated scope cleared its ship gate | Delivers the produced translations |
| **parked** | Work remains that the loop could not carry to the gate (a failing check, an unreachable gate) | Delivers what *did* converge, and annotates the run with the parked locales. This is normal pending work, not a failure |
| **converged** | Every gated scope cleared its ship gate — the project is up to date | Delivers the produced translations |
| **parked** | Work remains that the loop could not carry to the gate (a failing check, an unreachable gate) | Delivers what it *did* catch up, and annotates the run with the parked locales. This is normal pending work, not a failure |
| **failed / canceled** | The run broke (a provider outage, a server error, a cancel) | `kapi up` exits non-zero, the step fails, **nothing is delivered** |

Parked is the interesting one: partial progress is real progress, so the default is to deliver it and warn rather than throw it away. To block instead:
Expand All @@ -51,7 +51,7 @@ Parked is the interesting one: partial progress is real progress, so the default
fail-on-parked: "true"
```

### How convergence works
### How the loop works

`kapi up` treats the recipe as the desired state — the languages the project targets, and the ship gates that define *shippable* — and reconciles the content toward it. Each pass, for every language behind its gate:

Expand All @@ -68,15 +68,15 @@ flowchart LR
TM["1 · reuse<br/>TM exact matches"] --> AI["2 · translate<br/>AI + terminology"] --> CK["3 · check<br/>placeholders · terms · tags"]
end
U --> PASS
CK -->|every gate clear| CV["converged<br/>PR with translations"]
CK -->|every gate met| CV["up to date<br/>PR with translations"]
CK -->|needs a person| PK["parked<br/>the review queue"]
PK --> RV["review & approve<br/>recorded in .kapi-state.json"]
RV -.->|next run sees it| U
```

**Parked work is the review queue, not an error.** What the machine couldn't decide waits for a person: review the wording, approve or fix it, and the decision is recorded — in the committed `.kapi-state.json` state store, or on the connected server. Approvals raise the `reviewed` coverage the ship gate measures, so the next run and the next gate see them. `kapi check --ship` (see [Gate pull requests](#gate-pull-requests-on-content-quality)) is what enforces the bar at release time.

The convergence report (outcome, passes, parked locales) is always written to the job summary. Under the hood the Action runs `kapi up --json`, an NDJSON stream — one convergence event per line, closed by a single `{"type":"result", ...}` record. That record is the contract; the events are the log. It becomes the `outcome`, `passes`, and `parked-locales` outputs.
The kapi up report (outcome, passes, parked locales) is always written to the job summary. Under the hood the Action runs `kapi up --json`, an NDJSON stream — one convergence event per line, closed by a single `{"type":"result", ...}` record. That record is the contract; the events are the log. It becomes the `outcome`, `passes`, and `parked-locales` outputs.

### Deliver as a pull request

Expand All @@ -93,11 +93,11 @@ steps:
create-pull-request: "true"
```

The created PR carries the convergence report in its description. `pr-title`, `pr-labels`, `pr-base`, and `branch-prefix` tune it; labels are applied best-effort (a label that doesn't exist in the repo never fails the run). The PR URL lands in the `pull-request-url` output.
The created PR carries the kapi up report in its description. `pr-title`, `pr-labels`, `pr-base`, and `branch-prefix` tune it; labels are applied best-effort (a label that doesn't exist in the repo never fails the run). The PR URL lands in the `pull-request-url` output.

### Plan mode: the cost of a change, on its PR

`plan: "true"` dry-runs the convergence loop — pending work, TM leverage, and a token estimate, with no writes and no provider calls (so it needs no API keys). With `pr-comment: "true"` on a pull-request event, the plan lands as one sticky comment that re-runs update in place:
`plan: "true"` dry-runs the kapi loop — pending work, TM leverage, and a token estimate, with no writes and no provider calls (so it needs no API keys). With `pr-comment: "true"` on a pull-request event, the plan lands as one sticky comment that re-runs update in place:

```yaml
name: Translation plan
Expand Down Expand Up @@ -153,7 +153,7 @@ Ordinary builds never fail on target-language drift — a locale that is behind

### Run any other kapi command

`command` takes any kapi subcommand — the Action stays a general runner. The convergence outputs are only populated for `up`.
`command` takes any kapi subcommand — the Action stays a general runner. The loop outputs (`outcome`, `passes`, `parked-locales`) are only populated for `up`.

```yaml
- uses: neokapi/kapi-action@v1
Expand All @@ -169,7 +169,7 @@ This runs `kapi run -p myproject.kapi translate`.

### Caching

Convergence is incremental via the project's `.kapi/cache` (block store, extractions), which is gitignored and therefore rebuilt on every fresh runner. Restore it across runs to skip re-extraction:
The loop runs incrementally via the project's `.kapi/cache` (block store, extractions), which is gitignored and therefore rebuilt on every fresh runner. Restore it across runs to skip re-extraction:

```yaml
- uses: actions/cache@v5
Expand All @@ -179,7 +179,7 @@ Convergence is incremental via the project's `.kapi/cache` (block store, extract
restore-keys: kapi-cache-
```

Server-connected projects don't need this — the convergence state lives on the server.
Server-connected projects don't need this — the project state lives on the server.

## Inputs

Expand Down
18 changes: 9 additions & 9 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: "Kapi Run"
description: "Run kapi commands — converge translations, gate content quality, plan cost — and deliver the results as a commit or pull request"
description: "Run kapi commands — catch up translations, gate content quality, plan cost — and deliver the results as a commit or pull request"
branding:
icon: "refresh-cw"
color: "blue"
Expand Down Expand Up @@ -28,7 +28,7 @@ inputs:
description: >-
With `command: up`, fail the workflow when the run parks (work remains that
the loop could not carry to the ship gate). Parked is normal pending work,
not a broken run, so the default is to commit what did converge and
not a broken run, so the default is to commit what it caught up and
annotate the rest.
required: false
default: "false"
Expand Down Expand Up @@ -65,7 +65,7 @@ inputs:
pr-comment:
description: >-
On pull-request events, post one sticky comment with the report (plan,
convergence outcome, or gate result) that re-runs update in place.
`kapi up` outcome, or gate result) that re-runs update in place.
Needs `permissions: pull-requests: write`.
required: false
default: "false"
Expand Down Expand Up @@ -212,8 +212,8 @@ runs:
exit 0
fi

# `kapi up` is the convergence verb: in a server-connected project it
# pushes, converges on the Bowrain server, and pulls the produced targets
# `kapi up` runs the kapi loop: in a server-connected project it
# pushes, catches up on the Bowrain server, and pulls the produced targets
# back; with no server it runs the same loop locally. Under --json it is
# an NDJSON stream — one convergence event per line, closed by a single
# {"type":"result", ...} record. That record is the CI contract; the
Expand Down Expand Up @@ -271,7 +271,7 @@ runs:
} >> "$GITHUB_OUTPUT"

{
echo "## kapi up — convergence report"
echo "## kapi up report"
echo
echo "| | |"
echo "|---|---|"
Expand All @@ -282,7 +282,7 @@ runs:

echo "Run ${OUTCOME} after ${PASSES} pass(es)."
if [ "$OUTCOME" = "parked" ]; then
# Parked is pending work, not a broken run: what did converge is real
# Parked is pending work, not a broken run: what it caught up is real
# progress and still gets committed below.
echo "::warning::Translations parked${PARKED:+ for: ${PARKED}} — work remains that the loop could not carry to the ship gate."
if [ "$FAIL_ON_PARKED" = "true" ]; then
Expand Down Expand Up @@ -382,7 +382,7 @@ runs:
echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"

BODY="<!-- kapi-convergence-report -->
## kapi up — convergence report
## kapi up report

| | |
|---|---|
Expand Down Expand Up @@ -447,7 +447,7 @@ runs:
${HEAD}"
elif [ -n "$OUTCOME" ]; then
BODY="${MARKER}
## kapi up — convergence report
## kapi up report

| | |
|---|---|
Expand Down
Loading