@intentius/behold 0.13.0 → 0.14.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 CHANGED
@@ -164,13 +164,35 @@ and nothing else about the run is behold's to decide: a stream that dies leaves
164
164
  the playhead at the last settled step and says so, and a gate paints as pending
165
165
  only when chant's `gateState` query named it.
166
166
 
167
- ## The operating loop (a strip, and a gate that is not the run gate)
167
+ ## The operating loop (a strip, a timeline, and a gate that is not the run gate)
168
168
 
169
169
  A project that declares a `ConvergeOp` gets an operator strip on the ops lens:
170
170
  per loop, the last tick's own log line (verbatim, with its instant), the lease,
171
171
  and how many gates are pending. **One** tick — `chant operator status` keeps only
172
- `records.at(-1)` and no CLI exposes the history (chant#2029), so this is a strip
173
- and never a timeline; the statusbar says so rather than leaving you to assume.
172
+ `records.at(-1)` — so the strip is never a timeline, and it says so.
173
+
174
+ The timeline is its own read: `GET /api/operator/log` → `chant operator log
175
+ --json` (chant#2029), the tick records and the gate resolutions against them
176
+ merged oldest-first. It lives in a panel that grows from the strip, and two rules
177
+ hold it there. It is **pulled**, on the click that opens it and never on a timer.
178
+ And it is **bounded** — `--limit` on every invocation, 50 by default and 200 at
179
+ most, `--since` when asked — because the ledger grows one line per tick forever;
180
+ the answer reports the window it used, so a full one can't read as the end of
181
+ history. The route checks the project's chant version *before* it spawns: below
182
+ 0.53.1, `chant operator log` resolves to `chant operator`, the tick daemon, and
183
+ behold reading a history must never become behold running an operator.
184
+
185
+ Since chant 0.53.1 (chant#2027) a tick record carries an `id` and the
186
+ per-component verdicts it derived, and both ride through to
187
+ `[].lastTick.{id,components}`. The strip line names the tick (truncated), and
188
+ the verdicts join onto the component DAG by component name — the same key the
189
+ live `chant components status` read is joined by. They join **under** that read:
190
+ a tick only ever feeds the last tier of `componentStatusColor` (the
191
+ reconciliation verdict), only on a node the live read left unpainted, and only
192
+ while the tick is younger than fifteen of chant's own operator rounds. Past
193
+ that it is named on the node, dated, and painted nothing — a graph fill has
194
+ nowhere to put "as of an hour ago". A chant older than 0.53.1 sends neither
195
+ field and every one of these paths is a no-op.
174
196
 
175
197
  Two gate cards exist and they are **different acts**:
176
198
 
@@ -182,10 +204,16 @@ Two gate cards exist and they are **different acts**:
182
204
  resolution or not. The next tick reads the fact. The card says this in its
183
205
  body, and the toast after the click says "recorded; the next tick acts on it".
184
206
 
185
- A pending gate fact carries no URL (chant#2028), so the card renders no link and
186
- no placeholder for one. A gate someone already resolved simply leaves
187
- `pendingGates` — the status read carries no `resolvedBy`/`when` — so behold shows
188
- no resolved-by line rather than attributing an approval to nobody.
207
+ A gate fact carries its address since chant#2028, on both halves, and the card
208
+ links it under chant's own words — `approve at: <url>`. The field is optional by
209
+ design (a local tick with no PR behind it has none) and never synthesized, so a
210
+ fact without one renders no link and no placeholder for one, and a url behold
211
+ would not put behind an `href` reads as no address at all.
212
+
213
+ A gate someone already resolved simply leaves `pendingGates` — the status read
214
+ carries no `resolvedBy`/`when` — so the strip shows no resolved-by line rather
215
+ than attributing an approval to nobody. The timeline is where resolutions are
216
+ named, because there they are records rather than an inference.
189
217
 
190
218
  An `OperatorStack` (chant#1940) declares the loop as a k8s estate, so it already
191
219
  appears in the entity graph. behold names it there — the Namespace as the loop's