@intentius/behold 0.13.1 → 0.15.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 +78 -7
- package/dist/cli.js +2310 -1874
- 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 +144 -52
- 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 +144 -52
- package/example-k8s/package-lock.json +18 -18
- 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 +124 -5
- package/web/index.html +24 -2
- package/web/operator.js +247 -14
- package/web/operator.test.js +188 -4
- package/web/release.js +66 -0
- package/web/release.test.js +52 -0
package/AGENTS.md
CHANGED
|
@@ -54,6 +54,13 @@ preview-locked, and one load runs at a time (409 otherwise).
|
|
|
54
54
|
per-node observed state, drift and field ownership; `/api/reconcile?env=`
|
|
55
55
|
summarizes the pending change set; `/api/substrates` reports substrate
|
|
56
56
|
readiness; `/api/events` (SSE) pushes `changed`/`op`/`apply`/`run`/`pr`.
|
|
57
|
+
With `?components=1&env=`, each component node carries `_liveStatus` (the
|
|
58
|
+
`chant components status` verdict) and, when the release ledger recorded
|
|
59
|
+
one, `_release` — `{runId, forge, originSource, url?, gitSha, digest,
|
|
60
|
+
timestamp, actor, approver?}` (#165). `url` is present only when the record
|
|
61
|
+
itself carries an address (chant#2045); `originSource: "inferred"` means
|
|
62
|
+
behold read the id's spelling and nothing more, and a `forge: "unknown"` id
|
|
63
|
+
is never resolved to a link on behold's guess.
|
|
57
64
|
`?ops=1` is the ops lens — the project's declared Ops as a phase track, read
|
|
58
65
|
from each emitted `dist/ops/<name>/op.json`, with the current run painted
|
|
59
66
|
over it (`meta.run`, `meta.gate`); `/api/ops/<name>/status` reads that Op's
|
|
@@ -164,13 +171,35 @@ and nothing else about the run is behold's to decide: a stream that dies leaves
|
|
|
164
171
|
the playhead at the last settled step and says so, and a gate paints as pending
|
|
165
172
|
only when chant's `gateState` query named it.
|
|
166
173
|
|
|
167
|
-
## The operating loop (a strip, and a gate that is not the run gate)
|
|
174
|
+
## The operating loop (a strip, a timeline, and a gate that is not the run gate)
|
|
168
175
|
|
|
169
176
|
A project that declares a `ConvergeOp` gets an operator strip on the ops lens:
|
|
170
177
|
per loop, the last tick's own log line (verbatim, with its instant), the lease,
|
|
171
178
|
and how many gates are pending. **One** tick — `chant operator status` keeps only
|
|
172
|
-
`records.at(-1)`
|
|
173
|
-
|
|
179
|
+
`records.at(-1)` — so the strip is never a timeline, and it says so.
|
|
180
|
+
|
|
181
|
+
The timeline is its own read: `GET /api/operator/log` → `chant operator log
|
|
182
|
+
--json` (chant#2029), the tick records and the gate resolutions against them
|
|
183
|
+
merged oldest-first. It lives in a panel that grows from the strip, and two rules
|
|
184
|
+
hold it there. It is **pulled**, on the click that opens it and never on a timer.
|
|
185
|
+
And it is **bounded** — `--limit` on every invocation, 50 by default and 200 at
|
|
186
|
+
most, `--since` when asked — because the ledger grows one line per tick forever;
|
|
187
|
+
the answer reports the window it used, so a full one can't read as the end of
|
|
188
|
+
history. The route checks the project's chant version *before* it spawns: below
|
|
189
|
+
0.53.1, `chant operator log` resolves to `chant operator`, the tick daemon, and
|
|
190
|
+
behold reading a history must never become behold running an operator.
|
|
191
|
+
|
|
192
|
+
Since chant 0.53.1 (chant#2027) a tick record carries an `id` and the
|
|
193
|
+
per-component verdicts it derived, and both ride through to
|
|
194
|
+
`[].lastTick.{id,components}`. The strip line names the tick (truncated), and
|
|
195
|
+
the verdicts join onto the component DAG by component name — the same key the
|
|
196
|
+
live `chant components status` read is joined by. They join **under** that read:
|
|
197
|
+
a tick only ever feeds the last tier of `componentStatusColor` (the
|
|
198
|
+
reconciliation verdict), only on a node the live read left unpainted, and only
|
|
199
|
+
while the tick is younger than fifteen of chant's own operator rounds. Past
|
|
200
|
+
that it is named on the node, dated, and painted nothing — a graph fill has
|
|
201
|
+
nowhere to put "as of an hour ago". A chant older than 0.53.1 sends neither
|
|
202
|
+
field and every one of these paths is a no-op.
|
|
174
203
|
|
|
175
204
|
Two gate cards exist and they are **different acts**:
|
|
176
205
|
|
|
@@ -182,10 +211,16 @@ Two gate cards exist and they are **different acts**:
|
|
|
182
211
|
resolution or not. The next tick reads the fact. The card says this in its
|
|
183
212
|
body, and the toast after the click says "recorded; the next tick acts on it".
|
|
184
213
|
|
|
185
|
-
A
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
no
|
|
214
|
+
A gate fact carries its address since chant#2028, on both halves, and the card
|
|
215
|
+
links it under chant's own words — `approve at: <url>`. The field is optional by
|
|
216
|
+
design (a local tick with no PR behind it has none) and never synthesized, so a
|
|
217
|
+
fact without one renders no link and no placeholder for one, and a url behold
|
|
218
|
+
would not put behind an `href` reads as no address at all.
|
|
219
|
+
|
|
220
|
+
A gate someone already resolved simply leaves `pendingGates` — the status read
|
|
221
|
+
carries no `resolvedBy`/`when` — so the strip shows no resolved-by line rather
|
|
222
|
+
than attributing an approval to nobody. The timeline is where resolutions are
|
|
223
|
+
named, because there they are records rather than an inference.
|
|
189
224
|
|
|
190
225
|
An `OperatorStack` (chant#1940) declares the loop as a k8s estate, so it already
|
|
191
226
|
appears in the entity graph. behold names it there — the Namespace as the loop's
|
|
@@ -229,3 +264,39 @@ own Terraform is not edited either. The only request-derived value is `select`,
|
|
|
229
264
|
and it must be an address the served report already ranks — the value that
|
|
230
265
|
reaches the spawn's argv comes from a closed set read off disk. No cloud write,
|
|
231
266
|
no Terraform mutation, no edit to anyone's chant source.
|
|
267
|
+
|
|
268
|
+
## Changing behold (for agents working on this repo)
|
|
269
|
+
|
|
270
|
+
The sections above are about driving a running behold. This one is about
|
|
271
|
+
changing it — the working rules that used to live in a handoff note and now
|
|
272
|
+
live here, with the enforceable ones enforced.
|
|
273
|
+
|
|
274
|
+
- **Branches and merges.** Work on a branch off `main` (an isolated worktree
|
|
275
|
+
when more than one agent is active). `main` is protected by a ruleset: every
|
|
276
|
+
change arrives as a PR, and the `check` job in `ci.yml` must be green before
|
|
277
|
+
it merges. A check that has merely settled is not a pass — read the lines.
|
|
278
|
+
No `gh pr merge --auto`; merge one PR at a time, in order, and rebase the
|
|
279
|
+
next onto what landed.
|
|
280
|
+
- **The local gate** is `just check` (tsc, tests, build). `just test` keeps
|
|
281
|
+
the reporter's full output in `vitest.log`, because #334's one-shot
|
|
282
|
+
first-run failures kept losing the failing file's name — if the suite fails
|
|
283
|
+
once and passes on rerun, the log from the first run is the evidence; attach
|
|
284
|
+
it to #334.
|
|
285
|
+
- **Releasing** is `just release`, after the version-bump PR merged: it tags
|
|
286
|
+
`behold-v<version>`, pushes the tag (which is what runs `release.yml`), and
|
|
287
|
+
waits for npm to show the version. It refuses in every state where a tag
|
|
288
|
+
push would be wrong. Never re-push a `behold-v*` tag by hand — a tag push
|
|
289
|
+
re-fires publish. Tags absent from origin (behold-v0.10.0, 0.10.1) stay
|
|
290
|
+
absent for that reason.
|
|
291
|
+
- **Scratch infrastructure** is governed by `src/scratch.ts`, asserted by
|
|
292
|
+
`scratch.test.ts` across every boot site: anything behold boots is named
|
|
293
|
+
`behold-*`, refuses if the name is taken, tears down only what it created,
|
|
294
|
+
and never binds the shared emulator ports. The protected names — `floci*`,
|
|
295
|
+
`chant-floci*`, the kubemicrovm and fountain k3d clusters, :4566 — are
|
|
296
|
+
listed there, not in prose. A new boot site calls `assertScratch` before
|
|
297
|
+
its spawn and gets a row in the test.
|
|
298
|
+
- **The write boundary** is the Invariant section above. Apply is never a
|
|
299
|
+
button; `/api/carve/apply` does not exist and the route test asserts it
|
|
300
|
+
stays that way.
|
|
301
|
+
- **chant's working rules** (its single-lane checkout, its release path) are
|
|
302
|
+
chant's and live in chant's repo, not here.
|