@kici-dev/compiler 0.5.0 → 0.6.1
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/dist/cli.js +46 -8
- package/dist/commands/approve.d.ts +12 -0
- package/dist/commands/approve.js +5 -2
- package/dist/commands/compile.js +4 -2
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/endpoints.js +4 -6
- package/dist/commands/feedback.d.ts +53 -0
- package/dist/commands/feedback.js +142 -0
- package/dist/commands/held-run-client.d.ts +21 -1
- package/dist/commands/held-run-client.js +34 -15
- package/dist/commands/hook.js +22 -20
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +3 -1
- package/dist/commands/init.d.ts +9 -2
- package/dist/commands/init.js +43 -16
- package/dist/commands/login.js +1 -1
- package/dist/commands/orchestrators.js +3 -2
- package/dist/commands/reject.d.ts +12 -0
- package/dist/commands/reject.js +5 -2
- package/dist/commands/report/collect.d.ts +82 -0
- package/dist/commands/report/collect.js +234 -0
- package/dist/commands/report/identity.d.ts +48 -0
- package/dist/commands/report/identity.js +49 -0
- package/dist/commands/report/index.d.ts +63 -0
- package/dist/commands/report/index.js +119 -0
- package/dist/commands/report/upload.d.ts +38 -0
- package/dist/commands/report/upload.js +64 -0
- package/dist/commands/run-hold-watch.js +2 -2
- package/dist/commands/run.js +6 -3
- package/dist/commands/runs/show.js +80 -1
- package/dist/commands/types.js +51 -8
- package/dist/execution/sdk-alias.js +4 -2
- package/dist/fixtures/compiler.js +2 -1
- package/dist/format.js +3 -3
- package/dist/generators/secrets-dts.d.ts +8 -2
- package/dist/generators/secrets-dts.js +3 -2
- package/dist/hooks/installer.js +2 -1
- package/dist/llm-context/llms-architecture.txt +35 -13
- package/dist/llm-context/llms-cli-remote.txt +2347 -0
- package/dist/llm-context/llms-cli.txt +284 -2470
- package/dist/llm-context/llms-features-execution.txt +2028 -0
- package/dist/llm-context/llms-features.txt +298 -1483
- package/dist/llm-context/llms-full.txt +6153 -4639
- package/dist/llm-context/llms-getting-started.txt +292 -12
- package/dist/llm-context/llms-patterns.txt +176 -1
- package/dist/llm-context/llms-providers.txt +11 -27
- package/dist/llm-context/llms-sdk-runtime.txt +25 -4
- package/dist/llm-context/llms-sdk.txt +31 -1
- package/dist/llm-context/llms.txt +33 -18
- package/dist/local-plane/paths.d.ts +15 -0
- package/dist/local-plane/paths.js +22 -1
- package/dist/local-plane/plane-manager.js +2 -2
- package/dist/local-plane/port-holder.js +1 -1
- package/dist/local-plane/postgres.d.ts +3 -16
- package/dist/local-plane/postgres.js +10 -15
- package/dist/lockfile/generator.d.ts +12 -0
- package/dist/lockfile/generator.js +47 -14
- package/dist/postinstall.js +2 -1
- package/dist/remote/config.d.ts +2 -15
- package/dist/remote/config.js +2 -16
- package/dist/remote/dashboard-client.d.ts +39 -0
- package/dist/remote/dashboard-client.js +41 -0
- package/dist/remote/oauth.js +7 -5
- package/dist/remote/uploader.js +2 -2
- package/dist/templates/package-json.js +1 -1
- package/dist/test-runner/dry-run.js +4 -2
- package/dist/test-runner/git-detector.js +2 -1
- package/dist/test-runner/job-executor.js +2 -1
- package/dist/test-runner/payload-builder.js +11 -17
- package/dist/types.d.ts +33 -3
- package/dist/validation/validator.js +23 -6
- package/package.json +16 -11
- package/sbom.spdx.json +953 -901
|
@@ -76,6 +76,8 @@ Trigger matching can query the **contents** of individual source files, not just
|
|
|
76
76
|
|
|
77
77
|
The orchestrator also does **not** run `dynamicJob` generator bodies itself: for the event-only (function) form it dispatches a dedicated dynamic-evaluation job to an agent at event time; the generator function then runs agent-side (see below).
|
|
78
78
|
|
|
79
|
+
A workflow-level `filter` predicate is the same shape: the orchestrator sees only the lock's `hasFilter` flag, never the predicate, so it dispatches an evaluation job and lets an agent decide whether the workflow applies. Prefer the declarative filters where they answer the question — `commitMessage` on the trigger and `requires` over source files cost no evaluation job at all.
|
|
80
|
+
|
|
79
81
|
See [dynamic values](https://docs.kici.dev/user/dynamic-values/) for how dynamic `context`, `env`, and `concurrencyGroup` functions resolve.
|
|
80
82
|
|
|
81
83
|
## Agent time
|
|
@@ -86,20 +88,33 @@ After dispatch, each job runs in its own ephemeral agent sandbox: a shallow clon
|
|
|
86
88
|
2. **Step-level rules**, then each step's `run()` body and its hooks.
|
|
87
89
|
3. **Dynamic values** (`context`, `env`, `concurrencyGroup` functions) are resolved here, via a short `__init__` job that runs the function before the real job runs; this shows in the run timeline as an `Init:` entry.
|
|
88
90
|
4. **`dynamicJob` generators run here — both forms.** The event-only (function) form runs in a dedicated evaluation job dispatched at event time; the result-aware (options) form is deferred until its declared `needs` complete, then run with the upstream outputs frozen as `ctx.needs`.
|
|
91
|
+
5. **A workflow-level `filter` predicate runs here too**, before the jobs it gates. A global workflow evaluates it once per (event × workflow repo), before any run row exists, so a `false` verdict leaves no run at all. A same-repo workflow evaluates it once per job that reaches dispatch and once per job generator, after the run row exists, so a `false` verdict leaves a run whose only entries are the evaluation jobs. Keep the predicate cheap, pure, and side-effect free — a ten-job workflow calls it ten times for one event. See [narrowing with a filter](https://docs.kici.dev/user/global-workflows/#narrowing-with-a-filter).
|
|
89
92
|
|
|
90
93
|
See [job execution](https://docs.kici.dev/architecture/execution/job-execution/) and [hooks and rules](https://docs.kici.dev/user/hooks/) for the details.
|
|
91
94
|
|
|
95
|
+
## How a reused agent stays clean between jobs
|
|
96
|
+
|
|
97
|
+
An ephemeral agent is discarded after one job, so residue never matters. A **reused agent** — a long-lived process on a shared host (the bare-metal profile) — serves many jobs in turn. Between them, the agent runs a supervisor-owned cleanup phase so one job's leftovers never reach the next:
|
|
98
|
+
|
|
99
|
+
1. **It reaps the finished job's process tree.** A step may background a daemon that outlives the job. The agent runs each job's process in its own process group and signals the whole group when the job ends, so a stray daemon does not survive into the next job. Set `KICI_AGENT_ORPHAN_CLEANUP=false` to keep only the runner and leave a backgrounded process alive on purpose.
|
|
100
|
+
2. **It re-runs declared cleanup after a hard kill.** A job's `cleanup` / `onFailure` hooks normally run in the job process. If that process is killed hard (out of memory, forced stop), the agent re-runs the declared cleanup against the preserved work directory.
|
|
101
|
+
3. **It deletes the work directory.**
|
|
102
|
+
4. **It runs an optional operator reset command.** Set `KICI_AGENT_BETWEEN_JOBS_RESET_COMMAND` to a host-reset command (for example, pruning a container cache). It runs after the reap and work-directory deletion. A failure never fails the finished job.
|
|
103
|
+
|
|
104
|
+
This phase is the primary cross-job cleanup. The agent's startup temp-directory sweep stays as a backstop for anything a between-jobs phase missed. See [agent configuration](https://docs.kici.dev/operator/agent/configuration/) for the full env-var reference.
|
|
105
|
+
|
|
92
106
|
## What re-evaluates where
|
|
93
107
|
|
|
94
|
-
| Construct | Runs on | When
|
|
95
|
-
| ---------------------------- | ---------------- |
|
|
96
|
-
| Static value | Compile → lock | Never re-evaluated
|
|
97
|
-
| Dynamic value | Agent init step | Per event
|
|
98
|
-
| Job-level rules | Agent | After clone
|
|
99
|
-
| Step-level rules | Agent | Per step
|
|
100
|
-
| `dynamicJob` (function form) | Agent (eval job) | Dispatched at event time
|
|
101
|
-
| `dynamicJob` (options form) | Agent | Deferred until `needs` complete
|
|
102
|
-
|
|
|
108
|
+
| Construct | Runs on | When |
|
|
109
|
+
| ---------------------------- | ---------------- | ---------------------------------------------------- |
|
|
110
|
+
| Static value | Compile → lock | Never re-evaluated |
|
|
111
|
+
| Dynamic value | Agent init step | Per event |
|
|
112
|
+
| Job-level rules | Agent | After clone |
|
|
113
|
+
| Step-level rules | Agent | Per step |
|
|
114
|
+
| `dynamicJob` (function form) | Agent (eval job) | Dispatched at event time |
|
|
115
|
+
| `dynamicJob` (options form) | Agent | Deferred until `needs` complete |
|
|
116
|
+
| Workflow `filter` predicate | Agent (eval job) | Per event (global) / per job + generator (same-repo) |
|
|
117
|
+
| Step / job body + hooks | Agent | Per job |
|
|
103
118
|
|
|
104
119
|
**Determinism note.** `ctx.event` and `ctx.needs` are frozen snapshots — captured once and replayed unchanged on any re-evaluation. A generator that derives its output from them is stable across re-evaluations; one that reads the wall clock (`Date.now()`) or a random source (`Math.random()`) is not.
|
|
105
120
|
|
|
@@ -149,6 +164,128 @@ Outputs are typed across the job boundary too: reading `jobRef.result.…` or `c
|
|
|
149
164
|
|
|
150
165
|
---
|
|
151
166
|
|
|
167
|
+
## Getting help
|
|
168
|
+
|
|
169
|
+
Source: https://docs.kici.dev/user/getting-help/
|
|
170
|
+
|
|
171
|
+
When something goes wrong, the fastest path to a fix is a report that already
|
|
172
|
+
carries the context. This page covers what to try first, what to send, and how
|
|
173
|
+
to send it privately.
|
|
174
|
+
|
|
175
|
+
## Diagnose it yourself first
|
|
176
|
+
|
|
177
|
+
Two commands answer most problems without anyone else involved:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Check your own setup: login, org, lock file, orchestrator, agent labels
|
|
181
|
+
kici doctor
|
|
182
|
+
|
|
183
|
+
# Look at the org's infrastructure: orchestrators, scalers, agents
|
|
184
|
+
kici diagnostics
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`kici doctor` prints the next command to run for each problem it finds. Work
|
|
188
|
+
down its output before reporting — a stale lock file or an expired login is a
|
|
189
|
+
one-command fix.
|
|
190
|
+
|
|
191
|
+
If your workflow ran and failed, read its logs:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
kici runs show <run-id>
|
|
195
|
+
kici runs logs <run-id>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
[Common failures](https://docs.kici.dev/user/common-failures/) covers the errors people hit most.
|
|
199
|
+
|
|
200
|
+
## Report a problem
|
|
201
|
+
|
|
202
|
+
When you cannot resolve it yourself, gather a diagnostic bundle:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
kici report --run <run-id> --message "what you expected, and what happened"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The command writes a ZIP and prints its path and `sha256`. It sends nothing.
|
|
209
|
+
The bundle holds:
|
|
210
|
+
|
|
211
|
+
- your CLI, Node, and orchestrator versions,
|
|
212
|
+
- your redacted KiCI configuration,
|
|
213
|
+
- your project's workflow list and lock-file state,
|
|
214
|
+
- the failing run's detail and logs, when you pass `--run`,
|
|
215
|
+
- a collection report saying which of those the command could and could not
|
|
216
|
+
read.
|
|
217
|
+
|
|
218
|
+
Open the file and read it. It is yours until you decide to share it.
|
|
219
|
+
|
|
220
|
+
### What gets redacted
|
|
221
|
+
|
|
222
|
+
KiCI removes known secret shapes before anything enters the bundle:
|
|
223
|
+
|
|
224
|
+
- API keys and access tokens (AWS, GitHub, Slack, KiCI agent tokens),
|
|
225
|
+
- `Authorization` headers and JSON web tokens,
|
|
226
|
+
- passwords inside connection URLs,
|
|
227
|
+
- private keys and encrypted-value blocks,
|
|
228
|
+
- values assigned to a secret-named key, such as `api_key=` or `password=`.
|
|
229
|
+
|
|
230
|
+
Configuration is redacted twice: an allowlist keeps only known-safe fields, and
|
|
231
|
+
the free-text scrubber runs over what remains.
|
|
232
|
+
|
|
233
|
+
**Redaction is best effort.** A secret in a format KiCI does not recognize can
|
|
234
|
+
survive it. Review the bundle before you share it. `--no-redact` turns
|
|
235
|
+
redaction off and prints a warning — use it only for a bundle you keep.
|
|
236
|
+
|
|
237
|
+
## Send it privately
|
|
238
|
+
|
|
239
|
+
Reports contain your data, so there is no public tracker for them. Add
|
|
240
|
+
`--upload` to send the bundle to KiCI directly:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
kici report --run <run-id> --upload --message "matrix job hangs on macOS"
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
A defect in KiCI itself is different: if you can reproduce it without your own
|
|
247
|
+
data — the docs promise something the tool does not do — it belongs in the
|
|
248
|
+
public tracker instead. See [Reporting a discrepancy](https://docs.kici.dev/user/reporting-discrepancies/).
|
|
249
|
+
|
|
250
|
+
The command prints a reference id. Quote it in any conversation about the
|
|
251
|
+
problem. The bundle goes straight from your machine to KiCI storage over a
|
|
252
|
+
one-time upload link — it never passes through the dashboard.
|
|
253
|
+
|
|
254
|
+
Add `--email` if you want a reply address attached to the report.
|
|
255
|
+
|
|
256
|
+
## Manage what you have sent
|
|
257
|
+
|
|
258
|
+
An upload is not permanent, and it is yours to revoke:
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# See the reports you have uploaded
|
|
262
|
+
kici report list
|
|
263
|
+
|
|
264
|
+
# Delete an uploaded bundle
|
|
265
|
+
kici report withdraw <ref>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Uploaded bundles expire automatically after 90 days.
|
|
269
|
+
|
|
270
|
+
Anyone in your organization can upload a report. By default you see and
|
|
271
|
+
withdraw your own. A member with the `support:admin` permission can manage
|
|
272
|
+
every report in the organization, which is how an owner cleans up on behalf of
|
|
273
|
+
someone who has left.
|
|
274
|
+
|
|
275
|
+
## Reporting a security issue
|
|
276
|
+
|
|
277
|
+
Do not use `kici report` for a suspected vulnerability. Follow the disclosure
|
|
278
|
+
process in [SECURITY.md](https://github.com/kici-dev/kici-public/blob/main/SECURITY.md)
|
|
279
|
+
instead.
|
|
280
|
+
|
|
281
|
+
## See also
|
|
282
|
+
|
|
283
|
+
- [Common failures](https://docs.kici.dev/user/common-failures/) — the errors people hit most, and their fixes
|
|
284
|
+
- [CLI reference](https://docs.kici.dev/user/cli-reference/) — every `kici` command
|
|
285
|
+
- [Dashboard](https://docs.kici.dev/user/dashboard/) — inspecting runs in the browser
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
152
289
|
## Getting started with workflows
|
|
153
290
|
|
|
154
291
|
Source: https://docs.kici.dev/user/getting-started/
|
|
@@ -171,11 +308,11 @@ npx kici init
|
|
|
171
308
|
|
|
172
309
|
This will:
|
|
173
310
|
|
|
174
|
-
1. Create `.kici/` directory with `workflows/`, `tests/`, `types/`, `package.json`, and `tsconfig.json`
|
|
311
|
+
1. Create `.kici/` directory with `workflows/`, `tests/`, `types/`, `package.json`, and `tsconfig.json`. The `types/` folder holds a local development aid — TypeScript declarations that `kici types` (and an authenticated `kici compile`) generate from your orchestrator's secret contexts. Its content is a snapshot of one org's secret keys, so it is not committed.
|
|
175
312
|
2. Create a `.kiciignore` file with sensible defaults
|
|
176
313
|
3. Let you choose from starter workflow templates (hello-world, pr-checks)
|
|
177
314
|
4. Install dependencies using the package manager detected for your repo (npm, pnpm, or yarn)
|
|
178
|
-
5. Update `.gitignore` to exclude `.kici/node_modules/`
|
|
315
|
+
5. Update `.gitignore` to exclude `.kici/node_modules/`, and write `.kici/.gitignore` to keep the generated `types/` declarations untracked (`kici.lock.json` stays tracked — the orchestrator fetches it from your repo)
|
|
179
316
|
6. Optionally install a pre-commit hook to auto-compile workflows
|
|
180
317
|
|
|
181
318
|
The package manager is detected from your repo's `packageManager` field, lockfile, or the manager that invoked `kici`, defaulting to npm. Pass `--package-manager <npm|pnpm|yarn>` to override it.
|
|
@@ -496,7 +633,7 @@ For coding agents that want the entire documentation set up front, KiCI follows
|
|
|
496
633
|
|
|
497
634
|
- `https://kici.dev/llms.txt` — curated link index grouped by SDK / patterns / CLI / architecture.
|
|
498
635
|
- `https://kici.dev/llms-full.txt` — concatenated markdown of every page indexed above.
|
|
499
|
-
- `kici docs llm` — print the same `llms
|
|
636
|
+
- `kici docs llm` — print the same curated `llms.txt` index to stdout, offline, straight from the installed `@kici-dev/compiler` package. `kici docs llm <topic>` prints one task bundle (`getting-started`, `patterns`, `sdk`, `sdk-runtime`, `cli`, `cli-remote`, `features`, `features-execution`, `providers`, `architecture`), and `kici docs llm full` prints the whole `llms-full.txt`. Add `--out <path>` to write to a file. The agent can pipe the output into its own context buffer with no network call.
|
|
500
637
|
- `kici docs` — open the docs site in your browser.
|
|
501
638
|
|
|
502
639
|
The offline bundle is regenerated from `docs/` every time the package is built, so it always matches the version of KiCI you've installed.
|
|
@@ -706,6 +843,12 @@ KiCI offers two equally-supported quickstart paths. Pick the one that fits your
|
|
|
706
843
|
|
|
707
844
|
Each guide is split into two parts. **Part 1** gets you a green run against your own orchestrator with `kici run remote` — no GitHub App needed, just sign up, bring up the stack, and run. **Part 2** then wires up real GitHub pushes so your team's commits trigger runs automatically. You can stop after Part 1 and come back to Part 2 whenever you're ready.
|
|
708
845
|
|
|
846
|
+
## Bring a coding agent
|
|
847
|
+
|
|
848
|
+
Workflows are TypeScript, so a coding agent can write them. KiCI ships its docs in a form an agent reads directly: point yours at [llms.txt](https://kici.dev/docs/llms.txt), or pipe a task bundle straight into its context with `kici docs llm` (`kici docs llm sdk` for the authoring API, `kici docs llm patterns` for recipes). An agent briefed that way can scaffold your first workflow, compile it, and read the failure when it breaks.
|
|
849
|
+
|
|
850
|
+
If your agent finds that these docs promise something KiCI does not do, that is worth telling us — `kici feedback` prints how to report it, and [Reporting a discrepancy](https://docs.kici.dev/user/reporting-discrepancies/) is the full guide.
|
|
851
|
+
|
|
709
852
|
## Option A — Docker / Podman (recommended)
|
|
710
853
|
|
|
711
854
|
Two containers brought up with `docker compose up -d` (orchestrator + PostgreSQL), plus one short-lived agent container spawned per job by the container scaler. Minimal host setup, perfect for a laptop, home server, or a tiny VM. No need to install PostgreSQL or any other system service.
|
|
@@ -736,6 +879,143 @@ Both quickstarts deploy a real orchestrator + agent. If you only want to write a
|
|
|
736
879
|
|
|
737
880
|
---
|
|
738
881
|
|
|
882
|
+
## Reporting a discrepancy
|
|
883
|
+
|
|
884
|
+
Source: https://docs.kici.dev/user/reporting-discrepancies/
|
|
885
|
+
|
|
886
|
+
This page is addressed to a **coding agent** working with KiCI. KiCI is built to
|
|
887
|
+
be driven by an LLM, so an agent is often the first to notice a mismatch. A
|
|
888
|
+
documented flag does not exist; a command prints something the docs never
|
|
889
|
+
promised. You can report that.
|
|
890
|
+
|
|
891
|
+
A human reader can use this page too. The rules below exist because the tracker
|
|
892
|
+
is public and you are filing under someone else's GitHub identity.
|
|
893
|
+
|
|
894
|
+
Run `kici feedback` to print this contract in your terminal, or
|
|
895
|
+
`kici feedback --json` to read it as structured data.
|
|
896
|
+
|
|
897
|
+
## The rule, in one sentence
|
|
898
|
+
|
|
899
|
+
You find a checkable mismatch between what the docs or the CLI advertise and
|
|
900
|
+
what KiCI actually does. You draft an issue carrying a reproduction and a
|
|
901
|
+
justification, and show it to the person you are working with. You file it only
|
|
902
|
+
after they say yes.
|
|
903
|
+
|
|
904
|
+
You never file on your own initiative.
|
|
905
|
+
|
|
906
|
+
## What qualifies
|
|
907
|
+
|
|
908
|
+
Report it when you can point at the claim and at the contradicting behaviour:
|
|
909
|
+
|
|
910
|
+
- A documented flag, command, or option that does not exist in the version you ran.
|
|
911
|
+
- Documented output — a shape, a field, an exit code — that differs from what the command produced.
|
|
912
|
+
- A CLI `--help` description that contradicts the published docs.
|
|
913
|
+
- A documented behaviour that does not happen, or a documented guarantee that does not hold.
|
|
914
|
+
- A documented error or limit that the tool does not actually enforce.
|
|
915
|
+
|
|
916
|
+
Two conditions apply to all of them. You ran the command and saw the result —
|
|
917
|
+
inference from reading the docs is not a reproduction. And you ran a published
|
|
918
|
+
version: check with `kici --version`.
|
|
919
|
+
|
|
920
|
+
## What does not qualify
|
|
921
|
+
|
|
922
|
+
- Usage questions, or behaviour you find surprising but that the docs describe correctly.
|
|
923
|
+
- Feature requests and design preferences.
|
|
924
|
+
- Anything you inferred from reading docs without running the command.
|
|
925
|
+
- Anything reproduced only on a locally built or unreleased version.
|
|
926
|
+
- A failure that is your workflow, your credentials, or your environment.
|
|
927
|
+
|
|
928
|
+
If you are unsure whether the docs are wrong or you misread them, you are not
|
|
929
|
+
ready to file. Say so to the person you are working with and let them decide.
|
|
930
|
+
|
|
931
|
+
## Never file these publicly
|
|
932
|
+
|
|
933
|
+
**A suspected vulnerability is never a public issue.** Do not file it, and do
|
|
934
|
+
not describe it in one. Open a private
|
|
935
|
+
[security advisory](https://github.com/kici-dev/kici-public/security/advisories/new)
|
|
936
|
+
instead, or tell the person you are working with to. This holds even if the
|
|
937
|
+
issue looks minor to you.
|
|
938
|
+
|
|
939
|
+
**A problem with someone's own runs is not a tracker issue.** That covers a
|
|
940
|
+
failing run, a broken deployment, and anything that needs their logs. Use the
|
|
941
|
+
private path in [Getting help](https://docs.kici.dev/user/getting-help/) instead:
|
|
942
|
+
`kici report --run <run-id> --upload` sends a redacted bundle straight to KiCI.
|
|
943
|
+
|
|
944
|
+
**Never put customer data in a public issue:**
|
|
945
|
+
|
|
946
|
+
- No secrets, tokens, or credentials — not even redacted-looking ones.
|
|
947
|
+
- No private repository names, internal hostnames, organization ids, or run ids.
|
|
948
|
+
- No log excerpts you have not read line by line.
|
|
949
|
+
- Reproduce with a minimal synthetic workflow, never the real one you were working on.
|
|
950
|
+
|
|
951
|
+
Rewriting the reproduction against a throwaway workflow in an empty directory is
|
|
952
|
+
the reliable way to satisfy all four at once.
|
|
953
|
+
|
|
954
|
+
## Search before you draft
|
|
955
|
+
|
|
956
|
+
The tracker is small. The same finding arriving once per agent that reads the
|
|
957
|
+
docs is worse than not hearing it at all:
|
|
958
|
+
|
|
959
|
+
```bash
|
|
960
|
+
gh issue list --repo kici-dev/kici-public --search "<terms>" --state all
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
Search closed issues too — a closed one may carry the answer, or the decision
|
|
964
|
+
that the behaviour is intended. If a matching issue is open, add your
|
|
965
|
+
reproduction as a comment instead of opening a second one, under the same
|
|
966
|
+
approval rule.
|
|
967
|
+
|
|
968
|
+
## What the report must carry
|
|
969
|
+
|
|
970
|
+
Five things. A report missing any of them cannot be acted on:
|
|
971
|
+
|
|
972
|
+
| Field | What it holds |
|
|
973
|
+
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
974
|
+
| What the docs or CLI advertise | The exact claim, quoted, plus its source: a docs URL or the command whose `--help` says it. |
|
|
975
|
+
| What actually happened | The real output or behaviour, quoted, with any error text. |
|
|
976
|
+
| Minimal reproduction, including setup | Every step from an empty directory: the setup commands, a minimal synthetic workflow, and the exact command you ran. |
|
|
977
|
+
| Version and environment | Output of `kici --version`, plus Node version and OS. |
|
|
978
|
+
| Why this is a discrepancy | One or two sentences ruling out the likely misreads — why the docs cannot be read to match what you observed. |
|
|
979
|
+
|
|
980
|
+
The last field is the one agents skip, and it is the one that makes a report
|
|
981
|
+
usable. "The docs say `--foo` exists and it does not" is a claim. "`--foo` is
|
|
982
|
+
documented at <url>, and `kici bar --help` on 0.1.16 lists no such flag" is a
|
|
983
|
+
finding someone can act on in one pass.
|
|
984
|
+
|
|
985
|
+
Include setup steps whenever your reproduction needed any. A reproduction that
|
|
986
|
+
starts from state a maintainer cannot recreate is not a reproduction.
|
|
987
|
+
|
|
988
|
+
## Filing it
|
|
989
|
+
|
|
990
|
+
The tracker is [kici-dev/kici-public](https://github.com/kici-dev/kici-public),
|
|
991
|
+
and the form is **Agent report**:
|
|
992
|
+
|
|
993
|
+
```bash
|
|
994
|
+
kici feedback --open
|
|
995
|
+
```
|
|
996
|
+
|
|
997
|
+
Draft the complete body first. Show it to the person you are working with —
|
|
998
|
+
the whole body, not a summary of it. File only after they say yes:
|
|
999
|
+
|
|
1000
|
+
```bash
|
|
1001
|
+
gh issue create --repo kici-dev/kici-public --template agent_report.yml
|
|
1002
|
+
```
|
|
1003
|
+
|
|
1004
|
+
The form asks you to confirm the report was drafted by an agent and reviewed by
|
|
1005
|
+
a person before filing. Answer honestly; it is what lets maintainers triage
|
|
1006
|
+
agent-filed reports as a group.
|
|
1007
|
+
|
|
1008
|
+
If they say no, that is the end of it. Do not re-file the same finding in
|
|
1009
|
+
another form, and do not open it as a question instead.
|
|
1010
|
+
|
|
1011
|
+
## See also
|
|
1012
|
+
|
|
1013
|
+
- [Getting help](https://docs.kici.dev/user/getting-help/) — the private path for a problem with your own runs
|
|
1014
|
+
- [Drive KiCI from your coding agent](https://docs.kici.dev/user/ai-agents/) — the MCP server, and the agent safety model
|
|
1015
|
+
- [Common failures](https://docs.kici.dev/user/common-failures/) — check here before concluding the docs are wrong
|
|
1016
|
+
|
|
1017
|
+
---
|
|
1018
|
+
|
|
739
1019
|
## Why KiCI
|
|
740
1020
|
|
|
741
1021
|
Source: https://docs.kici.dev/user/why-kici/
|
|
@@ -577,6 +577,181 @@ This workflow:
|
|
|
577
577
|
|
|
578
578
|
---
|
|
579
579
|
|
|
580
|
+
## Git credentials
|
|
581
|
+
|
|
582
|
+
Source: https://docs.kici.dev/user/patterns/git-credentials/
|
|
583
|
+
|
|
584
|
+
Two facts drive everything on this page, and neither is guessable:
|
|
585
|
+
|
|
586
|
+
- **Cloning your own repository needs no credential.** The framework checks it
|
|
587
|
+
out for you, and the app KiCI installs already holds read access.
|
|
588
|
+
- **Pushing always needs a credential you supply.** The KiCI app holds read
|
|
589
|
+
access only, so every push — including to the job's own repository — needs one.
|
|
590
|
+
|
|
591
|
+
## Declare credentials once, by name
|
|
592
|
+
|
|
593
|
+
Credentials are declared on the job as a named map. **Every value is the name of
|
|
594
|
+
a secret**, in `<context>:<secret-name>` form — never the credential itself:
|
|
595
|
+
|
|
596
|
+
```typescript
|
|
597
|
+
job('release', {
|
|
598
|
+
runsOn: 'linux',
|
|
599
|
+
gitCredentials: {
|
|
600
|
+
// `default` is used whenever a call names no credential
|
|
601
|
+
default: {
|
|
602
|
+
kind: 'app',
|
|
603
|
+
appIdSecret: 'ci:ACME_APP_ID',
|
|
604
|
+
installationIdSecret: 'ci:ACME_INSTALL_ID',
|
|
605
|
+
privateKeySecret: 'ci:ACME_APP_KEY',
|
|
606
|
+
},
|
|
607
|
+
forge: { kind: 'token', tokenSecret: 'ci:FORGE_PAT' },
|
|
608
|
+
vendor: { kind: 'ssh', privateKeySecret: 'ci:VENDOR_DEPLOY_KEY' },
|
|
609
|
+
},
|
|
610
|
+
steps: [build, tagAndPush],
|
|
611
|
+
});
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
Store the secrets first with `kici-admin secret set`. Pasting a private key
|
|
615
|
+
straight into the workflow is rejected when the workflow is defined, naming the
|
|
616
|
+
field — a key written into `.kici/` would be committed to your repository.
|
|
617
|
+
|
|
618
|
+
## Push
|
|
619
|
+
|
|
620
|
+
Your checkout is read-only by default. Opening a write window is explicit:
|
|
621
|
+
|
|
622
|
+
```typescript
|
|
623
|
+
step('tag', async ({ $, repo }) => {
|
|
624
|
+
await $`git tag v${version}`;
|
|
625
|
+
await repo.withWrite({ permissions: { contents: 'write' } }, async () => {
|
|
626
|
+
await $`git push origin v${version}`;
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
Inside the callback, git operations on that repository use a write credential.
|
|
632
|
+
Outside it they do not, so an accidental push elsewhere in the job fails.
|
|
633
|
+
|
|
634
|
+
Pass `credential: 'forge'` to use a named entry instead of `default`.
|
|
635
|
+
|
|
636
|
+
**KiCI never guesses the permission set.** What a push needs depends on what is
|
|
637
|
+
being pushed — changing anything under `.github/workflows/` additionally requires
|
|
638
|
+
`workflows`:
|
|
639
|
+
|
|
640
|
+
```typescript
|
|
641
|
+
await repo.withWrite({ permissions: { contents: 'write', workflows: 'write' } }, async () => {
|
|
642
|
+
await $`git push origin HEAD`;
|
|
643
|
+
});
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
If the app was not granted a permission you request, the forge refuses to issue
|
|
647
|
+
the credential at all. The error names the repository and the permissions you
|
|
648
|
+
asked for, **before any git command runs** — not at the end of a long build.
|
|
649
|
+
|
|
650
|
+
## Clone more than one repository
|
|
651
|
+
|
|
652
|
+
A workflow often needs several repositories, not just its own. Mint one token
|
|
653
|
+
that covers all of them, then clone each with it:
|
|
654
|
+
|
|
655
|
+
```typescript
|
|
656
|
+
const { token } = await kici.git.github.getToken({
|
|
657
|
+
repositories: ['acme/app', 'acme/shared-lib'],
|
|
658
|
+
permissions: { contents: 'read' },
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
for (const repo of ['acme/app', 'acme/shared-lib']) {
|
|
662
|
+
await $`git clone https://x-access-token:${token}@github.com/${repo}.git`;
|
|
663
|
+
}
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
A GitHub App token is issued per installation, so one call covers every
|
|
667
|
+
repository you name. Each repository must be inside the app's installation. If
|
|
668
|
+
one is not, the forge refuses the whole request and the error names it.
|
|
669
|
+
|
|
670
|
+
The credential helper is installed on your own checkout only, so a repository
|
|
671
|
+
you clone yourself does not inherit it. That is why this case mints a token
|
|
672
|
+
rather than relying on the helper.
|
|
673
|
+
|
|
674
|
+
## Call the forge API
|
|
675
|
+
|
|
676
|
+
`gh` does not read git credential helpers, so this is the one case that wants the
|
|
677
|
+
token as a value:
|
|
678
|
+
|
|
679
|
+
```typescript
|
|
680
|
+
const { token } = await kici.git.github.getToken({
|
|
681
|
+
repositories: ['acme/app'],
|
|
682
|
+
permissions: { contents: 'write' },
|
|
683
|
+
});
|
|
684
|
+
await $({ env: { ...process.env, GH_TOKEN: token } })`gh release create v${version}`;
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
The token is masked in step logs. Prefer `withWrite` for git itself, which never
|
|
688
|
+
places a credential in the step environment.
|
|
689
|
+
|
|
690
|
+
## Credentials that only exist at run time
|
|
691
|
+
|
|
692
|
+
A credential fetched during the run — from a vault, or a cloud secret store via
|
|
693
|
+
the job's OIDC identity — cannot be named ahead of time. Use the `*Value` half of
|
|
694
|
+
the pair, which says "this is the credential, not a name for one":
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
gitCredentials: { default: { kind: 'token', tokenValue: fetchedAtRuntime } }
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
To pass a derived credential to a **later** job, publish it with
|
|
701
|
+
`ctx.setSecretOutput()` and name it with the reserved `needs:` context — that
|
|
702
|
+
path is encrypted, scoped to the run, and deleted when the run ends:
|
|
703
|
+
|
|
704
|
+
```typescript
|
|
705
|
+
const mint = job('mint', {
|
|
706
|
+
runsOn: 'linux',
|
|
707
|
+
run: async (ctx) => {
|
|
708
|
+
const token = (await ctx.$`vault write -f auth/token/create`).stdout.trim();
|
|
709
|
+
ctx.setSecretOutput('FORGE_TOKEN', token);
|
|
710
|
+
},
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
const build = job('build', {
|
|
714
|
+
runsOn: 'linux',
|
|
715
|
+
needs: [mint],
|
|
716
|
+
gitCredentials: { default: { kind: 'token', tokenSecret: 'needs:FORGE_TOKEN' } },
|
|
717
|
+
steps: [cloneAndPush],
|
|
718
|
+
});
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
Never put a credential in a regular job output: regular outputs are not masked,
|
|
722
|
+
are stored, and are shown in the dashboard.
|
|
723
|
+
|
|
724
|
+
For a **minted app token**, prefer re-deriving over transporting — those expire
|
|
725
|
+
after an hour, so one minted in an earlier job is often already dead by the time
|
|
726
|
+
a later job reads it. Have the later job name the same secret, or mint its own.
|
|
727
|
+
|
|
728
|
+
## How it works, and why long jobs still push
|
|
729
|
+
|
|
730
|
+
An app token expires an hour after it is issued, and cannot be renewed. Rather
|
|
731
|
+
than capture one at checkout time, the agent installs a git credential helper on
|
|
732
|
+
the checkout: git asks it on every network operation, and it obtains a fresh
|
|
733
|
+
credential each time. A push at the end of a three-hour build works exactly as it
|
|
734
|
+
does at the start, and no credential is ever written into `.git/config`, into
|
|
735
|
+
`git remote -v`, or into the step's environment.
|
|
736
|
+
|
|
737
|
+
## Limits worth knowing
|
|
738
|
+
|
|
739
|
+
- **Container jobs cannot use this yet.** A container job runs git inside the
|
|
740
|
+
container, which has no route to the credential service. Bare-metal jobs are
|
|
741
|
+
unaffected.
|
|
742
|
+
- **The reserved `needs:` context is not resolvable yet** on a deployed
|
|
743
|
+
orchestrator; naming it produces a clear error rather than a wrong credential.
|
|
744
|
+
- **A write window is bounded by the repository and the callback, not the step.**
|
|
745
|
+
Steps running concurrently in the same job can push to the same repository
|
|
746
|
+
while it is open. They cannot reach a different one.
|
|
747
|
+
- **A credential you supply yourself cannot be narrowed.** A personal access
|
|
748
|
+
token or SSH key grants whatever it was created with, so a requested permission
|
|
749
|
+
set is reported as unscoped rather than pretended to be enforced.
|
|
750
|
+
- **Being allowed to push is not the same as the push succeeding.** A branch
|
|
751
|
+
protection rule or repository ruleset can still reject it.
|
|
752
|
+
|
|
753
|
+
---
|
|
754
|
+
|
|
580
755
|
## Host restart & wait-for-alive
|
|
581
756
|
|
|
582
757
|
Source: https://docs.kici.dev/user/patterns/host-restart/
|
|
@@ -939,7 +1114,7 @@ export default workflow('on-forgejo-push', {
|
|
|
939
1114
|
**Caveat — cloning:** generic webhook sources deliver only the payload; they do not carry a clone token, and KiCI's automatic pre-step clone (`packages/agent/src/checkout/git-clone.ts`) is GitHub-only today (HTTPS + `http.extraHeader` Basic auth with a GitHub installation token). Three practical patterns:
|
|
940
1115
|
|
|
941
1116
|
- **Mirror to GitHub and fan out.** Keep the repo on GitHub, register the workflow via a GitHub default-branch push, and have Gogs/Forgejo webhooks fan out via [cross-source delivery](https://docs.kici.dev/architecture/webhooks/webhook-delivery/#cross-source-delivery). The clone runs against the GitHub mirror using the GitHub App's token.
|
|
942
|
-
- **Clone yourself using a
|
|
1117
|
+
- **Clone yourself using a declared credential.** Set `checkout: false` on the job to skip the framework clone, declare the forge credential on the job as a named `gitCredentials` entry (values are **secret names**, never the credential), and run `git clone` in the first step — the agent authenticates it for you, and the credential never appears in workflow source. See [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/). This works for any forge the agent can reach, no mirror needed. You still need a way to **register** the workflow — either keep a one-file GitHub repo whose only job is to own the registration, or bootstrap the registration manually against the orchestrator DB.
|
|
943
1118
|
- **Self-contained workflow.** No clone at all. The step reads whatever it needs from `rawPayload` (e.g., `rawPayload.after`, `rawPayload.repository.clone_url`) and drives external systems — notifications, deploys, third-party CI triggers.
|
|
944
1119
|
|
|
945
1120
|
Manual-clone example (pattern 2) using an SSH deploy key:
|
|
@@ -144,38 +144,22 @@ the manifest flow — follow these steps.
|
|
|
144
144
|
|
|
145
145
|
5. **Pick permissions.** Minimum required:
|
|
146
146
|
|
|
147
|
-
| Scope | Access | Why
|
|
148
|
-
| --------------------------- | ------------ |
|
|
149
|
-
| Repository -> Contents | Read | Clone the repo to read the lock file
|
|
150
|
-
| Repository -> Metadata | Read (auto) | Default for every App
|
|
151
|
-
| Repository -> Pull requests | Read | Match `pull_request` triggers
|
|
152
|
-
| Repository -> Checks | Read & write | Post KiCI's enriched Check runs
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
on an org-level install — see the event note below.
|
|
147
|
+
| Scope | Access | Why |
|
|
148
|
+
| --------------------------- | ------------ | ------------------------------------ |
|
|
149
|
+
| Repository -> Contents | Read | Clone the repo to read the lock file |
|
|
150
|
+
| Repository -> Metadata | Read (auto) | Default for every App |
|
|
151
|
+
| Repository -> Pull requests | Read | Match `pull_request` triggers |
|
|
152
|
+
| Repository -> Checks | Read & write | Post KiCI's enriched Check runs |
|
|
153
|
+
|
|
154
|
+
Those four cover the whole flow: clone, trigger matching, Check runs.
|
|
155
|
+
[CI trust](https://docs.kici.dev/architecture/security/ci-security/) needs no
|
|
156
|
+
permission of its own — it reads the fork relationship straight out of
|
|
157
|
+
the webhook payload and calls no GitHub API.
|
|
159
158
|
|
|
160
159
|
6. **Subscribe to events.** At minimum: `push`, `pull_request`,
|
|
161
160
|
`check_run`, `check_suite`. Add others (`issues`, `release`, ...) if
|
|
162
161
|
your workflows use those triggers.
|
|
163
162
|
|
|
164
|
-
**For CI trust (optional but recommended on org installs):** also
|
|
165
|
-
subscribe to `member`, `organization`, `membership`, and `team`.
|
|
166
|
-
KiCI caches each pull-request author's repository access level (used
|
|
167
|
-
to decide whether workflow changes take effect immediately or are
|
|
168
|
-
held for approval — see
|
|
169
|
-
[CI security](https://docs.kici.dev/architecture/security/ci-security/)). These
|
|
170
|
-
events let the orchestrator drop stale cache entries the moment a
|
|
171
|
-
contributor's access changes. They are not required for correctness:
|
|
172
|
-
without them the cache simply ages out on its own 15-minute TTL, so a
|
|
173
|
-
permission change can take up to 15 minutes to take effect. The
|
|
174
|
-
`organization` / `membership` / `team` events require the
|
|
175
|
-
**Organization -> Members** read permission and an org-level
|
|
176
|
-
installation; `member` is a repository event covered by the default
|
|
177
|
-
Metadata permission.
|
|
178
|
-
|
|
179
163
|
7. **Generate a private key.** Scroll to the bottom of the App settings
|
|
180
164
|
and click _Generate a private key_. A `.pem` file downloads —
|
|
181
165
|
store it safely; you cannot redownload it.
|