@intentius/behold 0.11.0 → 0.13.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 +76 -1
- package/dist/cli.js +2708 -720
- 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 +100 -124
- package/example-carve/README.md +26 -5
- package/example-carve/app/package-lock.json +10 -10
- 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 +100 -124
- package/example-k8s/package-lock.json +101 -125
- package/example-k8s/package.json +3 -3
- package/example-writes/package-lock.json +16 -16
- package/example-writes/package.json +3 -3
- package/package.json +3 -3
- package/web/app.js +614 -22
- package/web/carve-steps.js +79 -0
- package/web/carve-steps.test.js +67 -0
- package/web/index.html +61 -0
- package/web/operator.js +236 -0
- package/web/operator.test.js +158 -0
- package/web/run-playhead.js +194 -0
- package/web/run-playhead.test.js +134 -0
- package/web/theme.test.js +35 -0
package/AGENTS.md
CHANGED
|
@@ -53,7 +53,20 @@ preview-locked, and one load runs at a time (409 otherwise).
|
|
|
53
53
|
`?env=`, `/api/overlay` is the live entity overlay; `/api/diff?env=` slices
|
|
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
|
-
readiness; `/api/events` (SSE) pushes `changed`/`op`/`apply`/`pr`.
|
|
56
|
+
readiness; `/api/events` (SSE) pushes `changed`/`op`/`apply`/`run`/`pr`.
|
|
57
|
+
`?ops=1` is the ops lens — the project's declared Ops as a phase track, read
|
|
58
|
+
from each emitted `dist/ops/<name>/op.json`, with the current run painted
|
|
59
|
+
over it (`meta.run`, `meta.gate`); `/api/ops/<name>/status` reads that Op's
|
|
60
|
+
durable run status and pending gate (`chant run status --temporal`). A
|
|
61
|
+
`ConvergeOp` also gets one card per rule from its `convergeTick` step's
|
|
62
|
+
`args.rules` (`attrs._step: "rule"`), carrying `when` (chant's JSON predicate,
|
|
63
|
+
rendered as the condition it states), `then`, and the `why` chant requires of
|
|
64
|
+
every rule, verbatim. `then: run(<op>)` is an edge to that Op's first step
|
|
65
|
+
when the Op is in the rendered set, and `attrs.dangling` when it isn't.
|
|
66
|
+
`meta.operator` on that same lens names the ConvergeOps the project declares
|
|
67
|
+
(chant's own `searchAttributes.Converge === "true"`, read from op.json — no
|
|
68
|
+
subprocess), and `/api/operator/status` fills the strip in from
|
|
69
|
+
`chant operator status --json`.
|
|
57
70
|
2. **focus** — narrow with chant graph options as query params: `?detail=0..3`,
|
|
58
71
|
`?components=1`, `?logical=1`, `?lens=blast:<id>&down=1`, `?lens=lexicon:aws`,
|
|
59
72
|
`?env=`, `?stack=`, `?tier=`, `?target=`.
|
|
@@ -74,6 +87,32 @@ To move a resource: confirm its band on `/api/carve`, then run chant's own
|
|
|
74
87
|
applying the generated survivor rewrites stay a human gate — behold has no
|
|
75
88
|
endpoint that writes Terraform, and adding one would break the invariant below.
|
|
76
89
|
|
|
90
|
+
### Carve state, from chant's manifests (#230 M3)
|
|
91
|
+
|
|
92
|
+
chant ≥ 0.52.2 writes `<address>.carve.json` into `carve emit --output`; `carve
|
|
93
|
+
bridge` and `carve apply` add their own records to the same file. behold reads
|
|
94
|
+
those and never writes one, so the progression is on disk rather than in a
|
|
95
|
+
session.
|
|
96
|
+
|
|
97
|
+
`GET /api/project`'s `carve.state` publishes it: `{manifests, progress:
|
|
98
|
+
{applied, bridged, emitted, inFlight, total, label, detail}, states[], apply:
|
|
99
|
+
{human, note}}`. Each entry carries `target`, `stage`
|
|
100
|
+
(`emitted`/`bridged`/`applied`), `graduated`, `note` and a retypeable
|
|
101
|
+
`applyCommand`. The same field appears on an ordinary `behold serve` whose
|
|
102
|
+
project directory carries a carveout — no report and no demo needed — and is
|
|
103
|
+
absent entirely when nothing has been carved.
|
|
104
|
+
|
|
105
|
+
In the graph, an `applied` address draws inside the chant member box (keeping
|
|
106
|
+
its Terraform address as its node id) instead of in a band; `emitted` and
|
|
107
|
+
`bridged` stay banded with `attrs._status: "accent"` and the stage in
|
|
108
|
+
`attrs.carve`. Only `applied` means ownership moved.
|
|
109
|
+
|
|
110
|
+
**There is no `/api/carve/apply`.** `chant carve apply` graduates ownership;
|
|
111
|
+
behold renders what the manifest records and echoes the command. Do not add the
|
|
112
|
+
endpoint — src/carve-manifest.ts `APPLY_IS_HUMAN` is the statement of it, and
|
|
113
|
+
src/carve-actions.ts and src/server.ts both carry the refusal where the route
|
|
114
|
+
would go.
|
|
115
|
+
|
|
77
116
|
### The walkthrough (`behold demo carve`, #254)
|
|
78
117
|
|
|
79
118
|
`behold demo carve` copies a bundled half-migrated estate (a chant project
|
|
@@ -117,6 +156,42 @@ behold does not apply. To change the estate:
|
|
|
117
156
|
Every mutation is a gated, durable Temporal workflow with a human-confirmable gate
|
|
118
157
|
and saga rollback. There is no behold endpoint that mutates the cloud.
|
|
119
158
|
|
|
159
|
+
A run behold triggered is asked for structured per-step records (chant#1676:
|
|
160
|
+
`--progress-json` on the durable path, `--json` on the local one), so the ops
|
|
161
|
+
lens paints the run over the declared track and a pending gate renders as a card
|
|
162
|
+
with an Approve button. That button is `op-signal` — the same delegated write —
|
|
163
|
+
and nothing else about the run is behold's to decide: a stream that dies leaves
|
|
164
|
+
the playhead at the last settled step and says so, and a gate paints as pending
|
|
165
|
+
only when chant's `gateState` query named it.
|
|
166
|
+
|
|
167
|
+
## The operating loop (a strip, and a gate that is not the run gate)
|
|
168
|
+
|
|
169
|
+
A project that declares a `ConvergeOp` gets an operator strip on the ops lens:
|
|
170
|
+
per loop, the last tick's own log line (verbatim, with its instant), the lease,
|
|
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.
|
|
174
|
+
|
|
175
|
+
Two gate cards exist and they are **different acts**:
|
|
176
|
+
|
|
177
|
+
- The **run gate** — `POST /api/ops/:name/signal/:gate` → `chant run signal`.
|
|
178
|
+
Releases the waiting Temporal workflow.
|
|
179
|
+
- The **converge gate** — `POST /api/operator/approve/:op/:gate` →
|
|
180
|
+
`chant approve <op> <gate>`. **Records a fact and unblocks nothing.** chant's
|
|
181
|
+
gate ledger says it outright: the local executor still refuses a gated op,
|
|
182
|
+
resolution or not. The next tick reads the fact. The card says this in its
|
|
183
|
+
body, and the toast after the click says "recorded; the next tick acts on it".
|
|
184
|
+
|
|
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.
|
|
189
|
+
|
|
190
|
+
An `OperatorStack` (chant#1940) declares the loop as a k8s estate, so it already
|
|
191
|
+
appears in the entity graph. behold names it there — the Namespace as the loop's
|
|
192
|
+
home, each CronJob as a converge tick — off chant's own
|
|
193
|
+
`app.kubernetes.io/component: converge-tick` labels, never a naming convention.
|
|
194
|
+
|
|
120
195
|
## Invariant
|
|
121
196
|
|
|
122
197
|
If a request would have behold write to a cloud or to source directly, it's wrong.
|