@intentius/behold 0.15.0 → 0.17.0
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/AGENTS.md +50 -5
- package/README.md +34 -2
- package/dist/cli.js +1214 -654
- package/example-argo-estate/app-a/package.json +2 -2
- package/example-argo-estate/app-b/package.json +2 -2
- package/example-argo-estate/control-plane/package.json +2 -2
- package/example-argo-estate/package-lock.json +64 -156
- package/example-carve/app/package-lock.json +9 -9
- package/example-carve/app/package.json +2 -2
- package/example-flux-estate/app-a/package.json +2 -2
- package/example-flux-estate/app-b/package.json +2 -2
- package/example-flux-estate/control-plane/package.json +2 -2
- package/example-flux-estate/package-lock.json +64 -156
- package/example-k8s/package-lock.json +27 -27
- package/example-k8s/package.json +3 -3
- package/example-writes/package-lock.json +14 -14
- package/example-writes/package.json +3 -3
- package/package.json +3 -3
- package/web/app.js +137 -11
package/AGENTS.md
CHANGED
|
@@ -171,6 +171,49 @@ and nothing else about the run is behold's to decide: a stream that dies leaves
|
|
|
171
171
|
the playhead at the last settled step and says so, and a gate paints as pending
|
|
172
172
|
only when chant's `gateState` query named it.
|
|
173
173
|
|
|
174
|
+
### The executor contract (#165, #61)
|
|
175
|
+
|
|
176
|
+
`.behold.json` may designate which forge deploys an environment:
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{ "executor": { "prod": { "forge": "github", "workflow": "deploy-prod.yml" } } }
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
It designates the committed WORKFLOW, not just the forge: two environments'
|
|
183
|
+
generated pipelines carry identical job ids, so a picker cannot tell them
|
|
184
|
+
apart, and a contract that names prod must not sit on a guess. For a
|
|
185
|
+
designated env, `POST /api/apply` and a committed ApplyOp's `/api/ops/:name/run`
|
|
186
|
+
answer `409 {code: "executor-forge"}`, auto-sync declines out loud, and the
|
|
187
|
+
only deploy is `POST /api/ci/dispatch?env=<env>`, which runs the designated
|
|
188
|
+
workflow through the operator's own `gh` and follows it on the dial. Any
|
|
189
|
+
approval the workflow's environment requires is granted on the forge by a
|
|
190
|
+
GitHub identity behold does not have; the dial links the run's page and offers
|
|
191
|
+
nothing else. Fail-closed: a designation behold cannot honour (a typo'd forge,
|
|
192
|
+
a missing or non-dispatchable workflow, a forge with no trigger here) disables
|
|
193
|
+
Deploy for that env with the reason on `/api/project`'s `executor` block, and
|
|
194
|
+
never falls back to running it here. `/api/project` reports `{forge, workflow,
|
|
195
|
+
ok, reason?}` per designated env.
|
|
196
|
+
|
|
197
|
+
Without a designation, dispatch picks the committed workflow named for the env
|
|
198
|
+
(`chant-components-<env>`, chant ≥ 0.54.0); on the older job-overlap match it
|
|
199
|
+
refuses a tie rather than letting directory order choose, and a workflow named
|
|
200
|
+
for another env never stands in. `just e2e-ci-github` proves the contract
|
|
201
|
+
against the real forge (example-ci + `.github/workflows/behold-e2e-dispatch.yml`),
|
|
202
|
+
including the `lost` verdict, which `BEHOLD_CI_FOLLOW_TIMEOUT_MS` and
|
|
203
|
+
`BEHOLD_CI_POLL_FAIL_BUDGET` let a run force on purpose; a lost run is the one
|
|
204
|
+
`POST /api/ci/readopt` re-follows.
|
|
205
|
+
|
|
206
|
+
A dispatched run is followed honestly (#165 §6, PR #350): only GitHub's own
|
|
207
|
+
`completed` + conclusion paints `ok`/`failed`; a poll-failure budget or the
|
|
208
|
+
follow deadline promotes the run to `lost` (chips frozen at last-observed,
|
|
209
|
+
the run possibly still live at its own page), never to a verdict. The adopted
|
|
210
|
+
run id is persisted as one JSON per project under `~/.behold/ci-runs/` — the
|
|
211
|
+
operator's machine-state, outside the project tree, so the Invariant below
|
|
212
|
+
still names the whole in-project write surface. `GET /api/ci/run` reads the
|
|
213
|
+
record; `POST /api/ci/readopt` (also attempted once at boot) re-follows an
|
|
214
|
+
unconcluded run by its saved id, so a restart mid-deploy leaves the run a
|
|
215
|
+
reader instead of nothing.
|
|
216
|
+
|
|
174
217
|
## The operating loop (a strip, a timeline, and a gate that is not the run gate)
|
|
175
218
|
|
|
176
219
|
A project that declares a `ConvergeOp` gets an operator strip on the ops lens:
|
|
@@ -277,11 +320,13 @@ live here, with the enforceable ones enforced.
|
|
|
277
320
|
it merges. A check that has merely settled is not a pass — read the lines.
|
|
278
321
|
No `gh pr merge --auto`; merge one PR at a time, in order, and rebase the
|
|
279
322
|
next onto what landed.
|
|
280
|
-
- **The local gate** is `just check` (tsc, tests, build).
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
323
|
+
- **The local gate** is `just check` (tsc, tests, build). Every vitest run
|
|
324
|
+
also writes `.vitest-last.json` (the json reporter, PR #351), and `just
|
|
325
|
+
test` keeps the reporter's full output in `vitest.log` — both gitignored —
|
|
326
|
+
because #334's one-shot first-run failures kept losing the failing file's
|
|
327
|
+
name. If the suite fails once and passes on rerun, those two files from the
|
|
328
|
+
first run are the evidence; attach them to #334 (`jq '.testResults[] |
|
|
329
|
+
select(.status != "passed") | .name' .vitest-last.json` names the file).
|
|
285
330
|
- **Releasing** is `just release`, after the version-bump PR merged: it tags
|
|
286
331
|
`behold-v<version>`, pushes the tag (which is what runs `release.yml`), and
|
|
287
332
|
waits for npm to show the version. It refuses in every state where a tag
|
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@ drift — then act through delegated, gated Ops.
|
|
|
8
8
|
gets you to a running graph without reading anything else first.
|
|
9
9
|
|
|
10
10
|
Where Argo CD shows one cluster's tree, behold shows the mixed-substrate estate:
|
|
11
|
-
cloud drift on AWS, supply-chain drift on GitHub Actions, artifact presence
|
|
12
|
-
each substrate's own kind of truth, in one picture.
|
|
11
|
+
cloud drift on AWS, supply-chain drift on GitHub Actions, artifact presence and
|
|
12
|
+
render provenance on Helm — each substrate's own kind of truth, in one picture.
|
|
13
13
|
|
|
14
14
|
```
|
|
15
15
|
chant source ──build/lint──▶ graph IR ──behold──▶ live graph + drift + (delegated) actions
|
|
@@ -354,6 +354,38 @@ render and the graph loads with no tier selected — the default for any project
|
|
|
354
354
|
that doesn't opt in. There's no other tier config surface (not
|
|
355
355
|
`chant.config.ts`, not an env var behold guesses the name of).
|
|
356
356
|
|
|
357
|
+
### Deploy executors — `executor`
|
|
358
|
+
|
|
359
|
+
The same file can designate which forge deploys an environment (#165):
|
|
360
|
+
|
|
361
|
+
```json
|
|
362
|
+
{
|
|
363
|
+
"executor": {
|
|
364
|
+
"prod": { "forge": "github", "workflow": "deploy-prod.yml" }
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
It names the committed **workflow**, not just the forge, because two
|
|
370
|
+
environments' generated pipelines carry identical job ids and a picker cannot
|
|
371
|
+
tell them apart. For a designated environment the Deploy button dispatches that
|
|
372
|
+
workflow through your own `gh` login and follows the run on the dial; a local
|
|
373
|
+
apply, a committed ApplyOp for that environment, and auto-sync are all refused
|
|
374
|
+
(`409 executor-forge`), and rollback is withheld. Any approval the workflow's
|
|
375
|
+
GitHub environment requires is granted on GitHub, by your identity there — the
|
|
376
|
+
dial links the run's page and offers nothing else, because behold holds no
|
|
377
|
+
identity that could clear a forge gate. A designation behold cannot honour (a
|
|
378
|
+
typo'd forge, a missing workflow, one without `workflow_dispatch`) disables
|
|
379
|
+
Deploy for that environment with the reason, and never falls back to running
|
|
380
|
+
it on your machine. The workflow is read from the `.github/workflows` of the
|
|
381
|
+
repository the project belongs to, so a project that is one directory of a
|
|
382
|
+
monorepo works as-is.
|
|
383
|
+
|
|
384
|
+
A dispatched run's id is kept under `~/.behold/ci-runs/` — the operator's own
|
|
385
|
+
state, outside the project — so a behold restarted mid-deploy re-adopts the run
|
|
386
|
+
and keeps following it. A follow whose stream dies is reported as `lost`, never
|
|
387
|
+
as a verdict; `just e2e-ci-github` proves the whole contract against GitHub.
|
|
388
|
+
|
|
357
389
|
### The hand-layout sidecar — `.behold/layout.json`
|
|
358
390
|
|
|
359
391
|
dagre places your nodes; you can move them. Drag a card, resize a containment
|